CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • Curl
  • Stream
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * Redistributions of files must retain the above copyright notice.
  8:  *
  9:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 10:  * @link          https://cakephp.org CakePHP(tm) Project
 11:  * @since         3.0.0
 12:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 13:  */
 14: namespace Cake\Http\Client\Adapter;
 15: 
 16: use Cake\Core\Exception\Exception;
 17: use Cake\Http\Client\AdapterInterface;
 18: use Cake\Http\Client\Request;
 19: use Cake\Http\Client\Response;
 20: use Cake\Http\Exception\HttpException;
 21: 
 22: /**
 23:  * Implements sending Cake\Http\Client\Request
 24:  * via php's stream API.
 25:  *
 26:  * This approach and implementation is partly inspired by Aura.Http
 27:  */
 28: class Stream implements AdapterInterface
 29: {
 30:     /**
 31:      * Context resource used by the stream API.
 32:      *
 33:      * @var resource|null
 34:      */
 35:     protected $_context;
 36: 
 37:     /**
 38:      * Array of options/content for the HTTP stream context.
 39:      *
 40:      * @var array
 41:      */
 42:     protected $_contextOptions;
 43: 
 44:     /**
 45:      * Array of options/content for the SSL stream context.
 46:      *
 47:      * @var array
 48:      */
 49:     protected $_sslContextOptions;
 50: 
 51:     /**
 52:      * The stream resource.
 53:      *
 54:      * @var resource|null
 55:      */
 56:     protected $_stream;
 57: 
 58:     /**
 59:      * Connection error list.
 60:      *
 61:      * @var array
 62:      */
 63:     protected $_connectionErrors = [];
 64: 
 65:     /**
 66:      * {@inheritDoc}
 67:      */
 68:     public function send(Request $request, array $options)
 69:     {
 70:         $this->_stream = null;
 71:         $this->_context = null;
 72:         $this->_contextOptions = [];
 73:         $this->_sslContextOptions = [];
 74:         $this->_connectionErrors = [];
 75: 
 76:         $this->_buildContext($request, $options);
 77: 
 78:         return $this->_send($request);
 79:     }
 80: 
 81:     /**
 82:      * Create the response list based on the headers & content
 83:      *
 84:      * Creates one or many response objects based on the number
 85:      * of redirects that occurred.
 86:      *
 87:      * @param array $headers The list of headers from the request(s)
 88:      * @param string $content The response content.
 89:      * @return \Cake\Http\Client\Response[] The list of responses from the request(s)
 90:      */
 91:     public function createResponses($headers, $content)
 92:     {
 93:         $indexes = $responses = [];
 94:         foreach ($headers as $i => $header) {
 95:             if (strtoupper(substr($header, 0, 5)) === 'HTTP/') {
 96:                 $indexes[] = $i;
 97:             }
 98:         }
 99:         $last = count($indexes) - 1;
100:         foreach ($indexes as $i => $start) {
101:             $end = isset($indexes[$i + 1]) ? $indexes[$i + 1] - $start : null;
102:             $headerSlice = array_slice($headers, $start, $end);
103:             $body = $i == $last ? $content : '';
104:             $responses[] = $this->_buildResponse($headerSlice, $body);
105:         }
106: 
107:         return $responses;
108:     }
109: 
110:     /**
111:      * Build the stream context out of the request object.
112:      *
113:      * @param \Cake\Http\Client\Request $request The request to build context from.
114:      * @param array $options Additional request options.
115:      * @return void
116:      */
117:     protected function _buildContext(Request $request, $options)
118:     {
119:         $this->_buildContent($request, $options);
120:         $this->_buildHeaders($request, $options);
121:         $this->_buildOptions($request, $options);
122: 
123:         $url = $request->getUri();
124:         $scheme = parse_url($url, PHP_URL_SCHEME);
125:         if ($scheme === 'https') {
126:             $this->_buildSslContext($request, $options);
127:         }
128:         $this->_context = stream_context_create([
129:             'http' => $this->_contextOptions,
130:             'ssl' => $this->_sslContextOptions,
131:         ]);
132:     }
133: 
134:     /**
135:      * Build the header context for the request.
136:      *
137:      * Creates cookies & headers.
138:      *
139:      * @param \Cake\Http\Client\Request $request The request being sent.
140:      * @param array $options Array of options to use.
141:      * @return void
142:      */
143:     protected function _buildHeaders(Request $request, $options)
144:     {
145:         $headers = [];
146:         foreach ($request->getHeaders() as $name => $values) {
147:             $headers[] = sprintf('%s: %s', $name, implode(', ', $values));
148:         }
149:         $this->_contextOptions['header'] = implode("\r\n", $headers);
150:     }
151: 
152:     /**
153:      * Builds the request content based on the request object.
154:      *
155:      * If the $request->body() is a string, it will be used as is.
156:      * Array data will be processed with Cake\Http\Client\FormData
157:      *
158:      * @param \Cake\Http\Client\Request $request The request being sent.
159:      * @param array $options Array of options to use.
160:      * @return void
161:      */
162:     protected function _buildContent(Request $request, $options)
163:     {
164:         $body = $request->getBody();
165:         if (empty($body)) {
166:             $this->_contextOptions['content'] = '';
167: 
168:             return;
169:         }
170:         $body->rewind();
171:         $this->_contextOptions['content'] = $body->getContents();
172:     }
173: 
174:     /**
175:      * Build miscellaneous options for the request.
176:      *
177:      * @param \Cake\Http\Client\Request $request The request being sent.
178:      * @param array $options Array of options to use.
179:      * @return void
180:      */
181:     protected function _buildOptions(Request $request, $options)
182:     {
183:         $this->_contextOptions['method'] = $request->getMethod();
184:         $this->_contextOptions['protocol_version'] = $request->getProtocolVersion();
185:         $this->_contextOptions['ignore_errors'] = true;
186: 
187:         if (isset($options['timeout'])) {
188:             $this->_contextOptions['timeout'] = $options['timeout'];
189:         }
190:         // Redirects are handled in the client layer because of cookie handling issues.
191:         $this->_contextOptions['max_redirects'] = 0;
192: 
193:         if (isset($options['proxy']['proxy'])) {
194:             $this->_contextOptions['request_fulluri'] = true;
195:             $this->_contextOptions['proxy'] = $options['proxy']['proxy'];
196:         }
197:     }
198: 
199:     /**
200:      * Build SSL options for the request.
201:      *
202:      * @param \Cake\Http\Client\Request $request The request being sent.
203:      * @param array $options Array of options to use.
204:      * @return void
205:      */
206:     protected function _buildSslContext(Request $request, $options)
207:     {
208:         $sslOptions = [
209:             'ssl_verify_peer',
210:             'ssl_verify_peer_name',
211:             'ssl_verify_depth',
212:             'ssl_allow_self_signed',
213:             'ssl_cafile',
214:             'ssl_local_cert',
215:             'ssl_passphrase',
216:         ];
217:         if (empty($options['ssl_cafile'])) {
218:             $options['ssl_cafile'] = CORE_PATH . 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
219:         }
220:         if (!empty($options['ssl_verify_host'])) {
221:             $url = $request->getUri();
222:             $host = parse_url($url, PHP_URL_HOST);
223:             $this->_sslContextOptions['peer_name'] = $host;
224:         }
225:         foreach ($sslOptions as $key) {
226:             if (isset($options[$key])) {
227:                 $name = substr($key, 4);
228:                 $this->_sslContextOptions[$name] = $options[$key];
229:             }
230:         }
231:     }
232: 
233:     /**
234:      * Open the stream and send the request.
235:      *
236:      * @param \Cake\Http\Client\Request $request The request object.
237:      * @return array Array of populated Response objects
238:      * @throws \Cake\Http\Exception\HttpException
239:      */
240:     protected function _send(Request $request)
241:     {
242:         $deadline = false;
243:         if (isset($this->_contextOptions['timeout']) && $this->_contextOptions['timeout'] > 0) {
244:             $deadline = time() + $this->_contextOptions['timeout'];
245:         }
246: 
247:         $url = $request->getUri();
248:         $this->_open($url);
249:         $content = '';
250:         $timedOut = false;
251: 
252:         while (!feof($this->_stream)) {
253:             if ($deadline !== false) {
254:                 stream_set_timeout($this->_stream, max($deadline - time(), 1));
255:             }
256: 
257:             $content .= fread($this->_stream, 8192);
258: 
259:             $meta = stream_get_meta_data($this->_stream);
260:             if ($meta['timed_out'] || ($deadline !== false && time() > $deadline)) {
261:                 $timedOut = true;
262:                 break;
263:             }
264:         }
265:         $meta = stream_get_meta_data($this->_stream);
266:         fclose($this->_stream);
267: 
268:         if ($timedOut) {
269:             throw new HttpException('Connection timed out ' . $url, 504);
270:         }
271: 
272:         $headers = $meta['wrapper_data'];
273:         if (isset($headers['headers']) && is_array($headers['headers'])) {
274:             $headers = $headers['headers'];
275:         }
276: 
277:         return $this->createResponses($headers, $content);
278:     }
279: 
280:     /**
281:      * Build a response object
282:      *
283:      * @param array $headers Unparsed headers.
284:      * @param string $body The response body.
285:      *
286:      * @return \Cake\Http\Client\Response
287:      */
288:     protected function _buildResponse($headers, $body)
289:     {
290:         return new Response($headers, $body);
291:     }
292: 
293:     /**
294:      * Open the socket and handle any connection errors.
295:      *
296:      * @param string $url The url to connect to.
297:      * @return void
298:      * @throws \Cake\Core\Exception\Exception
299:      */
300:     protected function _open($url)
301:     {
302:         set_error_handler(function ($code, $message) {
303:             $this->_connectionErrors[] = $message;
304:         });
305:         try {
306:             $this->_stream = fopen($url, 'rb', false, $this->_context);
307:         } finally {
308:             restore_error_handler();
309:         }
310: 
311:         if (!$this->_stream || !empty($this->_connectionErrors)) {
312:             throw new Exception(implode("\n", $this->_connectionErrors));
313:         }
314:     }
315: 
316:     /**
317:      * Get the context options
318:      *
319:      * Useful for debugging and testing context creation.
320:      *
321:      * @return array
322:      */
323:     public function contextOptions()
324:     {
325:         return array_merge($this->_contextOptions, $this->_sslContextOptions);
326:     }
327: }
328: 
329: // @deprecated 3.4.0 Add backwards compat alias.
330: class_alias('Cake\Http\Client\Adapter\Stream', 'Cake\Network\Http\Adapter\Stream');
331: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs