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

Commit

Permalink
Added documentation on the BodyParseMiddleware
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Dec 22, 2015
1 parent 37a3618 commit dc05000
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 2 deletions.
187 changes: 187 additions & 0 deletions doc/book/helpers/body-parse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# BodyParse Middleware

`Zend\Expressive\Helper\BodyParse\BodyParseMiddleware` provides generic PSR-7
middleware for parsing the request body into parameters, and returning a new
request instance that composes them. The subcomponent provides a strategy
pattern around matching the request `Content-Type`, and then parsing it, giving
you a flexibile approach that can grow with your accepted content types.

By default, this middleware will detect the following content types:

- `application/x-www-form-urlencoded` (standard web-based forms, without file
uploads)
- `application/json`, `application/*+json` (JSON payloads)

## Registering the middleware

You can register it manually:

```php
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;

$app->pipe(BodyParamsMiddleware::class);

// register other middleware
// register routing middleware
$app->run();
```

or as `pre_routing` pipeline middleware:

```php
// config/autoload/middleware-pipeline.global.php
use Zend\Expressive\Helper;

return [
'dependencies' => [
'invokables' => [
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
/* ... */
],
'factories' => [
/* ... */
],
],
'middleware_pipeline' => [
'pre_routing' => [
[ 'middleware' => Helper\BodyParams\BodyParamsMiddleware::class ],
/* ... */
],
'post_routing' => [
/* ... */
],
],
];
```

Another option is to incorporate it in route-specific middleware queues:

```php
// config/autoload/routes.global.php
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;

return [
'dependencies' => [
'invokables' => [
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
/* ... */
],
'factories' => [
/* ... */
],
],
'routes' => [
[
'name' => 'contact:process',
'path' => '/contact/process',
'middleware' => [
BodyParamsMiddleware::class,
Contact\Process::class,
],
'allowed_methods' => ['POST'],
]
],
];
```

This latter approach has a slight advantage: the middleware will only execute
for routes that require the processing. While the middleware has some checks to
ensure it only triggers for HTTP methods that accept bodies, those checks are
still overhead that you might want to avoid; the above strategy of using the
middleware only with specific routes can accomplish that.

## Strategies

If you want to intercept and parse other payload types, you can add *strategies*
to the middleware. Strategies implement `Zend\Expressive\Helper\BodyParams\StrategyInterface`:

```php
namespace Zend\Expressive\Helper\BodyParams;

use Psr\Http\Message\ServerRequestInterface;

interface StrategyInterface
{
/**
* Match the content type to the strategy criteria.
*
* @param string $contentType
* @return bool Whether or not the strategy matches.
*/
public function match($contentType);

/**
* Parse the body content and return a new response.
*
* @param ServerRequestInterface $request
* @return ServerRequestInterface
*/
public function parse(ServerRequestInterface $request);
}
```

You then register them with the middleware using the `addStrategy()` method:

```php
$bodyParams->addStrategy(new MyCustomBodyParamsStrategy());
```

To automate the registration, we recommend writing a factory for the
`BodyParamsMiddleware`, and replacing the `invokables` registration with a
registration in the `factories` section of the `middleware-pipeline.config.php`
file:

```php
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;

class MyCustomBodyParamsStrategyFactory
{
public function __invoke($container)
{
$bodyParams = new BodyParamsMiddleware();
$bodyParams->addStrategy(new MyCustomBodyParamsStrategy());
return $bodyParams;
}
}

// In config/autoload/middleware-pipeline.config.php:
use Zend\Expressive\Helper;

return [
'dependencies' => [
'invokables' => [
// Remove this line:
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
/* ... */
],
'factories' => [
// Add this line:
Helper\BodyParams\BodyParamsMiddleware::class => MyCustomBodyParamsStrategy::class,
/* ... */
],
],
];
```

## Removing the default strategies

By default, `BodyParamsMiddleware` composes the following strategies:

- `Zend\Expressive\Helper\BodyParams\FormUrlEncodedStrategy`
- `Zend\Expressive\Helper\BodyParams\JsonStrategy`

These provide the most basic approaches to parsing the request body. They
operate in the order they do to ensure the most common content type —
`application/x-www-form-urlencoded` — matches first, as the middleware
delegates parsing to the first match.

If you do not want to use these default strategies, you can clear them from the
middleware using `clearStrategies()`:

```php
$bodyParamsMiddleware->clearStrategies();
```

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.
3 changes: 2 additions & 1 deletion doc/book/helpers/bookdown.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"content": [
{"Introduction": "intro.md"},
{"UrlHelper": "url-helper.md"},
{"ServerUrlHelper": "server-url-helper.md"}
{"ServerUrlHelper": "server-url-helper.md"},
{"Body Parsing Middleware": "body-parse.md"}
]
}
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pages:
- { 'Routing Adapters': [{ Introduction: router/intro.md }, { 'Routing Interface': router/interface.md }, { 'URI Generation': router/uri-generation.md }, { 'Route Result Observers': router/result-observers.md }, { 'Routing vs Piping': router/piping.md }, { 'Using Aura': router/aura.md }, { 'Using FastRoute': router/fast-route.md }, { 'Using the ZF2 Router': router/zf2.md }] }
- { Templating: [{ Introduction: template/intro.md }, { 'Template Renderer Interface': template/interface.md }, { 'Templated Middleware': template/middleware.md }, { 'Using Plates': template/plates.md }, { 'Using Twig': template/twig.md }, { 'Using zend-view': template/zend-view.md }] }
- { 'Error Handling': error-handling.md }
- { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }] }
- { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }, { 'Body Parsing Middleware': helpers/body-parse.md }] }
- { Emitters: emitters.md }
- { Examples: usage-examples.md }
- { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }, { 'Using Expressive from a subdirectory': cookbook/using-a-base-path.md }, { 'Building modular applications': cookbook/modular-layout.md }] }
Expand Down

0 comments on commit dc05000

Please sign in to comment.