Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
Merge branch 'feature/content-length-middleware' into develop
Browse files Browse the repository at this point in the history
Close #45
  • Loading branch information
weierophinney committed Sep 11, 2017
2 parents 788ac67 + d63ea4c commit 14836cc
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 3 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 4.1.0 - TBD
## 4.1.0 - 2017-09-11

### Added

- Nothing.
- [#45](https://github.com/zendframework/zend-expressive-helpers/pull/45) adds
`Zend\Expressive\Helper\ContentLengthMiddleware`. This middleware will inject
a `Content-Length` response header if none already exists and the response
body size is non-null.

### Deprecated

Expand Down
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,63 @@ Note: if you do this, **all** strategies will be removed! As such, we recommend
doing this only immediately before registering any custom strategies you might
be using.

### Content-Length middleware

In some cases, you may want to include an explicit `Content-Length` response
header, without having to inject it manually. To facilitate this, we provide
`Zend\Expressive\Helper\ContentLengthMiddleware`.

This middleware delegates the request, and operates on the returned response. It
will return a new response with the `Content-Length` header injected under the
following conditions:

- No `Content-Length` header is already present AND
- the body size is non-null.

To register it in your application, you will need to do two things: register the
middleware with the container, and register the middleware in either your
application pipeline, or within routed middleware.

To add it to your container, add the following configuration:

```php
// In a `config/autoload/*.global.php` file, or a `ConfigProvider` class:

use Zend\Expressive\Helper;

return [
'dependencies' => [
'invokables' => [
Helper\ContentLengthMiddleware::class => Helper\ContentLengthMiddleware::class,
],
],
];
```

To register it as pipeline middleware to execute on any request:

```php
// In `config/pipeline.php`:

use Zend\Expressive\Helper;

$app->pipe(Helper\ContentLengthMiddleware::class);
```

To register it within a routed middleware pipeline:

```php
// In `config/routes.php`:

use Zend\Expressive\Helper;

$app->get('/download/tarball', [
Helper\ContentLengthMiddleware::class,
Download\Tarball::class,
], 'download-tar');
```

## Documentation

See the [zend-expressive](https://github.com/zendframework/zend-expressive/blob/master/doc/book)
documentation tree, or browse online at http://zend-expressive.rtfd.org.
documentation tree, or browse online at https://docs.zendframework.com/zend-expressive/features/helpers/intro/
40 changes: 40 additions & 0 deletions src/ContentLengthMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* @see https://github.com/zendframework/zend-expressive-helpers for the canonical source repository
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-expressive-helpers/blob/master/LICENSE.md New BSD License
*/

namespace Zend\Expressive\Helper;

use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
* Middleware to inject a Content-Length response header.
*
* If the response returned by a delegate does not contain a Content-Length
* header, and the body size is non-null, this middleware will return a new
* response that contains a Content-Length header based on the body size.
*/
class ContentLengthMiddleware implements MiddlewareInterface
{
/**
* {@inheritDoc}
*/
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
$response = $delegate->process($request);
if ($response->hasHeader('Content-Length')) {
return $response;
}

$body = $response->getBody();
if (null === $body->getSize()) {
return $response;
}

return $response->withHeader('Content-Length', (string) $body->getSize());
}
}
59 changes: 59 additions & 0 deletions test/ContentLengthMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* @see https://github.com/zendframework/zend-expressive-helpers for the canonical source repository
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-expressive-helpers/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\Expressive\Helper;

use Interop\Http\ServerMiddleware\DelegateInterface;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use Zend\Expressive\Helper\ContentLengthMiddleware;

class ContentLengthMiddlewareTest extends TestCase
{
public function setUp()
{
$this->response = $response = $this->prophesize(ResponseInterface::class);
$this->request = $request = $this->prophesize(ServerRequestInterface::class)->reveal();
$this->stream = $this->prophesize(StreamInterface::class);

$delegate = $this->prophesize(DelegateInterface::class);
$delegate->process($request)->will([$response, 'reveal']);
$this->delegate = $delegate->reveal();

$this->middleware = new ContentLengthMiddleware();
}

public function testReturnsResponseVerbatimIfContentLengthHeaderPresent()
{
$this->response->hasHeader('Content-Length')->willReturn(true);
$response = $this->middleware->process($this->request, $this->delegate);
$this->assertSame($this->response->reveal(), $response);
}

public function testReturnsResponseVerbatimIfContentLengthHeaderNotPresentAndBodySizeIsNull()
{
$this->stream->getSize()->willReturn(null);
$this->response->hasHeader('Content-Length')->willReturn(false);
$this->response->getBody()->will([$this->stream, 'reveal']);

$response = $this->middleware->process($this->request, $this->delegate);
$this->assertSame($this->response->reveal(), $response);
}

public function testReturnsResponseWithContentLengthHeaderBasedOnBodySize()
{
$this->stream->getSize()->willReturn(42);
$this->response->hasHeader('Content-Length')->willReturn(false);
$this->response->getBody()->will([$this->stream, 'reveal']);
$this->response->withHeader('Content-Length', '42')->will([$this->response, 'reveal']);

$response = $this->middleware->process($this->request, $this->delegate);
$this->assertSame($this->response->reveal(), $response);
}
}

0 comments on commit 14836cc

Please sign in to comment.