Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
51 / 51 |
|
100.00% |
11 / 11 |
CRAP | |
100.00% |
1 / 1 |
Request | |
100.00% |
51 / 51 |
|
100.00% |
11 / 11 |
24 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
5 | |||
getRequestTarget | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
withRequestTarget | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
withMethod | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getUri | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
withUri | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
updateHostFromUri | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
4 | |||
setRequestTarget | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
setMethod | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setUri | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Tal; |
4 | |
5 | use GuzzleHttp\Psr7\Utils; |
6 | use function GuzzleHttp\Psr7\stream_for; |
7 | use GuzzleHttp\Psr7\Uri; |
8 | use InvalidArgumentException; |
9 | use Psr\Http\Message\RequestInterface; |
10 | use Psr\Http\Message\StreamInterface; |
11 | use Psr\Http\Message\UriInterface; |
12 | |
13 | /** |
14 | * PSR-7 request implementation. |
15 | */ |
16 | abstract class Request implements RequestInterface |
17 | { |
18 | use MessageTrait; |
19 | |
20 | /** @var string */ |
21 | protected $method; |
22 | |
23 | /** @var null|string */ |
24 | protected $requestTarget; |
25 | |
26 | /** @var UriInterface */ |
27 | protected $uri; |
28 | |
29 | /** |
30 | * @param string $method HTTP method |
31 | * @param string|UriInterface $uri URI |
32 | * @param array $headers Request headers |
33 | * @param string|null|resource|StreamInterface $body Request body |
34 | * @param string $version Protocol version |
35 | */ |
36 | public function __construct( |
37 | $method, |
38 | $uri, |
39 | array $headers = [], |
40 | $body = null, |
41 | $version = '1.1' |
42 | ) { |
43 | if (!($uri instanceof UriInterface)) { |
44 | $uri = new Uri($uri); |
45 | } |
46 | |
47 | $this->method = strtoupper($method); |
48 | $this->uri = $uri; |
49 | $this->setHeaders($headers); |
50 | $this->protocol = $version; |
51 | |
52 | if (!$this->hasHeader('Host')) { |
53 | $this->updateHostFromUri(); |
54 | } |
55 | |
56 | if ($body !== '' && $body !== null) { |
57 | $this->stream = Utils::streamFor($body); |
58 | } |
59 | } |
60 | |
61 | public function getRequestTarget(): string |
62 | { |
63 | if ($this->requestTarget !== null) { |
64 | return $this->requestTarget; |
65 | } |
66 | |
67 | $target = $this->uri->getPath(); |
68 | if ($target == '') { |
69 | $target = '/'; |
70 | } |
71 | if ($this->uri->getQuery() != '') { |
72 | $target .= '?' . $this->uri->getQuery(); |
73 | } |
74 | |
75 | return $target; |
76 | } |
77 | |
78 | public function withRequestTarget(string $requestTarget): RequestInterface |
79 | { |
80 | $new = clone $this; |
81 | return $new->setRequestTarget($requestTarget); |
82 | } |
83 | |
84 | public function getMethod(): string |
85 | { |
86 | return $this->method; |
87 | } |
88 | |
89 | public function withMethod(string $method): RequestInterface |
90 | { |
91 | $new = clone $this; |
92 | return $new->setMethod($method); |
93 | } |
94 | |
95 | public function getUri(): UriInterface |
96 | { |
97 | return $this->uri; |
98 | } |
99 | |
100 | public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface |
101 | { |
102 | if ($uri === $this->uri) { |
103 | return $this; |
104 | } |
105 | |
106 | $new = clone $this; |
107 | return $new->setUri($uri, $preserveHost); |
108 | } |
109 | |
110 | protected function updateHostFromUri() |
111 | { |
112 | $host = $this->uri->getHost(); |
113 | |
114 | if ($host == '') { |
115 | return; |
116 | } |
117 | |
118 | $port = $this->uri->getPort(); |
119 | if ($port !== null) { |
120 | $host .= ':' . $port; |
121 | } |
122 | |
123 | if (isset($this->headerNames['host'])) { |
124 | $header = $this->headerNames['host']; |
125 | } else { |
126 | $header = 'Host'; |
127 | $this->headerNames['host'] = 'Host'; |
128 | } |
129 | // Ensure Host is the first header. |
130 | // See: http://tools.ietf.org/html/rfc7230#section-5.4 |
131 | $this->headers = [$header => [$host]] + $this->headers; |
132 | } |
133 | |
134 | /** |
135 | * Sets the specific request-target. |
136 | * |
137 | * If the request needs a non-origin-form request-target — e.g., for |
138 | * specifying an absolute-form, authority-form, or asterisk-form — |
139 | * this method may be used to create an instance with the specified |
140 | * request-target, verbatim. |
141 | * |
142 | * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various |
143 | * request-target forms allowed in request messages) |
144 | * @param mixed $requestTarget |
145 | * @return static |
146 | */ |
147 | protected function setRequestTarget($requestTarget) |
148 | { |
149 | if (preg_match('#\s#', $requestTarget)) { |
150 | throw new InvalidArgumentException( |
151 | 'Invalid request target provided; cannot contain whitespace' |
152 | ); |
153 | } |
154 | |
155 | $this->requestTarget = $requestTarget; |
156 | return $this; |
157 | } |
158 | |
159 | /** |
160 | * Sets the provided HTTP method. |
161 | * |
162 | * While HTTP method names are typically all uppercase characters, HTTP |
163 | * method names are case-sensitive and thus implementations SHOULD NOT |
164 | * modify the given string. |
165 | * |
166 | * This method MUST be implemented in such a way as to retain the |
167 | * immutability of the message, and MUST return an instance that has the |
168 | * changed request method. |
169 | * |
170 | * @param string $method Case-sensitive method. |
171 | * @return static |
172 | * @throws \InvalidArgumentException for invalid HTTP methods. |
173 | */ |
174 | protected function setMethod($method) |
175 | { |
176 | $this->method = strtoupper($method); |
177 | return $this; |
178 | } |
179 | |
180 | /** |
181 | * Sets the provided URI. |
182 | * |
183 | * This method MUST update the Host header of the returned request by |
184 | * default if the URI contains a host component. If the URI does not |
185 | * contain a host component, any pre-existing Host header MUST be carried |
186 | * over to the returned request. |
187 | * |
188 | * You can opt-in to preserving the original state of the Host header by |
189 | * setting `$preserveHost` to `true`. When `$preserveHost` is set to |
190 | * `true`, this method interacts with the Host header in the following ways: |
191 | * |
192 | * - If the Host header is missing or empty, and the new URI contains |
193 | * a host component, this method MUST update the Host header in the returned |
194 | * request. |
195 | * - If the Host header is missing or empty, and the new URI does not contain a |
196 | * host component, this method MUST NOT update the Host header in the returned |
197 | * request. |
198 | * - If a Host header is present and non-empty, this method MUST NOT update |
199 | * the Host header in the returned request. |
200 | * |
201 | * @link http://tools.ietf.org/html/rfc3986#section-4.3 |
202 | * @param UriInterface $uri New request URI to use. |
203 | * @param bool $preserveHost Preserve the original state of the Host header. |
204 | * @return static |
205 | */ |
206 | protected function setUri(UriInterface $uri, $preserveHost = false) |
207 | { |
208 | $this->uri = $uri; |
209 | |
210 | if (!$preserveHost) { |
211 | $this->updateHostFromUri(); |
212 | } |
213 | return $this; |
214 | } |
215 | } |