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