public static function assignSslContext($context, Options $options) { $caPath = $options->getCaPath(); if (!empty($caPath)) { stream_context_set_option($context, 'ssl', 'verify_peer', true); if (is_file($caPath)) { stream_context_set_option($context, 'ssl', 'cafile', $caPath); } elseif (is_dir($caPath)) { stream_context_set_option($context, 'ssl', 'capath', $caPath); } } else { stream_context_set_option($context, 'ssl', 'verify_peer', false); } }
public function testHttpsRequestWithCertFile() { $this->markTestIncomplete('Doest not work at the moment on travis <= 5.5'); $options = new Options(); $options->setSsl(true, __DIR__ . '/cacert.pem'); $request = new GetRequest(new Url('https://google.com')); $response = $this->http->request($request, $options); $this->assertGoogleResponse($response); }
public function request(RequestInterface $request, Options $options) { $context = stream_context_create(); // ssl $scheme = null; if ($options->getSsl() !== false && ($options->getSsl() === true || strcasecmp($request->getUri()->getScheme(), 'https') === 0)) { $transports = stream_get_transports(); if (in_array('tls', $transports)) { $scheme = 'tls'; } elseif (in_array('ssl', $transports)) { $scheme = 'ssl'; } else { throw new NotSupportedException('https is not supported'); } Stream::assignSslContext($context, $options); } else { $scheme = 'tcp'; } // port $port = $request->getUri()->getPort(); if (empty($port)) { $port = getservbyname($request->getUri()->getScheme(), 'tcp'); } // open socket set_error_handler(__CLASS__ . '::handleError'); $timeout = ini_get('default_socket_timeout'); $handle = stream_socket_client($scheme . '://' . $request->getUri()->getHost() . ':' . $port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context); restore_error_handler(); if ($handle !== false) { // timeout $timeout = $options->getTimeout(); if (!empty($timeout)) { stream_set_timeout($handle, $timeout); } // callback $callback = $options->getCallback(); if (!empty($callback)) { call_user_func_array($callback, array($handle, $request)); } // write header $headers = ResponseParser::buildHeaderFromMessage($request); fwrite($handle, Http\RequestParser::buildStatusLine($request) . Http::$newLine); foreach ($headers as $header) { fwrite($handle, $header . Http::$newLine); } fwrite($handle, Http::$newLine); fflush($handle); // write body $body = $request->getBody(); if ($body !== null && !in_array($request->getMethod(), array('HEAD', 'GET'))) { if ($request->getHeader('Transfer-Encoding') == 'chunked') { while (!$body->eof()) { $chunk = $body->read($this->chunkSize); $len = strlen($chunk); if ($len > 0) { fwrite($handle, dechex($len) . Http::$newLine . $chunk . Http::$newLine); fflush($handle); } } fwrite($handle, '0' . Http::$newLine . Http::$newLine); fflush($handle); } else { fwrite($handle, (string) $body); fflush($handle); } } // read header $headers = array(); do { $header = trim(fgets($handle)); if (!empty($header)) { $headers[] = $header; } } while (!empty($header)); // check for timeout $meta = stream_get_meta_data($handle); if ($meta['timed_out']) { throw new HandlerException('Connection timeout'); } // build response $response = ResponseParser::buildResponseFromHeader($headers); // create stream $contentLength = (int) $response->getHeader('Content-Length'); $chunkedEncoding = $response->getHeader('Transfer-Encoding') == 'chunked'; if ($request->getMethod() != 'HEAD') { $response->setBody(new SocksStream($handle, $contentLength, $chunkedEncoding)); } else { fclose($handle); $response->setBody(new StringStream()); } return $response; } else { throw new HandlerException(!empty($errstr) ? $errstr : 'Could not open socket'); } }
public function request(RequestInterface $request, Options $options) { $this->header = array(); $this->body = fopen('php://temp', 'r+'); $handle = curl_init($request->getUri()->toString()); curl_setopt($handle, CURLOPT_HEADER, false); curl_setopt($handle, CURLOPT_RETURNTRANSFER, false); curl_setopt($handle, CURLOPT_HEADERFUNCTION, array($this, 'header')); curl_setopt($handle, CURLOPT_WRITEFUNCTION, array($this, 'write')); curl_setopt($handle, CURLOPT_CUSTOMREQUEST, $request->getMethod()); // set header $headers = ResponseParser::buildHeaderFromMessage($request); if (!empty($headers)) { if (!$request->hasHeader('Expect')) { $headers[] = 'Expect:'; } curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); } // set body $body = $request->getBody(); if ($body !== null && !in_array($request->getMethod(), array('HEAD', 'GET'))) { if ($request->getHeader('Transfer-Encoding') == 'chunked') { curl_setopt($handle, CURLOPT_UPLOAD, true); curl_setopt($handle, CURLOPT_READFUNCTION, function ($handle, $fd, $length) use($body) { return $body->read($length); }); } else { curl_setopt($handle, CURLOPT_POSTFIELDS, (string) $body); } } // set proxy $proxy = $options->getProxy(); if (!empty($proxy)) { curl_setopt($handle, CURLOPT_PROXY, $proxy); } // set follow location curl_setopt($handle, CURLOPT_FOLLOWLOCATION, $options->getFollowLocation() && $this->hasFollowLocation); curl_setopt($handle, CURLOPT_MAXREDIRS, $options->getMaxRedirects()); // set ssl if ($options->getSsl() !== false && ($options->getSsl() === true || strcasecmp($request->getUri()->getScheme(), 'https') === 0)) { $caPath = $options->getCaPath(); if (!empty($caPath)) { curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 2); if (is_file($caPath)) { curl_setopt($handle, CURLOPT_CAINFO, $caPath); } elseif (is_dir($caPath)) { curl_setopt($handle, CURLOPT_CAPATH, $caPath); } } else { curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0); } } // set timeout $timeout = $options->getTimeout(); if (!empty($timeout)) { curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); } // callback $callback = $options->getCallback(); if (!empty($callback)) { call_user_func_array($callback, array($handle, $request)); } curl_exec($handle); // if follow location is active modify the header since all headers from // each redirection are included if ($options->getFollowLocation() && $this->hasFollowLocation) { $positions = array(); foreach ($this->header as $key => $header) { if (substr($header, 0, 5) == 'HTTP/') { $positions[] = $key; } } if (count($positions) > 1) { $this->header = array_slice($this->header, end($positions) - 1); } } if (curl_errno($handle)) { throw new HandlerException('Curl error: ' . curl_error($handle)); } curl_close($handle); // build response rewind($this->body); $response = ResponseParser::buildResponseFromHeader($this->header); if ($request->getMethod() != 'HEAD') { $response->setBody(new TempStream($this->body)); } else { $response->setBody(new StringStream()); } return $response; }