2 namespace GuzzleHttp\Psr7;
4 use Psr\Http\Message\StreamInterface;
7 * Trait implementing functionality common to requests and responses.
11 /** @var array Map of all registered headers, as original name => array of values */
12 private $headers = [];
14 /** @var array Map of lowercase header name => original name at registration */
15 private $headerNames = [];
18 private $protocol = '1.1';
20 /** @var StreamInterface */
23 public function getProtocolVersion()
25 return $this->protocol;
28 public function withProtocolVersion($version)
30 if ($this->protocol === $version) {
35 $new->protocol = $version;
39 public function getHeaders()
41 return $this->headers;
44 public function hasHeader($header)
46 return isset($this->headerNames[strtolower($header)]);
49 public function getHeader($header)
51 $header = strtolower($header);
53 if (!isset($this->headerNames[$header])) {
57 $header = $this->headerNames[$header];
59 return $this->headers[$header];
62 public function getHeaderLine($header)
64 return implode(', ', $this->getHeader($header));
67 public function withHeader($header, $value)
69 if (!is_array($value)) {
73 $value = $this->trimHeaderValues($value);
74 $normalized = strtolower($header);
77 if (isset($new->headerNames[$normalized])) {
78 unset($new->headers[$new->headerNames[$normalized]]);
80 $new->headerNames[$normalized] = $header;
81 $new->headers[$header] = $value;
86 public function withAddedHeader($header, $value)
88 if (!is_array($value)) {
92 $value = $this->trimHeaderValues($value);
93 $normalized = strtolower($header);
96 if (isset($new->headerNames[$normalized])) {
97 $header = $this->headerNames[$normalized];
98 $new->headers[$header] = array_merge($this->headers[$header], $value);
100 $new->headerNames[$normalized] = $header;
101 $new->headers[$header] = $value;
107 public function withoutHeader($header)
109 $normalized = strtolower($header);
111 if (!isset($this->headerNames[$normalized])) {
115 $header = $this->headerNames[$normalized];
118 unset($new->headers[$header], $new->headerNames[$normalized]);
123 public function getBody()
125 if (!$this->stream) {
126 $this->stream = stream_for('');
129 return $this->stream;
132 public function withBody(StreamInterface $body)
134 if ($body === $this->stream) {
139 $new->stream = $body;
143 private function setHeaders(array $headers)
145 $this->headerNames = $this->headers = [];
146 foreach ($headers as $header => $value) {
147 if (!is_array($value)) {
151 $value = $this->trimHeaderValues($value);
152 $normalized = strtolower($header);
153 if (isset($this->headerNames[$normalized])) {
154 $header = $this->headerNames[$normalized];
155 $this->headers[$header] = array_merge($this->headers[$header], $value);
157 $this->headerNames[$normalized] = $header;
158 $this->headers[$header] = $value;
164 * Trims whitespace from the header values.
166 * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
168 * header-field = field-name ":" OWS field-value OWS
169 * OWS = *( SP / HTAB )
171 * @param string[] $values Header values
173 * @return string[] Trimmed header values
175 * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
177 private function trimHeaderValues(array $values)
179 return array_map(function ($value) {
180 return trim($value, " \t");