24 require_once
'HTTP/Request2/Adapter.php';
43 'accept-encoding' => CURLOPT_ENCODING,
44 'cookie' => CURLOPT_COOKIE,
45 'referer' => CURLOPT_REFERER,
46 'user-agent' => CURLOPT_USERAGENT
54 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
55 'ssl_cafile' => CURLOPT_CAINFO,
56 'ssl_capath' => CURLOPT_CAPATH,
57 'ssl_local_cert' => CURLOPT_SSLCERT,
58 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD
66 CURLE_UNSUPPORTED_PROTOCOL => array(
'HTTP_Request2_MessageException',
68 CURLE_COULDNT_RESOLVE_PROXY => array(
'HTTP_Request2_ConnectionException'),
69 CURLE_COULDNT_RESOLVE_HOST => array(
'HTTP_Request2_ConnectionException'),
70 CURLE_COULDNT_CONNECT => array(
'HTTP_Request2_ConnectionException'),
72 CURLE_WRITE_ERROR => array(
'HTTP_Request2_MessageException',
74 CURLE_OPERATION_TIMEOUTED => array(
'HTTP_Request2_MessageException',
76 CURLE_HTTP_RANGE_ERROR => array(
'HTTP_Request2_MessageException'),
77 CURLE_SSL_CONNECT_ERROR => array(
'HTTP_Request2_ConnectionException'),
78 CURLE_LIBRARY_NOT_FOUND => array(
'HTTP_Request2_LogicException',
80 CURLE_FUNCTION_NOT_FOUND => array(
'HTTP_Request2_LogicException',
82 CURLE_ABORTED_BY_CALLBACK => array(
'HTTP_Request2_MessageException',
84 CURLE_TOO_MANY_REDIRECTS => array(
'HTTP_Request2_MessageException',
86 CURLE_SSL_PEER_CERTIFICATE => array(
'HTTP_Request2_ConnectionException'),
87 CURLE_GOT_NOTHING => array(
'HTTP_Request2_MessageException'),
88 CURLE_SSL_ENGINE_NOTFOUND => array(
'HTTP_Request2_LogicException',
90 CURLE_SSL_ENGINE_SETFAILED => array(
'HTTP_Request2_LogicException',
92 CURLE_SEND_ERROR => array(
'HTTP_Request2_MessageException'),
93 CURLE_RECV_ERROR => array(
'HTTP_Request2_MessageException'),
94 CURLE_SSL_CERTPROBLEM => array(
'HTTP_Request2_LogicException',
96 CURLE_SSL_CIPHER => array(
'HTTP_Request2_ConnectionException'),
97 CURLE_SSL_CACERT => array(
'HTTP_Request2_ConnectionException'),
98 CURLE_BAD_CONTENT_ENCODING => array(
'HTTP_Request2_MessageException'),
141 $nativeCode = curl_errno($ch);
142 $message =
'Curl error: ' . curl_error($ch);
143 if (!isset(self::$errorMap[$nativeCode])) {
146 $class = self::$errorMap[$nativeCode][0];
147 $code = empty(self::$errorMap[$nativeCode][1])
148 ? 0 : self::$errorMap[$nativeCode][1];
149 return new $class($message, $code, $nativeCode);
163 if (!extension_loaded(
'curl')) {
170 $this->response = null;
172 $this->eventSentHeaders =
false;
173 $this->eventReceivedHeaders =
false;
177 $e = self::wrapCurlError($ch);
179 }
catch (Exception $e) {
182 $this->lastInfo = curl_getinfo($ch);
187 unset($this->request, $this->requestBody, $this->response);
197 if (0 < $this->lastInfo[
'size_download']) {
224 curl_setopt_array($ch, array(
226 CURLOPT_HEADERFUNCTION => array($this,
'callbackWriteHeader'),
227 CURLOPT_WRITEFUNCTION => array($this,
'callbackWriteBody'),
229 CURLOPT_BUFFERSIZE => $this->request->getConfig(
'buffer_size'),
231 CURLOPT_CONNECTTIMEOUT => $this->request->getConfig(
'connect_timeout'),
233 CURLINFO_HEADER_OUT =>
true,
235 CURLOPT_URL => $this->request->getUrl()->getUrl()
239 if (!$this->request->getConfig(
'follow_redirects')) {
240 curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
false);
242 if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
true)) {
244 'Redirect support in curl is unavailable due to open_basedir or safe_mode setting',
248 curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig(
'max_redirects'));
250 if (defined(
'CURLOPT_REDIR_PROTOCOLS')) {
251 curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
254 if ($this->request->getConfig(
'strict_redirects') && defined(
'CURLOPT_POSTREDIR')) {
255 curl_setopt($ch, CURLOPT_POSTREDIR, 3);
260 if ($ip = $this->request->getConfig(
'local_ip')) {
261 curl_setopt($ch, CURLOPT_INTERFACE, $ip);
265 if ($timeout = $this->request->getConfig(
'timeout')) {
266 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
270 switch ($this->request->getConfig(
'protocol_version')) {
272 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
275 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
279 switch ($this->request->getMethod()) {
281 curl_setopt($ch, CURLOPT_HTTPGET,
true);
284 curl_setopt($ch, CURLOPT_POST,
true);
287 curl_setopt($ch, CURLOPT_NOBODY,
true);
290 curl_setopt($ch, CURLOPT_UPLOAD,
true);
293 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
297 if ($host = $this->request->getConfig(
'proxy_host')) {
298 if (!($port = $this->request->getConfig(
'proxy_port'))) {
303 curl_setopt($ch, CURLOPT_PROXY, $host .
':' . $port);
304 if ($user = $this->request->getConfig(
'proxy_user')) {
306 $ch, CURLOPT_PROXYUSERPWD,
307 $user .
':' . $this->request->getConfig(
'proxy_password')
309 switch ($this->request->getConfig(
'proxy_auth_scheme')) {
311 curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
314 curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
317 if ($type = $this->request->getConfig(
'proxy_type')) {
320 curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
323 curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
327 "Proxy type '{$type}' is not supported"
334 if ($auth = $this->request->getAuth()) {
335 curl_setopt($ch, CURLOPT_USERPWD, $auth[
'user'] .
':' . $auth[
'password']);
336 switch ($auth[
'scheme']) {
338 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
341 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
346 foreach ($this->request->getConfig() as $name => $value) {
347 if (
'ssl_verify_host' == $name && null !== $value) {
348 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
349 } elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
350 curl_setopt($ch, self::$sslContextMap[$name], $value);
354 $headers = $this->request->getHeaders();
356 if (!isset($headers[
'accept-encoding'])) {
357 $headers[
'accept-encoding'] =
'';
360 if (($jar = $this->request->getCookieJar())
361 && ($cookies = $jar->getMatching($this->request->getUrl(),
true))
363 $headers[
'cookie'] = (empty($headers[
'cookie'])?
'': $headers[
'cookie'] .
'; ') . $cookies;
367 foreach (self::$headerMap as $name => $option) {
368 if (isset($headers[$name])) {
369 curl_setopt($ch, $option, $headers[$name]);
370 unset($headers[$name]);
375 if (isset($headers[
'content-length']) || isset($headers[
'transfer-encoding'])) {
380 $headersFmt = array();
381 foreach ($headers as $name => $value) {
382 $canonicalName = implode(
'-', array_map(
'ucfirst', explode(
'-', $name)));
383 $headersFmt[] = $canonicalName .
': ' . $value;
385 curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
403 if (!$this->request->getConfig(
'follow_redirects')
404 && (!($auth = $this->request->getAuth())
407 curl_setopt($ch, CURLOPT_READFUNCTION, array($this,
'callbackReadBody'));
412 $this->requestBody = $this->requestBody->__toString();
414 } elseif (is_resource($this->requestBody)) {
416 $this->requestBody =
'';
418 $this->requestBody .= fread($fp, 16384);
422 unset($headers[
'content-length']);
423 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
438 if (!$this->eventSentHeaders) {
439 $this->request->setLastEvent(
440 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
442 $this->eventSentHeaders =
true;
444 if (in_array($this->request->getMethod(), self::$bodyDisallowed)
445 || 0 == $this->contentLength || $this->position >= $this->contentLength
449 if (is_string($this->requestBody)) {
450 $string = substr($this->requestBody, $this->position, $length);
451 } elseif (is_resource($this->requestBody)) {
452 $string = fread($this->requestBody, $length);
454 $string = $this->requestBody->read($length);
456 $this->request->setLastEvent(
'sentBodyPart', strlen($string));
457 $this->position += strlen($string);
473 if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
475 if (!$this->eventSentHeaders
476 || $this->response->getStatus() >= 200
478 $this->request->setLastEvent(
479 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
482 $upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
484 if ($upload > $this->position) {
485 $this->request->setLastEvent(
486 'sentBodyPart', $upload - $this->position
488 $this->position = $upload;
490 if ($upload && (!$this->eventSentHeaders
491 || $this->response->getStatus() >= 200)
493 $this->request->setLastEvent(
'sentBody', $upload);
495 $this->eventSentHeaders =
true;
497 if ($this->eventReceivedHeaders) {
498 $this->eventReceivedHeaders =
false;
499 $this->response = null;
502 if (empty($this->response)) {
504 $string,
false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)
507 $this->response->parseHeaderLine($string);
508 if (
'' == trim($string)) {
510 if (200 <= $this->response->getStatus()) {
511 $this->request->setLastEvent(
'receivedHeaders', $this->response);
514 if ($this->request->getConfig(
'follow_redirects') && $this->response->isRedirect()) {
515 $redirectUrl =
new Net_URL2($this->response->getHeader(
'location'));
518 if (!defined(
'CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute()
519 && !in_array($redirectUrl->getScheme(), array(
'http',
'https'))
524 if ($jar = $this->request->getCookieJar()) {
525 $jar->addCookiesFromResponse($this->response, $this->request->getUrl());
526 if (!$redirectUrl->isAbsolute()) {
527 $redirectUrl = $this->request->getUrl()->
resolve($redirectUrl);
529 if ($cookies = $jar->getMatching($redirectUrl,
true)) {
530 curl_setopt($ch, CURLOPT_COOKIE, $cookies);
534 $this->eventReceivedHeaders =
true;
537 return strlen($string);
554 if (empty($this->response)) {
556 "Malformed response: {$string}",
560 if ($this->request->getConfig(
'store_body')) {
561 $this->response->appendBody($string);
563 $this->request->setLastEvent(
'receivedBodyPart', $string);
564 return strlen($string);
workaroundPhpBug47204($ch, &$headers)
callbackWriteHeader($ch, $string)
sendRequest(HTTP_Request2 $request)
static wrapCurlError($ch)
calculateRequestLength(&$headers)
setLastEvent($name, $data=null)
callbackWriteBody($ch, $string)
callbackReadBody($ch, $fd, $length)