Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace GuzzleHttp\Psr7;
4
 
5
use Psr\Http\Message\StreamInterface;
6
 
7
/**
8
 * Trait implementing functionality common to requests and responses.
9
 */
10
trait MessageTrait
11
{
12
    /** @var array Map of all registered headers, as original name => array of values */
13
    private $headers = [];
14
 
15
    /** @var array Map of lowercase header name => original name at registration */
16
    private $headerNames  = [];
17
 
18
    /** @var string */
19
    private $protocol = '1.1';
20
 
21
    /** @var StreamInterface|null */
22
    private $stream;
23
 
24
    public function getProtocolVersion()
25
    {
26
        return $this->protocol;
27
    }
28
 
29
    public function withProtocolVersion($version)
30
    {
31
        if ($this->protocol === $version) {
32
            return $this;
33
        }
34
 
35
        $new = clone $this;
36
        $new->protocol = $version;
37
        return $new;
38
    }
39
 
40
    public function getHeaders()
41
    {
42
        return $this->headers;
43
    }
44
 
45
    public function hasHeader($header)
46
    {
47
        return isset($this->headerNames[strtolower($header)]);
48
    }
49
 
50
    public function getHeader($header)
51
    {
52
        $header = strtolower($header);
53
 
54
        if (!isset($this->headerNames[$header])) {
55
            return [];
56
        }
57
 
58
        $header = $this->headerNames[$header];
59
 
60
        return $this->headers[$header];
61
    }
62
 
63
    public function getHeaderLine($header)
64
    {
65
        return implode(', ', $this->getHeader($header));
66
    }
67
 
68
    public function withHeader($header, $value)
69
    {
70
        $this->assertHeader($header);
71
        $value = $this->normalizeHeaderValue($value);
72
        $normalized = strtolower($header);
73
 
74
        $new = clone $this;
75
        if (isset($new->headerNames[$normalized])) {
76
            unset($new->headers[$new->headerNames[$normalized]]);
77
        }
78
        $new->headerNames[$normalized] = $header;
79
        $new->headers[$header] = $value;
80
 
81
        return $new;
82
    }
83
 
84
    public function withAddedHeader($header, $value)
85
    {
86
        $this->assertHeader($header);
87
        $value = $this->normalizeHeaderValue($value);
88
        $normalized = strtolower($header);
89
 
90
        $new = clone $this;
91
        if (isset($new->headerNames[$normalized])) {
92
            $header = $this->headerNames[$normalized];
93
            $new->headers[$header] = array_merge($this->headers[$header], $value);
94
        } else {
95
            $new->headerNames[$normalized] = $header;
96
            $new->headers[$header] = $value;
97
        }
98
 
99
        return $new;
100
    }
101
 
102
    public function withoutHeader($header)
103
    {
104
        $normalized = strtolower($header);
105
 
106
        if (!isset($this->headerNames[$normalized])) {
107
            return $this;
108
        }
109
 
110
        $header = $this->headerNames[$normalized];
111
 
112
        $new = clone $this;
113
        unset($new->headers[$header], $new->headerNames[$normalized]);
114
 
115
        return $new;
116
    }
117
 
118
    public function getBody()
119
    {
120
        if (!$this->stream) {
121
            $this->stream = Utils::streamFor('');
122
        }
123
 
124
        return $this->stream;
125
    }
126
 
127
    public function withBody(StreamInterface $body)
128
    {
129
        if ($body === $this->stream) {
130
            return $this;
131
        }
132
 
133
        $new = clone $this;
134
        $new->stream = $body;
135
        return $new;
136
    }
137
 
138
    private function setHeaders(array $headers)
139
    {
140
        $this->headerNames = $this->headers = [];
141
        foreach ($headers as $header => $value) {
142
            if (is_int($header)) {
143
                // Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec
144
                // and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.
145
                $header = (string) $header;
146
            }
147
            $this->assertHeader($header);
148
            $value = $this->normalizeHeaderValue($value);
149
            $normalized = strtolower($header);
150
            if (isset($this->headerNames[$normalized])) {
151
                $header = $this->headerNames[$normalized];
152
                $this->headers[$header] = array_merge($this->headers[$header], $value);
153
            } else {
154
                $this->headerNames[$normalized] = $header;
155
                $this->headers[$header] = $value;
156
            }
157
        }
158
    }
159
 
160
    private function normalizeHeaderValue($value)
161
    {
162
        if (!is_array($value)) {
163
            return $this->trimHeaderValues([$value]);
164
        }
165
 
166
        if (count($value) === 0) {
167
            throw new \InvalidArgumentException('Header value can not be an empty array.');
168
        }
169
 
170
        return $this->trimHeaderValues($value);
171
    }
172
 
173
    /**
174
     * Trims whitespace from the header values.
175
     *
176
     * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
177
     *
178
     * header-field = field-name ":" OWS field-value OWS
179
     * OWS          = *( SP / HTAB )
180
     *
181
     * @param string[] $values Header values
182
     *
183
     * @return string[] Trimmed header values
184
     *
185
     * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
186
     */
187
    private function trimHeaderValues(array $values)
188
    {
189
        return array_map(function ($value) {
190
            if (!is_scalar($value) && null !== $value) {
191
                throw new \InvalidArgumentException(sprintf(
192
                    'Header value must be scalar or null but %s provided.',
193
                    is_object($value) ? get_class($value) : gettype($value)
194
                ));
195
            }
196
 
197
            return trim((string) $value, " \t");
198
        }, array_values($values));
199
    }
200
 
201
    private function assertHeader($header)
202
    {
203
        if (!is_string($header)) {
204
            throw new \InvalidArgumentException(sprintf(
205
                'Header name must be a string but %s provided.',
206
                is_object($header) ? get_class($header) : gettype($header)
207
            ));
208
        }
209
 
210
        if ($header === '') {
211
            throw new \InvalidArgumentException('Header name can not be empty.');
212
        }
213
    }
214
}