201486317d54bd2c270ecaeacd870d1f38d94b27
[yaffs-website] / vendor / zendframework / zend-diactoros / src / Request / Serializer.php
1 <?php
2 /**
3  * Zend Framework (http://framework.zend.com/)
4  *
5  * @see       http://github.com/zendframework/zend-diactoros for the canonical source repository
6  * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
7  * @license   https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8  */
9
10 namespace Zend\Diactoros\Request;
11
12 use InvalidArgumentException;
13 use Psr\Http\Message\RequestInterface;
14 use Psr\Http\Message\StreamInterface;
15 use UnexpectedValueException;
16 use Zend\Diactoros\AbstractSerializer;
17 use Zend\Diactoros\Request;
18 use Zend\Diactoros\Stream;
19 use Zend\Diactoros\Uri;
20
21 use function preg_match;
22 use function sprintf;
23
24 /**
25  * Serialize (cast to string) or deserialize (cast string to Request) messages.
26  *
27  * This class provides functionality for serializing a RequestInterface instance
28  * to a string, as well as the reverse operation of creating a Request instance
29  * from a string/stream representing a message.
30  */
31 final class Serializer extends AbstractSerializer
32 {
33     /**
34      * Deserialize a request string to a request instance.
35      *
36      * Internally, casts the message to a stream and invokes fromStream().
37      *
38      * @param string $message
39      * @return Request
40      * @throws UnexpectedValueException when errors occur parsing the message.
41      */
42     public static function fromString($message)
43     {
44         $stream = new Stream('php://temp', 'wb+');
45         $stream->write($message);
46         return self::fromStream($stream);
47     }
48
49     /**
50      * Deserialize a request stream to a request instance.
51      *
52      * @param StreamInterface $stream
53      * @return Request
54      * @throws UnexpectedValueException when errors occur parsing the message.
55      */
56     public static function fromStream(StreamInterface $stream)
57     {
58         if (! $stream->isReadable() || ! $stream->isSeekable()) {
59             throw new InvalidArgumentException('Message stream must be both readable and seekable');
60         }
61
62         $stream->rewind();
63
64         list($method, $requestTarget, $version) = self::getRequestLine($stream);
65         $uri = self::createUriFromRequestTarget($requestTarget);
66
67         list($headers, $body) = self::splitStream($stream);
68
69         return (new Request($uri, $method, $body, $headers))
70             ->withProtocolVersion($version)
71             ->withRequestTarget($requestTarget);
72     }
73
74     /**
75      * Serialize a request message to a string.
76      *
77      * @param RequestInterface $request
78      * @return string
79      */
80     public static function toString(RequestInterface $request)
81     {
82         $httpMethod = $request->getMethod();
83         if (empty($httpMethod)) {
84             throw new UnexpectedValueException('Object can not be serialized because HTTP method is empty');
85         }
86         $headers = self::serializeHeaders($request->getHeaders());
87         $body    = (string) $request->getBody();
88         $format  = '%s %s HTTP/%s%s%s';
89
90         if (! empty($headers)) {
91             $headers = "\r\n" . $headers;
92         }
93         if (! empty($body)) {
94             $headers .= "\r\n\r\n";
95         }
96
97         return sprintf(
98             $format,
99             $httpMethod,
100             $request->getRequestTarget(),
101             $request->getProtocolVersion(),
102             $headers,
103             $body
104         );
105     }
106
107     /**
108      * Retrieve the components of the request line.
109      *
110      * Retrieves the first line of the stream and parses it, raising an
111      * exception if it does not follow specifications; if valid, returns a list
112      * with the method, target, and version, in that order.
113      *
114      * @param StreamInterface $stream
115      * @return array
116      */
117     private static function getRequestLine(StreamInterface $stream)
118     {
119         $requestLine = self::getLine($stream);
120
121         if (! preg_match(
122             '#^(?P<method>[!\#$%&\'*+.^_`|~a-zA-Z0-9-]+) (?P<target>[^\s]+) HTTP/(?P<version>[1-9]\d*\.\d+)$#',
123             $requestLine,
124             $matches
125         )) {
126             throw new UnexpectedValueException('Invalid request line detected');
127         }
128
129         return [$matches['method'], $matches['target'], $matches['version']];
130     }
131
132     /**
133      * Create and return a Uri instance based on the provided request target.
134      *
135      * If the request target is of authority or asterisk form, an empty Uri
136      * instance is returned; otherwise, the value is used to create and return
137      * a new Uri instance.
138      *
139      * @param string $requestTarget
140      * @return Uri
141      */
142     private static function createUriFromRequestTarget($requestTarget)
143     {
144         if (preg_match('#^https?://#', $requestTarget)) {
145             return new Uri($requestTarget);
146         }
147
148         if (preg_match('#^(\*|[^/])#', $requestTarget)) {
149             return new Uri();
150         }
151
152         return new Uri($requestTarget);
153     }
154 }