New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assert values according to PSR standard #250
Changes from all commits
9ceb5db
53c3278
df60ffa
42ad61c
7b128a3
d67db57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,11 +66,8 @@ public function getHeaderLine($header) | |
|
||
public function withHeader($header, $value) | ||
{ | ||
if (!is_array($value)) { | ||
$value = [$value]; | ||
} | ||
|
||
$value = $this->trimHeaderValues($value); | ||
$this->assertHeader($header); | ||
$value = $this->normalizeHeaderValue($value); | ||
$normalized = strtolower($header); | ||
|
||
$new = clone $this; | ||
|
@@ -85,11 +82,8 @@ public function withHeader($header, $value) | |
|
||
public function withAddedHeader($header, $value) | ||
{ | ||
if (!is_array($value)) { | ||
$value = [$value]; | ||
} | ||
|
||
$value = $this->trimHeaderValues($value); | ||
$this->assertHeader($header); | ||
$value = $this->normalizeHeaderValue($value); | ||
$normalized = strtolower($header); | ||
|
||
$new = clone $this; | ||
|
@@ -144,11 +138,8 @@ private function setHeaders(array $headers) | |
{ | ||
$this->headerNames = $this->headers = []; | ||
foreach ($headers as $header => $value) { | ||
if (!is_array($value)) { | ||
$value = [$value]; | ||
} | ||
|
||
$value = $this->trimHeaderValues($value); | ||
$this->assertHeader($header); | ||
$value = $this->normalizeHeaderValue($value); | ||
$normalized = strtolower($header); | ||
if (isset($this->headerNames[$normalized])) { | ||
$header = $this->headerNames[$normalized]; | ||
|
@@ -160,6 +151,23 @@ private function setHeaders(array $headers) | |
} | ||
} | ||
|
||
private function normalizeHeaderValue($value) | ||
{ | ||
if (!is_array($value)) { | ||
if (!is_string($value)) { | ||
throw new \InvalidArgumentException('Header value must be a string or an array of strings.'); | ||
} | ||
|
||
return $this->trimHeaderValues([$value]); | ||
} | ||
|
||
if (count($value) === 0) { | ||
throw new \InvalidArgumentException('Header value can not be an empty array.'); | ||
} | ||
|
||
return $this->trimHeaderValues($value); | ||
} | ||
|
||
/** | ||
* Trims whitespace from the header values. | ||
* | ||
|
@@ -177,7 +185,17 @@ private function setHeaders(array $headers) | |
private function trimHeaderValues(array $values) | ||
{ | ||
return array_map(function ($value) { | ||
if (!is_string($value)) { | ||
throw new \InvalidArgumentException('Header value must be a string.'); | ||
} | ||
return trim($value, " \t"); | ||
}, $values); | ||
} | ||
|
||
private function assertHeader($header) | ||
{ | ||
if (!is_string($header) || $header === '') { | ||
throw new \InvalidArgumentException('Header must be a non empty string.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: non-empty |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ public function __construct( | |
$body = null, | ||
$version = '1.1' | ||
) { | ||
$this->assertMethod($method); | ||
if (!($uri instanceof UriInterface)) { | ||
$uri = new Uri($uri); | ||
} | ||
|
@@ -91,6 +92,7 @@ public function getMethod() | |
|
||
public function withMethod($method) | ||
{ | ||
$this->assertMethod($method); | ||
$new = clone $this; | ||
$new->method = strtoupper($method); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the tests the strtoupper should not be here.. the current PR targets 1,x.. Can this be fixed on v1. and add the change on the current PR or it should be fixed on version 2.x? |
||
return $new; | ||
|
@@ -139,4 +141,11 @@ private function updateHostFromUri() | |
// See: http://tools.ietf.org/html/rfc7230#section-5.4 | ||
$this->headers = [$header => [$host]] + $this->headers; | ||
} | ||
|
||
private function assertMethod($method) | ||
{ | ||
if (!is_string($method) || $method === '') { | ||
throw new \InvalidArgumentException('Method should be a non empty string.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 method is defined as |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,9 +93,9 @@ public function __construct( | |
$version = '1.1', | ||
$reason = null | ||
) { | ||
if (filter_var($status, FILTER_VALIDATE_INT) === false) { | ||
throw new \InvalidArgumentException('Status code must be an integer value.'); | ||
} | ||
$this->assertStatusCodeIsInteger($status); | ||
$status = (int) $status; | ||
$this->assertStatusCodeRange($status); | ||
|
||
$this->statusCode = (int) $status; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can remove this cast since you casted already a few lines above |
||
|
||
|
@@ -125,12 +125,30 @@ public function getReasonPhrase() | |
|
||
public function withStatus($code, $reasonPhrase = '') | ||
{ | ||
$this->assertStatusCodeIsInteger($code); | ||
$code = (int) $code; | ||
$this->assertStatusCodeRange($code); | ||
|
||
$new = clone $this; | ||
$new->statusCode = (int) $code; | ||
$new->statusCode = $code; | ||
if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { | ||
$reasonPhrase = self::$phrases[$new->statusCode]; | ||
} | ||
$new->reasonPhrase = $reasonPhrase; | ||
return $new; | ||
} | ||
|
||
private function assertStatusCodeIsInteger($statusCode) | ||
{ | ||
if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) { | ||
throw new \InvalidArgumentException('Status code must be an integer value.'); | ||
} | ||
} | ||
|
||
private function assertStatusCodeRange($statusCode) | ||
{ | ||
if ($statusCode < 100 || $statusCode >= 600) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 according to https://tools.ietf.org/html/rfc7231#section-6 |
||
throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory that's correct. But I think it's too risky to add this validation in a minor version, e.g.
withHeader('Api-Version', 1)
would suddenly break for people. Before the integer was simply casted to string which seems like a sensible behavior.So I would remove this validation for now. It might be something to consider for 2.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/zendframework/zend-diactoros/blob/9a4b4a3c78c1a65e6096fb1f37ab424f33c68821/src/HeaderSecurity.php#L138
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this change leads to unexpected exceptions.
$request->getBody()->getSize()
returns integer:https://github.com/guzzle/guzzle/blob/master/src/PrepareBodyMiddleware.php#L57
and any request leads to throwing that exception.