Skip to content

Commit 4f13747

Browse files
authored
Merge pull request #138 from legionth/handle-cl-tl-response
Remove Transfer-Encoding if Content-Length is given in Response object
2 parents cf7075a + b82e8dd commit 4f13747

File tree

4 files changed

+144
-8
lines changed

4 files changed

+144
-8
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,9 @@ Calling this method after the response has ended/closed is a NOOP.
272272

273273
Unless you specify a `Content-Length` header yourself, HTTP/1.1 responses
274274
will automatically use chunked transfer encoding and send the respective header
275-
(`Transfer-Encoding: chunked`) automatically. If you know the length of your
276-
body, you MAY specify it like this instead:
275+
(`Transfer-Encoding: chunked`) automatically. The server is responsible for handling
276+
`Transfer-Encoding` so you SHOULD NOT pass it yourself.
277+
If you know the length of your body, you MAY specify it like this instead:
277278

278279
```php
279280
$data = 'Hello World!';

src/Response.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,15 @@ public function writeHead($status = 200, array $headers = array())
204204
);
205205
}
206206

207-
// assign chunked transfer-encoding if no 'content-length' is given for HTTP/1.1 responses
208-
if (!isset($lower['content-length']) && $this->protocolVersion === '1.1') {
209-
foreach($headers as $name => $value) {
210-
if (strtolower($name) === 'transfer-encoding') {
211-
unset($headers[$name]);
212-
}
207+
// always remove transfer-encoding
208+
foreach($headers as $name => $value) {
209+
if (strtolower($name) === 'transfer-encoding') {
210+
unset($headers[$name]);
213211
}
212+
}
214213

214+
// assign chunked transfer-encoding if no 'content-length' is given for HTTP/1.1 responses
215+
if (!isset($lower['content-length']) && $this->protocolVersion === '1.1') {
215216
$headers['Transfer-Encoding'] = 'chunked';
216217
$this->chunkedEncoding = true;
217218
}

tests/ResponseTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,4 +596,37 @@ public function testDrainEventShouldBeForwarded()
596596

597597
$input->emit('drain');
598598
}
599+
600+
public function testContentLengthWillBeRemovedIfTransferEncodingIsGiven()
601+
{
602+
$expectedHeader = '';
603+
$expectedHeader .= "HTTP/1.1 200 OK\r\n";
604+
$expectedHeader .= "X-Powered-By: React/alpha\r\n";
605+
$expectedHeader .= "Content-Length: 4\r\n";
606+
$expectedHeader .= "Connection: close\r\n";
607+
$expectedHeader .= "\r\n";
608+
609+
$expectedBody = "hello";
610+
611+
$conn = $this
612+
->getMockBuilder('React\Socket\ConnectionInterface')
613+
->getMock();
614+
$conn
615+
->expects($this->exactly(2))
616+
->method('write')
617+
->withConsecutive(
618+
array($expectedHeader),
619+
array($expectedBody)
620+
);
621+
622+
$response = new Response($conn, '1.1');
623+
$response->writeHead(
624+
200,
625+
array(
626+
'Content-Length' => 4,
627+
'Transfer-Encoding' => 'chunked'
628+
)
629+
);
630+
$response->write('hello');
631+
}
599632
}

tests/ServerTest.php

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,107 @@ public function testRequestWithoutDefinedLengthWillIgnoreDataEvent()
12341234
$this->connection->emit('data', array($data));
12351235
}
12361236

1237+
public function testResponseWillBeChunkDecodedByDefault()
1238+
{
1239+
$server = new Server($this->socket);
1240+
1241+
$server->on('request', function (Request $request, Response $response) {
1242+
$response->writeHead();
1243+
$response->write('hello');
1244+
});
1245+
1246+
$this->connection
1247+
->expects($this->exactly(2))
1248+
->method('write')
1249+
->withConsecutive(
1250+
array($this->anything()),
1251+
array("5\r\nhello\r\n")
1252+
);
1253+
1254+
$this->socket->emit('connection', array($this->connection));
1255+
1256+
$data = $this->createGetRequest();
1257+
1258+
$this->connection->emit('data', array($data));
1259+
}
1260+
1261+
public function testContentLengthWillBeRemovedForResponseStream()
1262+
{
1263+
$server = new Server($this->socket);
1264+
1265+
$server->on('request', function (Request $request, Response $response) {
1266+
$response->writeHead(
1267+
200,
1268+
array(
1269+
'Content-Length' => 4,
1270+
'Transfer-Encoding' => 'chunked'
1271+
)
1272+
);
1273+
1274+
$response->write('hello');
1275+
});
1276+
1277+
$buffer = '';
1278+
$this->connection
1279+
->expects($this->exactly(2))
1280+
->method('write')
1281+
->will(
1282+
$this->returnCallback(
1283+
function ($data) use (&$buffer) {
1284+
$buffer .= $data;
1285+
}
1286+
)
1287+
);
1288+
1289+
$this->socket->emit('connection', array($this->connection));
1290+
1291+
$data = $this->createGetRequest();
1292+
1293+
$this->connection->emit('data', array($data));
1294+
1295+
$this->assertNotContains("Transfer-Encoding: chunked", $buffer);
1296+
$this->assertContains("Content-Length: 4", $buffer);
1297+
$this->assertContains("hello", $buffer);
1298+
}
1299+
1300+
public function testOnlyAllowChunkedEncoding()
1301+
{
1302+
$server = new Server($this->socket);
1303+
1304+
$server->on('request', function (Request $request, Response $response) {
1305+
$response->writeHead(
1306+
200,
1307+
array(
1308+
'Transfer-Encoding' => 'custom'
1309+
)
1310+
);
1311+
1312+
$response->write('hello');
1313+
});
1314+
1315+
$buffer = '';
1316+
$this->connection
1317+
->expects($this->exactly(2))
1318+
->method('write')
1319+
->will(
1320+
$this->returnCallback(
1321+
function ($data) use (&$buffer) {
1322+
$buffer .= $data;
1323+
}
1324+
)
1325+
);
1326+
1327+
$this->socket->emit('connection', array($this->connection));
1328+
1329+
$data = $this->createGetRequest();
1330+
1331+
$this->connection->emit('data', array($data));
1332+
1333+
$this->assertContains('Transfer-Encoding: chunked', $buffer);
1334+
$this->assertNotContains('Transfer-Encoding: custom', $buffer);
1335+
$this->assertContains("5\r\nhello\r\n", $buffer);
1336+
}
1337+
12371338
private function createGetRequest()
12381339
{
12391340
$data = "GET / HTTP/1.1\r\n";

0 commit comments

Comments
 (0)