Skip to content

Commit aa47f5c

Browse files
authored
Merge pull request #128 from clue-labs/send-close
Explicitly send Connection: close header for HTTP/1.1 messages
2 parents b90e080 + c72c125 commit aa47f5c

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ $response->writeHead(200, array(
283283
));
284284
```
285285

286+
Note that persistent connections (`Connection: keep-alive`) are currently
287+
not supported.
288+
As such, HTTP/1.1 response messages will automatically include a
289+
`Connection: close` header, irrespective of what header values are
290+
passed explicitly.
291+
286292
## Install
287293

288294
The recommended way to install this library is [through Composer](http://getcomposer.org).

src/Response.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ public function writeContinue()
172172
* ));
173173
* ```
174174
*
175+
* Note that persistent connections (`Connection: keep-alive`) are currently
176+
* not supported.
177+
* As such, HTTP/1.1 response messages will automatically include a
178+
* `Connection: close` header, irrespective of what header values are
179+
* passed explicitly.
180+
*
175181
* @param int $status
176182
* @param array $headers
177183
* @throws \Exception
@@ -204,6 +210,18 @@ public function writeHead($status = 200, array $headers = array())
204210
$this->chunkedEncoding = true;
205211
}
206212

213+
// HTTP/1.1 assumes persistent connection support by default
214+
// we do not support persistent connections, so let the client know
215+
if ($this->protocolVersion === '1.1') {
216+
foreach($headers as $name => $value) {
217+
if (strtolower($name) === 'connection') {
218+
unset($headers[$name]);
219+
}
220+
}
221+
222+
$headers['Connection'] = 'close';
223+
}
224+
207225
$data = $this->formatHead($status, $headers);
208226
$this->conn->write($data);
209227

tests/ResponseTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function testResponseShouldBeChunkedByDefault()
1212
$expected .= "HTTP/1.1 200 OK\r\n";
1313
$expected .= "X-Powered-By: React/alpha\r\n";
1414
$expected .= "Transfer-Encoding: chunked\r\n";
15+
$expected .= "Connection: close\r\n";
1516
$expected .= "\r\n";
1617

1718
$conn = $this
@@ -51,6 +52,7 @@ public function testResponseShouldBeChunkedEvenWithOtherTransferEncoding()
5152
$expected .= "HTTP/1.1 200 OK\r\n";
5253
$expected .= "X-Powered-By: React/alpha\r\n";
5354
$expected .= "Transfer-Encoding: chunked\r\n";
55+
$expected .= "Connection: close\r\n";
5456
$expected .= "\r\n";
5557

5658
$conn = $this
@@ -71,6 +73,7 @@ public function testResponseShouldNotBeChunkedWithContentLength()
7173
$expected .= "HTTP/1.1 200 OK\r\n";
7274
$expected .= "X-Powered-By: React/alpha\r\n";
7375
$expected .= "Content-Length: 22\r\n";
76+
$expected .= "Connection: close\r\n";
7477
$expected .= "\r\n";
7578

7679
$conn = $this
@@ -91,6 +94,7 @@ public function testResponseShouldNotBeChunkedWithContentLengthCaseInsensitive()
9194
$expected .= "HTTP/1.1 200 OK\r\n";
9295
$expected .= "X-Powered-By: React/alpha\r\n";
9396
$expected .= "CONTENT-LENGTH: 0\r\n";
97+
$expected .= "Connection: close\r\n";
9498
$expected .= "\r\n";
9599

96100
$conn = $this
@@ -111,6 +115,7 @@ public function testResponseShouldIncludeCustomByPoweredAsFirstHeaderIfGivenExpl
111115
$expected .= "HTTP/1.1 200 OK\r\n";
112116
$expected .= "Content-Length: 0\r\n";
113117
$expected .= "X-POWERED-BY: demo\r\n";
118+
$expected .= "Connection: close\r\n";
114119
$expected .= "\r\n";
115120

116121
$conn = $this
@@ -130,6 +135,7 @@ public function testResponseShouldNotIncludePoweredByIfGivenEmptyArray()
130135
$expected = '';
131136
$expected .= "HTTP/1.1 200 OK\r\n";
132137
$expected .= "Content-Length: 0\r\n";
138+
$expected .= "Connection: close\r\n";
133139
$expected .= "\r\n";
134140

135141
$conn = $this
@@ -144,6 +150,27 @@ public function testResponseShouldNotIncludePoweredByIfGivenEmptyArray()
144150
$response->writeHead(200, array('Content-Length' => 0, 'X-Powered-By' => array()));
145151
}
146152

153+
public function testResponseShouldAlwaysIncludeConnectionCloseIrrespectiveOfExplicitValue()
154+
{
155+
$expected = '';
156+
$expected .= "HTTP/1.1 200 OK\r\n";
157+
$expected .= "X-Powered-By: React/alpha\r\n";
158+
$expected .= "Content-Length: 0\r\n";
159+
$expected .= "Connection: close\r\n";
160+
$expected .= "\r\n";
161+
162+
$conn = $this
163+
->getMockBuilder('React\Socket\ConnectionInterface')
164+
->getMock();
165+
$conn
166+
->expects($this->once())
167+
->method('write')
168+
->with($expected);
169+
170+
$response = new Response($conn);
171+
$response->writeHead(200, array('Content-Length' => 0, 'connection' => 'ignored'));
172+
}
173+
147174
public function testResponseBodyShouldBeChunkedCorrectly()
148175
{
149176
$conn = $this
@@ -283,6 +310,7 @@ public function shouldRemoveNewlinesFromHeaders()
283310
$expected .= "X-Powered-By: React/alpha\r\n";
284311
$expected .= "FooBar: BazQux\r\n";
285312
$expected .= "Transfer-Encoding: chunked\r\n";
313+
$expected .= "Connection: close\r\n";
286314
$expected .= "\r\n";
287315

288316
$conn = $this
@@ -304,6 +332,7 @@ public function missingStatusCodeTextShouldResultInNumberOnlyStatus()
304332
$expected .= "HTTP/1.1 700 \r\n";
305333
$expected .= "X-Powered-By: React/alpha\r\n";
306334
$expected .= "Transfer-Encoding: chunked\r\n";
335+
$expected .= "Connection: close\r\n";
307336
$expected .= "\r\n";
308337

309338
$conn = $this
@@ -327,6 +356,7 @@ public function shouldAllowArrayHeaderValues()
327356
$expected .= "Set-Cookie: foo=bar\r\n";
328357
$expected .= "Set-Cookie: bar=baz\r\n";
329358
$expected .= "Transfer-Encoding: chunked\r\n";
359+
$expected .= "Connection: close\r\n";
330360
$expected .= "\r\n";
331361

332362
$conn = $this
@@ -348,6 +378,7 @@ public function shouldIgnoreHeadersWithNullValues()
348378
$expected .= "HTTP/1.1 200 OK\r\n";
349379
$expected .= "X-Powered-By: React/alpha\r\n";
350380
$expected .= "Transfer-Encoding: chunked\r\n";
381+
$expected .= "Connection: close\r\n";
351382
$expected .= "\r\n";
352383

353384
$conn = $this

0 commit comments

Comments
 (0)