Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit d78a757

Browse files
committed
Merge branch 'hotfix/320-string-reason-phrase'
Close #320
2 parents e396d37 + f6a9cf8 commit d78a757

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ All notable changes to this project will be documented in this file, in reverse
2222

2323
### Fixed
2424

25+
- [#320](https://github.com/zendframework/zend-diactoros/pull/320) adds checking within `Response` to ensure that the provided reason
26+
phrase is a string; an `InvalidArgumentException` is now raised if it is not. This change
27+
ensures the class adheres strictly to the PSR-7 specification.
28+
2529
- [#319](https://github.com/zendframework/zend-diactoros/pull/319) provides a fix to `Zend\Diactoros\Response` that ensures that the status
2630
code returned is _always_ an integer (and never a string containing an
2731
integer), thus ensuring it strictly adheres to the PSR-7 specification.

src/Response.php

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4-
* @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
4+
* @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (http://www.zend.com)
55
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
66
*/
77

@@ -113,7 +113,7 @@ class Response implements ResponseInterface
113113
/**
114114
* @var string
115115
*/
116-
private $reasonPhrase = '';
116+
private $reasonPhrase;
117117

118118
/**
119119
* @var int
@@ -146,12 +146,6 @@ public function getStatusCode()
146146
*/
147147
public function getReasonPhrase()
148148
{
149-
if (! $this->reasonPhrase
150-
&& isset($this->phrases[$this->statusCode])
151-
) {
152-
$this->reasonPhrase = $this->phrases[$this->statusCode];
153-
}
154-
155149
return $this->reasonPhrase;
156150
}
157151

@@ -161,18 +155,18 @@ public function getReasonPhrase()
161155
public function withStatus($code, $reasonPhrase = '')
162156
{
163157
$new = clone $this;
164-
$new->setStatusCode($code);
165-
$new->reasonPhrase = $reasonPhrase;
158+
$new->setStatusCode($code, $reasonPhrase);
166159
return $new;
167160
}
168161

169162
/**
170163
* Set a valid status code.
171164
*
172165
* @param int $code
166+
* @param string $reasonPhrase
173167
* @throws InvalidArgumentException on an invalid status code.
174168
*/
175-
private function setStatusCode($code)
169+
private function setStatusCode($code, $reasonPhrase = '')
176170
{
177171
if (! is_numeric($code)
178172
|| is_float($code)
@@ -181,11 +175,24 @@ private function setStatusCode($code)
181175
) {
182176
throw new InvalidArgumentException(sprintf(
183177
'Invalid status code "%s"; must be an integer between %d and %d, inclusive',
184-
(is_scalar($code) ? $code : gettype($code)),
178+
is_scalar($code) ? $code : gettype($code),
185179
static::MIN_STATUS_CODE_VALUE,
186180
static::MAX_STATUS_CODE_VALUE
187181
));
188182
}
183+
184+
if (! is_string($reasonPhrase)) {
185+
throw new InvalidArgumentException(sprintf(
186+
'Unsupported response reason phrase; must be a string, received %s',
187+
is_object($reasonPhrase) ? get_class($reasonPhrase) : gettype($reasonPhrase)
188+
));
189+
}
190+
191+
if ($reasonPhrase === '' && isset($this->phrases[$code])) {
192+
$reasonPhrase = $this->phrases[$code];
193+
}
194+
195+
$this->reasonPhrase = $reasonPhrase;
189196
$this->statusCode = (int) $code;
190197
}
191198
}

test/ResponseTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,29 @@ public function testCanSetCustomReasonPhrase()
112112
$this->assertSame('Foo Bar!', $response->getReasonPhrase());
113113
}
114114

115+
public function invalidReasonPhrases()
116+
{
117+
return [
118+
'true' => [ true ],
119+
'false' => [ false ],
120+
'array' => [ [ 200 ] ],
121+
'object' => [ (object) [ 'reasonPhrase' => 'Ok' ] ],
122+
'integer' => [99],
123+
'float' => [400.5],
124+
'null' => [null],
125+
];
126+
}
127+
128+
/**
129+
* @dataProvider invalidReasonPhrases
130+
*/
131+
public function testWithStatusRaisesAnExceptionForNonStringReasonPhrases($invalidReasonPhrase)
132+
{
133+
$this->expectException(InvalidArgumentException::class);
134+
135+
$this->response->withStatus(422, $invalidReasonPhrase);
136+
}
137+
115138
public function testConstructorRaisesExceptionForInvalidStream()
116139
{
117140
$this->expectException(InvalidArgumentException::class);

0 commit comments

Comments
 (0)