/** * Read a response from a socket * * @param RequestInterface $request * @param resource $socket * * @throws NetworkException When the response cannot be read * * @return ResponseInterface */ protected function readResponse(RequestInterface $request, $socket) { $headers = []; $reason = null; $status = null; $protocol = null; while (($line = fgets($socket)) !== false) { if (rtrim($line) === '') { break; } $headers[] = trim($line); } $parts = explode(' ', array_shift($headers), 3); if (count($parts) <= 1) { throw new NetworkException('Cannot read the response', $request); } $protocol = substr($parts[0], -3); $status = $parts[1]; if (isset($parts[2])) { $reason = $parts[2]; } // Set the size on the stream if it was returned in the response $responseHeaders = []; foreach ($headers as $header) { $headerParts = explode(':', $header, 2); $responseHeaders[trim($headerParts[0])] = isset($headerParts[1]) ? trim($headerParts[1]) : ''; } $response = $this->messageFactory->createResponse($status, $reason, $protocol, $responseHeaders, null); $stream = $this->createStream($socket, $response); return $response->withBody($stream); }
/** * Create new ResponseBuilder instance * * @return ResponseBuilder * * @throws \RuntimeException If creating the stream from $body fails. */ private function createResponseBuilder() { try { $body = $this->streamFactory->createStream(fopen('php://temp', 'w+')); } catch (\InvalidArgumentException $e) { throw new \RuntimeException('Can not create "php://temp" stream.'); } $response = $this->messageFactory->createResponse(200, null, [], $body); return new ResponseBuilder($response); }
/** * Sends a PSR-7 request. * * @param RequestInterface $request * * @return ResponseInterface * * @throws \Http\Client\Exception If an error happens during processing the request. * @throws \Exception If processing the request is impossible (eg. bad configuration). */ public function sendRequest(RequestInterface $request) { $body = (string) $request->getBody(); $headers = []; foreach (array_keys($request->getHeaders()) as $headerName) { if (strtolower($headerName) === 'content-length') { $values = array(strlen($body)); } else { $values = $request->getHeader($headerName); } foreach ($values as $value) { $headers[] = $headerName . ': ' . $value; } } $streamContextOptions = array('protocol_version' => $request->getProtocolVersion(), 'method' => $request->getMethod(), 'header' => implode("\r\n", $headers), 'timeout' => $this->timeout, 'ignore_errors' => true, 'follow_location' => $this->followRedirects ? 1 : 0, 'max_redirects' => 100); if (strlen($body) > 0) { $streamContextOptions['content'] = $body; } $context = stream_context_create(array('http' => $streamContextOptions, 'https' => $streamContextOptions)); $httpHeadersOffset = 0; $finalUrl = (string) $request->getUri(); stream_context_set_params($context, array('notification' => function ($code, $severity, $msg, $msgCode, $bytesTx, $bytesMax) use(&$remoteDocument, &$http_response_header, &$httpHeadersOffset) { if ($code === STREAM_NOTIFY_REDIRECTED) { $finalUrl = $msg; $httpHeadersOffset = count($http_response_header); } })); $response = $this->messageFactory->createResponse(); if (false === ($responseBody = @file_get_contents((string) $request->getUri(), false, $context))) { if (!isset($http_response_header)) { throw new NetworkException('Unable to execute request', $request); } } else { $response = $response->withBody($this->streamFactory->createStream($responseBody)); } $parser = new HeaderParser(); try { return $parser->parseArray(array_slice($http_response_header, $httpHeadersOffset), $response); } catch (\Exception $e) { throw new RequestException($e->getMessage(), $request, $e); } }
/** * Unserialize data from binary string. * * @param string $string * * @return MessageInterface Unserialized data. * * @throws UnserializeException If $string can not be unserialized. * * @since 1.0 */ public function unserialize($string) { $parts = explode("\r\n", $string, 2); if (count($parts) !== 2) { throw new UnserializeException('Serialized data does not contain message type ID'); } $type = $parts[0]; $string = $parts[1]; switch ($type) { case self::REQUEST: list($part, $string) = explode("\r\n", $string, 2); $pattern = "/^HTTP\\/(?P<version>\\d\\.\\d) (?P<method>[A-Z]+) (?P<uri>.+)\$/"; if (preg_match($pattern, $part, $matches) === 0) { throw new UnserializeException(sprintf('Line "%s" not matches HTTP heading format', $part)); } $message = $this->messageFactory->createRequest($matches['method'], $matches['uri']); $message = $message->withProtocolVersion($matches['version']); break; case self::RESPONSE: $message = $this->messageFactory->createResponse(); break; default: throw new UnserializeException(); } /** @var MessageInterface $message */ list($part, $string) = explode("\r\n\r\n", $string, 2); $headers = explode("\r\n", $part); foreach ($headers as $header) { list($name, $value) = explode(':', $header, 2); $name = trim(urldecode($name)); $value = trim(urldecode($value)); if ($message->hasHeader($name)) { $message = $message->withAddedHeader($name, $value); } else { $message = $message->withHeader($name, $value); } } $body = $this->streamFactory->createStream($string); $message = $message->withBody($body); return $message; }
/** * Converts a Guzzle response into a PSR response. * * @param GuzzleResponse $response * * @return ResponseInterface */ private function createResponse(GuzzleResponse $response) { $body = $response->getBody(); return $this->messageFactory->createResponse($response->getStatusCode(), null, $response->getHeaders(), isset($body) ? $body->detach() : null, $response->getProtocolVersion()); }
/** * {@inheritdoc} */ public function createResponse($statusCode = 200, $reasonPhrase = null, $protocolVersion = '1.1', array $headers = [], $body = null) { return $this->messageFactory->createResponse($statusCode, $reasonPhrase, $protocolVersion, $headers, $body); }