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.7 Red Velvet API

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