2
namespace GuzzleHttp\Message;
4
use GuzzleHttp\Stream\StreamInterface;
6
abstract class AbstractMessage implements MessageInterface
8
/** @var array HTTP header collection */
11
/** @var array mapping a lowercase header name to its name over the wire */
12
private $headerNames = [];
14
/** @var StreamInterface Message body */
17
/** @var string HTTP protocol version of the message */
18
private $protocolVersion = '1.1';
20
public function __toString()
22
return static::getStartLineAndHeaders($this)
23
. "\r\n\r\n" . $this->getBody();
26
public function getProtocolVersion()
28
return $this->protocolVersion;
31
public function getBody()
36
public function setBody(StreamInterface $body = null)
39
// Setting a null body will remove the body of the request
40
$this->removeHeader('Content-Length')
41
->removeHeader('Transfer-Encoding');
49
public function addHeader($header, $value)
51
static $valid = ['string' => true, 'integer' => true,
52
'double' => true, 'array' => true];
54
$type = gettype($value);
55
if (!isset($valid[$type])) {
56
throw new \InvalidArgumentException('Invalid header value');
59
if ($type == 'array') {
60
$current = array_merge($this->getHeader($header, true), $value);
62
$current = $this->getHeader($header, true);
66
return $this->setHeader($header, $current);
69
public function addHeaders(array $headers)
71
foreach ($headers as $name => $header) {
72
$this->addHeader($name, $header);
76
public function getHeader($header, $asArray = false)
78
$name = strtolower($header);
80
if (!isset($this->headers[$name])) {
81
return $asArray ? [] : '';
85
? $this->headers[$name]
86
: implode(', ', $this->headers[$name]);
89
public function getHeaders()
92
foreach ($this->headers as $name => $values) {
93
$headers[$this->headerNames[$name]] = $values;
99
public function setHeader($header, $value)
101
$header = trim($header);
102
$name = strtolower($header);
103
$this->headerNames[$name] = $header;
105
switch (gettype($value)) {
107
$this->headers[$name] = [trim($value)];
111
$this->headers[$name] = [(string) $value];
114
foreach ($value as &$v) {
117
$this->headers[$name] = $value;
120
throw new \InvalidArgumentException('Invalid header value '
121
. 'provided: ' . var_export($value, true));
127
public function setHeaders(array $headers)
129
$this->headers = $this->headerNames = [];
130
foreach ($headers as $key => $value) {
131
$this->setHeader($key, $value);
137
public function hasHeader($header)
139
return isset($this->headers[strtolower($header)]);
142
public function removeHeader($header)
144
$name = strtolower($header);
145
unset($this->headers[$name], $this->headerNames[$name]);
151
* Parse an array of header values containing ";" separated data into an
152
* array of associative arrays representing the header key value pair
153
* data of the header. When a parameter does not contain a value, but just
154
* contains a key, this function will inject a key with a '' string value.
156
* @param MessageInterface $message That contains the header
157
* @param string $header Header to retrieve from the message
159
* @return array Returns the parsed header values.
161
public static function parseHeader(MessageInterface $message, $header)
163
static $trimmed = "\"' \n\t\r";
164
$params = $matches = [];
166
foreach (self::normalizeHeader($message, $header) as $val) {
168
foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
169
if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
172
$part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
174
$part[] = trim($m[0], $trimmed);
187
* Converts an array of header values that may contain comma separated
188
* headers into an array of headers with no comma separated values.
190
* @param MessageInterface $message That contains the header
191
* @param string $header Header to retrieve from the message
193
* @return array Returns the normalized header field values.
195
public static function normalizeHeader(MessageInterface $message, $header)
197
$h = $message->getHeader($header, true);
198
for ($i = 0, $total = count($h); $i < $total; $i++) {
199
if (strpos($h[$i], ',') === false) {
202
foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $h[$i]) as $v) {
212
* Gets the start-line and headers of a message as a string
214
* @param MessageInterface $message
218
public static function getStartLineAndHeaders(MessageInterface $message)
220
return static::getStartLine($message)
221
. self::getHeadersAsString($message);
225
* Gets the headers of a message as a string
227
* @param MessageInterface $message
231
public static function getHeadersAsString(MessageInterface $message)
234
foreach ($message->getHeaders() as $name => $values) {
235
$result .= "\r\n{$name}: " . implode(', ', $values);
242
* Gets the start line of a message
244
* @param MessageInterface $message
247
* @throws \InvalidArgumentException
249
public static function getStartLine(MessageInterface $message)
251
if ($message instanceof RequestInterface) {
252
return trim($message->getMethod() . ' '
253
. $message->getResource())
254
. ' HTTP/' . $message->getProtocolVersion();
255
} elseif ($message instanceof ResponseInterface) {
256
return 'HTTP/' . $message->getProtocolVersion() . ' '
257
. $message->getStatusCode() . ' '
258
. $message->getReasonPhrase();
260
throw new \InvalidArgumentException('Unknown message type');
265
* Accepts and modifies the options provided to the message in the
268
* Can be overridden in subclasses as necessary.
270
* @param array $options Options array passed by reference.
272
protected function handleOptions(array &$options)
274
if (isset($options['protocol_version'])) {
275
$this->protocolVersion = $options['protocol_version'];