3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4 * @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8 namespace Zend\Diactoros\Response;
10 use InvalidArgumentException;
11 use Psr\Http\Message\ResponseInterface;
12 use Psr\Http\Message\StreamInterface;
13 use UnexpectedValueException;
14 use Zend\Diactoros\AbstractSerializer;
15 use Zend\Diactoros\Response;
16 use Zend\Diactoros\Stream;
18 final class Serializer extends AbstractSerializer
21 * Deserialize a response string to a response instance.
23 * @param string $message
25 * @throws UnexpectedValueException when errors occur parsing the message.
27 public static function fromString($message)
29 $stream = new Stream('php://temp', 'wb+');
30 $stream->write($message);
31 return static::fromStream($stream);
35 * Parse a response from a stream.
37 * @param StreamInterface $stream
39 * @throws InvalidArgumentException when the stream is not readable.
40 * @throws UnexpectedValueException when errors occur parsing the message.
42 public static function fromStream(StreamInterface $stream)
44 if (! $stream->isReadable() || ! $stream->isSeekable()) {
45 throw new InvalidArgumentException('Message stream must be both readable and seekable');
50 list($version, $status, $reasonPhrase) = self::getStatusLine($stream);
51 list($headers, $body) = self::splitStream($stream);
53 return (new Response($body, $status, $headers))
54 ->withProtocolVersion($version)
55 ->withStatus((int) $status, $reasonPhrase);
59 * Create a string representation of a response.
61 * @param ResponseInterface $response
64 public static function toString(ResponseInterface $response)
66 $reasonPhrase = $response->getReasonPhrase();
67 $headers = self::serializeHeaders($response->getHeaders());
68 $body = (string) $response->getBody();
69 $format = 'HTTP/%s %d%s%s%s';
71 if (! empty($headers)) {
72 $headers = "\r\n" . $headers;
75 $headers .= "\r\n\r\n";
79 $response->getProtocolVersion(),
80 $response->getStatusCode(),
81 ($reasonPhrase ? ' ' . $reasonPhrase : ''),
88 * Retrieve the status line for the message.
90 * @param StreamInterface $stream
91 * @return array Array with three elements: 0 => version, 1 => status, 2 => reason
92 * @throws UnexpectedValueException if line is malformed
94 private static function getStatusLine(StreamInterface $stream)
96 $line = self::getLine($stream);
99 '#^HTTP/(?P<version>[1-9]\d*\.\d) (?P<status>[1-5]\d{2})(\s+(?P<reason>.+))?$#',
103 throw new UnexpectedValueException('No status line detected');
106 return [$matches['version'], $matches['status'], isset($matches['reason']) ? $matches['reason'] : ''];