/** * {@inheritdoc} */ public function send(RequestInterface $request, array $options = array()) { $options += Client::$defaultOptions; $curlOptions = $options['curl'] + array(CURLOPT_URL => (string) $request->getUri(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_HTTPHEADER => \EasyRequest\get_headers($request), CURLOPT_ENCODING => $request->getHeaderLine('Accept-Encoding'), CURLOPT_NOBODY => $options['nobody'], CURLOPT_CONNECTTIMEOUT => $options['timeout'], CURLOPT_HTTP_VERSION => $request->getProtocolVersion() == '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1); if ($options['upload']) { $body = $request->getBody(); $curlOptions += array(CURLOPT_UPLOAD => true, CURLOPT_READFUNCTION => function ($ch, $fp, $length) use($body) { return $body->read($length); }); } elseif ($options['body']) { $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody(); } if ($options['proxy']) { $curlOptions += array(CURLOPT_PROXY => $options['proxy'], CURLOPT_PROXYTYPE => $options['proxy_type']); if ($options['proxy_userpwd']) { $curlOptions[CURLOPT_PROXYUSERPWD] = $options['proxy_userpwd']; } } if ($options['bindto']) { $curlOptions[CURLOPT_INTERFACE] = $options['bindto']; } $header = $body = ''; $curlOptions[CURLOPT_HEADERFUNCTION] = $this->handleResponseHeader($header); $ch = curl_init(); curl_setopt_array($ch, $curlOptions); $result = curl_exec($ch); curl_close($ch); if ($result === false) { throw new Exception(sprintf('%d - %s', curl_errno($ch), curl_error($ch))); } $body = substr($result, strlen($header)); return Response::parse($header, $body); }
/** * {@inheritdoc} */ public function send(RequestInterface $request, array $options = array()) { static $ports = array('https' => 443, 'http' => 80, '' => 80); $options += Client::$defaultOptions; $uri = $request->getUri(); $targetHost = $host = $uri->getHost(); $targetPort = $port = $uri->getPort() ? $uri->getPort() : $ports[$uri->getScheme()]; $requestTarget = $request->getRequestTarget(); if ($options['proxy']) { list($host, $port) = explode(':', $options['proxy']); $requestTarget = (string) $uri; } if (!($stream = $this->getConnection($host, $port, $errno, $errstr, $options, $uri))) { throw new Exception(sprintf("Couldn't connect to %s:%s. %s - %s", $host, $port, $errno, $errstr)); } $httpsThroughSocks = $options['proxy'] && $options['proxy_type'] != Client::PROXY_HTTP && $uri->getScheme() == 'https'; $headers = \EasyRequest\get_headers($request); $headers[] = 'Connection: close'; // handle proxy if ($options['proxy']) { try { switch ($options['proxy_type']) { case Client::PROXY_HTTP: if ($options['proxy_userpwd']) { $headers[] = 'Proxy-Authorization: Basic ' . base64_encode($options['proxy_userpwd']); } break; case Client::PROXY_SOCKS5: $this->handleSocks5($stream, $options, $targetHost, $targetPort); break; case Client::PROXY_SOCKS4: case Client::PROXY_SOCKS4A: if ($options['proxy_userpwd']) { // socks4 does not support authentication, // if user give a wrong version, just handle it $this->handleSocks5($stream, $options, $targetHost, $targetPort); } else { $this->handleSocks4($stream, $options, $targetHost, $targetPort); } break; } } catch (\Exception $e) { fclose($stream); throw $e; } if ($httpsThroughSocks) { $this->toggleCrypto($stream, true); } } // build request header $header = sprintf("%s %s HTTP/%s\r\n", $request->getMethod(), $requestTarget, $request->getProtocolVersion()); $header .= implode("\r\n", $headers) . "\r\n"; $header .= "\r\n"; $this->sendRequest($header, $request->getBody(), $options, function ($message) use($stream) { fwrite($stream, $message); }); $request->getBody()->close(); // ignore some warning such as "SSL: Connection reset by peer", // this issue sometimes happen on some SOCKS servers while // browsing to HTTPS website. $httpsThroughSocks && ($level = error_reporting(~E_WARNING)); $response = ''; while (!feof($stream)) { $response .= fgets($stream, 1024); } fclose($stream); $httpsThroughSocks && error_reporting($level); list($header, $body) = explode("\r\n\r\n", $response, 2) + array('', ''); $response = Response::parse($header, ''); if ($response->getHeaderLine('Transfer-Encoding') == 'chunked') { $body = \EasyRequest\decode_chunked($body); } if ($response->getHeaderLine('Content-Encoding') == 'gzip') { $body = \EasyRequest\decode_gzip($body); } $response->getBody()->write($body); return $response; }