This repository has been archived by the owner on Jan 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added documentation on the BodyParseMiddleware
Followup to zendframework/zend-expressive-helpers#5
- Loading branch information
1 parent
37a3618
commit dc05000
Showing
3 changed files
with
190 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters