Skip to content

Commit a88fd51

Browse files
committed
Make Content-Length addition explicit
1 parent c0aeade commit a88fd51

File tree

4 files changed

+47
-3
lines changed

4 files changed

+47
-3
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9+
## [0.2.3] - 2018-12-18
10+
### Added
11+
- Added a method `HttpClient::enableContentLength()` to enable automatic adding of `Content-Length` header
12+
13+
### Changed
14+
- The `HttpClient` will no longer automatically add the `Content-Length` header unless explicitly requested.
15+
16+
### Fixed
17+
- The `HttpClient` will no longer call the `ServerApi::output()` with empty content
18+
919
## [0.2.2] - 2018-10-17
1020
### Changed
1121
- Now depends on version `^0.3.0` of the `simply/container` library

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"zendframework/zend-diactoros": "^2.0"
3030
},
3131
"require-dev": {
32-
"phpunit/phpunit": "^7.4",
32+
"phpunit/phpunit": "^7.5",
3333
"riimu/php-cs-fixer-config": "^0.1.1",
3434
"riimu/sami-config": "^0.1.0"
3535
},

src/HttpClient.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class HttpClient
2121
/** @var ServerApi The api used to actually communicate to the browser */
2222
private $serverApi;
2323

24+
/** @var bool Whether to automatically detect content length */
25+
private $contentLength;
26+
2427
/**
2528
* HttpClient constructor.
2629
*/
@@ -29,6 +32,7 @@ public function __construct()
2932
$this->omitBody = false;
3033
$this->chunkSize = 8 * 1024;
3134
$this->serverApi = new ServerApi();
35+
$this->contentLength = false;
3236
}
3337

3438
/**
@@ -53,6 +57,15 @@ public function setResponseChunkSize(int $bytes): void
5357
$this->chunkSize = $bytes;
5458
}
5559

60+
/**
61+
* Enables automatic detection of content length and adding the appropriate header.
62+
* @param bool $enable True to enable, false to disable
63+
*/
64+
public function enableContentLength(bool $enable = true): void
65+
{
66+
$this->contentLength = $enable;
67+
}
68+
5669
/**
5770
* Tells the client to omit the body from the response.
5871
* @param bool $omit True to omit the body, false to include it
@@ -107,6 +120,10 @@ private function hasResponseBody(ResponseInterface $response): bool
107120
*/
108121
private function detectLength(ResponseInterface $response): ?int
109122
{
123+
if (! $this->contentLength) {
124+
return null;
125+
}
126+
110127
if ($response->hasHeader('Content-Length')) {
111128
$lengthHeader = $response->getHeader('Content-Length');
112129
return array_shift($lengthHeader);
@@ -154,7 +171,10 @@ private function sendBody(ResponseInterface $response, ?int $length): int
154171
while (!$body->eof()) {
155172
$read = $length === null ? $this->chunkSize : min($this->chunkSize, $length - $bytes);
156173
$output = $body->read($read);
157-
$this->serverApi->output($output);
174+
175+
if ($output !== '') {
176+
$this->serverApi->output($output);
177+
}
158178

159179
$bytes += \strlen($output);
160180

tests/tests/ApplicationTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public function testSuccessfulRouting()
6464

6565
$this->assertSame('Correct Output', $this->sentOutput);
6666
$this->assertContains('Content-Type: text/plain; charset=utf-8', $this->sentHeaders);
67+
$this->assertNotContains('Content-Length', implode("\n", $this->sentHeaders));
6768
}
6869

6970
public function testCallingApplicationTwice()
@@ -180,6 +181,8 @@ public function testHeaderLimitedBody()
180181
['GET', '/limited/', $handler],
181182
]);
182183

184+
$this->getContainerHttpClient()->enableContentLength();
185+
$this->getContainerHttpClient()->setResponseChunkSize(3);
183186
$this->makeRequest('GET', '/limited/');
184187

185188
$this->assertContains('Content-Length: 4', $this->sentHeaders);
@@ -216,6 +219,7 @@ public function testSmallRewindedBody()
216219
['GET', '/path/', $this->getHandler($response)],
217220
]);
218221

222+
$this->getContainerHttpClient()->enableContentLength();
219223
$this->makeRequest('GET', '/path/');
220224

221225
$this->assertContains('Content-Length: 1', $this->sentHeaders);
@@ -260,7 +264,7 @@ public function testUnmockedApplication()
260264
private function makeRequest(string $method, string $path)
261265
{
262266
$this->nextRequest = (new ServerRequestFactory())->createServerRequest($method, $path);
263-
$this->container->get(Application::class)->run();
267+
$this->getContainerApplication()->run();
264268
}
265269

266270
private function buildApplication(array $routes): void
@@ -361,4 +365,14 @@ private function getResponse(string $body, array $headers = null): Response
361365

362366
return $response;
363367
}
368+
369+
private function getContainerApplication(): Application
370+
{
371+
return $this->container->get(Application::class);
372+
}
373+
374+
private function getContainerHttpClient(): HttpClient
375+
{
376+
return $this->container->get(HttpClient::class);
377+
}
364378
}

0 commit comments

Comments
 (0)