Skip to content

Commit

Permalink
Certain status codes never contain a body length
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Mar 30, 2017
1 parent 28c02e0 commit d81fca1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,14 @@ This is just a example you could use of the streaming,
you could also send a big amount of data via little chunks
or use it for body data that needs to calculated.

If the response body is a `string` a `Content-Length` header will be added automatically.
Unless you specify a `Content-Length` header for a ReactPHP `ReadableStreamInterface`
response body yourself, HTTP/1.1 responses will automatically use chunked transfer encoding
and send the respective header
(`Transfer-Encoding: chunked`) automatically. The server is responsible for handling
`Transfer-Encoding` so you SHOULD NOT pass it yourself.
If the response body is a `string`, a `Content-Length` header will be added
automatically.
If the response body is a ReactPHP `ReadableStreamInterface` and you do not
specify a `Content-Length` header, HTTP/1.1 responses will automatically use
chunked transfer encoding and send the respective header
(`Transfer-Encoding: chunked`) automatically.
The server is responsible for handling `Transfer-Encoding` so you SHOULD NOT
pass this header yourself.
If you know the length of your stream body, you MAY specify it like this instead:

```php
Expand All @@ -387,10 +389,18 @@ The `Server` will add the protocol version of the request, so you don't have to.

Any response to a `HEAD` request and any response with a `1xx` (Informational),
`204` (No Content) or `304` (Not Modified) status code will *not* include a
message body as per the HTTP spec.
message body as per the HTTP specs.
This means that your callback does not have to take special care of this and any
response body will simply be ignored.

Similarly, any response with a `1xx` (Informational), `204` (No Content) status
code will *not* include `Content-Length` or `Transfer-Encoding` header as
these do not apply to these messages.
Note that a response to a `HEAD` request and any response with a `304` (Not
Modified) status code MAY include these headers even though
the message does not contain a response body, because these header would apply
to the message if the same request would have used an (unconditional) `GET`.

A `Date` header will be automatically added with the system date and time if none is given.
You can add a custom `Date` header yourself like this:

Expand Down
7 changes: 6 additions & 1 deletion src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,13 @@ public function handleResponse(ConnectionInterface $connection, RequestInterface
$response = $response->withHeader('Connection', 'close');
}

// response to HEAD and 1xx, 204 and 304 responses MUST NOT include a body
// response code 1xx and 204 MUST NOT include Content-Length or Transfer-Encoding header
$code = $response->getStatusCode();
if (($code >= 100 && $code < 200) || $code === 204) {
$response = $response->withoutHeader('Content-Length')->withoutHeader('Transfer-Encoding');
}

// response to HEAD and 1xx, 204 and 304 responses MUST NOT include a body
if ($request->getMethod() === 'HEAD' || ($code >= 100 && $code < 200) || $code === 204 || $code === 304) {
$response = $response->withBody(Psr7Implementation\stream_for(''));
}
Expand Down
4 changes: 3 additions & 1 deletion tests/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ function ($data) use (&$buffer) {
$this->assertNotContains("bye", $buffer);
}

public function testResponseContainsNoResponseBodyForNoContentStatus()
public function testResponseContainsNoResponseBodyAndNoContentLengthForNoContentStatus()
{
$server = new Server($this->socket, function (RequestInterface $request) {
return new Response(204, array(), 'bye');
Expand All @@ -382,6 +382,7 @@ function ($data) use (&$buffer) {
$this->connection->emit('data', array($data));

$this->assertContains("HTTP/1.1 204 No Content\r\n", $buffer);
$this->assertNotContains("\r\n\Content-Length: 3\r\n", $buffer);
$this->assertNotContains("bye", $buffer);
}

Expand Down Expand Up @@ -409,6 +410,7 @@ function ($data) use (&$buffer) {
$this->connection->emit('data', array($data));

$this->assertContains("HTTP/1.1 304 Not Modified\r\n", $buffer);
$this->assertContains("\r\nContent-Length: 3\r\n", $buffer);
$this->assertNotContains("bye", $buffer);
}

Expand Down

0 comments on commit d81fca1

Please sign in to comment.