-
Notifications
You must be signed in to change notification settings - Fork 195
Refactor: extract middleware marshaling, routing, and app running #543
Refactor: extract middleware marshaling, routing, and app running #543
Conversation
@@ -9,6 +9,7 @@ | |||
|
|||
namespace Zend\Expressive; | |||
|
|||
use Psr\Http\Server\MiddlewareInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MiddlewareInterface is not used.
src/Container/ApplicationFactory.php
Outdated
: null; | ||
|
||
$emitter = $container->has(EmitterInterface::class) | ||
? $container->get(EmitterInterface::class) | ||
: null; | ||
|
||
$app = new Application($router, $container, $delegate, $emitter); | ||
$response = $container->has(ResponseInterface::class) | ||
? $container->get(ResponseInterface::class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ResponseInterface needs import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -9,11 +9,11 @@ | |||
|
|||
namespace Zend\Expressive\Middleware; | |||
|
|||
use Interop\Http\Server\MiddlewareInterface; | |||
use Interop\Http\Server\RequestHandlerInterface; | |||
use Psr\Container\ContainerInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ContainerInterface not used.
use Psr\Container\ContainerInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Psr\Http\Server\MiddlewareInterface; | ||
use Psr\Http\Server\RequestHandlerInterface; | ||
use Zend\Expressive\MarshalMiddlewareTrait; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MarshalMiddlewareTrait doesn't exist.
use Psr\Container\ContainerInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Psr\Http\Server\MiddlewareInterface; | ||
use Psr\Http\Server\RequestHandlerInterface; | ||
use Zend\Expressive\MarshalMiddlewareTrait; | ||
use Zend\Expressive\Router\RouteResult; | ||
use Zend\Expressive\Router\RouterInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RouterInterface isn't used.
composer.json
Outdated
"psr/container": "^1.0", | ||
"psr/http-message": "^1.0.1", | ||
"psr/http-server-middleware": "^1.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually we use just ^1.0
.
src/Application.php
Outdated
{ | ||
return $this->route($path, $middleware, ['POST'], $name); | ||
try { | ||
$request = $request ?: ServerRequestFactory::fromGlobals(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One space before =
please
src/Application.php
Outdated
} | ||
|
||
/** | ||
* @param callable|string $middleware Middleware (or middleware service name) to associate with route. | ||
* @param null|string $name The name of the route. | ||
* @param string|array|callable|MiddlewareInterface $middleware Middleware |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I've suggested in another place order of types - null|(simple types in alphabetical order)|(complex types in alphabetical order)
- so here we should have array|callable|string|MiddlewareInterface
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue for the following order:
null
- all other scalar types, in alphabetical order
- complex built-in types (
array
,callable
,resource
) in alphabetical order - instance types, in alphabetical order
So, clearly we have differing opinions, and we'll need to make a decision. In the meantime, this is not the main point of this PR at this time; I need feedback on architecture and design.
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com) | ||
* @license https://github.com/zendframework/zend-expressive/blob/master/LICENSE.md New BSD License | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No new line before strict_type declaration please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@webimpress let's try reducing noise over CS by moving these discussions to the CS checks repo instead 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also little bit unhappy with this type of comments. Because the first comments are always related to the coding standard. After the noise, there are often no other comments. CS is important, but code formatting should not have the first place in this and other discussions. (imo)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coding Standard Police 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is why we need proper CS for zf and then we are not going to have these comments at all. Sorry, I'm adding comments about everything I can see at the beginning because otherwise (it happened already couple times) it could be merged without fixing...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@webimpress
Sorry, my comment was not only for you. It was a hint to: zendframework/zend-coding-standard/pull/1
ping @weierophinney
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry guys, actually I was wrong... Probably we should keep the line. See my comments there:
zendframework/zend-expressive-aurarouter#30 (comment)
{ | ||
public function __invoke(ContainerInterface $container) : DispatchMiddleware | ||
{ | ||
return new DispatchMiddleware(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need that factory? Isn't it invokable
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is invokable, but it may not always be. Additionally, having it here simplifies how we refer to it when writing configuration for different container types.
} | ||
|
||
/** | ||
* @var mixed $service The actual service created by the container. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@param
instead of @var
please
src/MiddlewareFactory.php
Outdated
return $this->pipeline(...$middleware); | ||
} | ||
|
||
if ((! is_string($middleware) || empty($middleware))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove one pair of parentheses and the second part can be just ! $middleware
src/MiddlewareFactory.php
Outdated
{ | ||
if (! $this->container) { | ||
throw new Exception\ContainerNotRegisteredException(sprintf( | ||
'Cannot marshal middleware by service name "%s"; no container registered', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it should be moved to the static method in the exception?
src/MiddlewareFactory.php
Outdated
|
||
public function __construct(ContainerInterface $container = null) | ||
{ | ||
$this->container = $container ? new MiddlewareContainer($container) : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better testability we should pass MiddlewareContainer
as param instead of creating one in the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes usability harder, however, as developers who are creating an instance on the fly now need to do the following:
$factory = new MiddlewareFactory(new MiddlewareContainer($app->getContainer()));
Additionally, the above example I present would fail with an E_FATAL
if $app->getContainer()
returns null
(which is possible currently), which means it technically needs to become:
$factory = new MiddlewareFactory(
$app->getContainer()
? new MiddlewareContainer($app->getContainer())
: null
);
which is not user friendly at all. (FTR, if the middleware in a specification or a pipeline resolves to an constructor-less class, a callable, or a MiddlewareInterface
instance, the factory can still do its work; it's only if a service name is used that the container becomes necessary. At that point, it raises an exception when a container is missing.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've since changed this to accept only a MiddlewareContainer
instance.
<?php | ||
/** | ||
* @see https://github.com/zendframework/zend-expressive for the canonical source repository | ||
* @copyright Copyright (c) 2016-2017 Zend Technologies USA Inc. (https://www.zend.com) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2018 only, please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was renamed from NotFoundHandler
; date range is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you use git mv
to rename the file? We are loosing the connection between new and old file, it looks like new file...
Shouldn't we update year range as the file is updated (renamed)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
best way is to move file 100% unchanged, and then edit it in another commit as git does not really have "move" type of change. Simple diff might not detect it anyway as it uses similarity threshold. It is more for a 3-way merge benefit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... or use PhpStorm :D
It keeps track of moved files (most of the time) so you can move and edit it in the same commit. Not sure how to do that in git. But as PhpStorm can do it, it must be doable with git as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a git mv
, but then also added the new file in the same commit, which is why this happened.
Note to self: be more granular in commits.
Do we need it? Maybe we should just register these type of middlewares as invokable in container? |
src/MiddlewareFactory.php
Outdated
* | ||
* @param string|array|MiddlewareInterface $middleware | ||
*/ | ||
public function path(string $path, $middleware) : PathMiddlewareDecorator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the same way we should add method host
?
I'm looking again through the code, and it doesn't to be right, imho. Looks like we can do the same things in multiple ways now, and it's confusing. I think we should deliver simple interface for devs. Need a bit more time to think about it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm considering removing the path()
method, as the same can be accomplished with the following:
use function Zend\Stratigility\path;
$app->pipe(path('/api', $factory->prepare($middleware));
If we keep the methods down to only those needed for preparing middleware of different types (prepare()
, callable()
, lazy()
) and pipelines (pipeline()
), we can use these with any of the various decorator classes and/or their related utility functions. That means we can add new decorators and utility functions in Stratigility or Expressive, and they're automatically supported.
Ideally, that's what we'd do. However, that poses a few problems:
We can largely solve the second use case via the zend-expressive-tooling project; in fact, there is an open issue requesting creation of a factory when middleware:create is called. The first is harder, however; unless we can write a tool to solve that migration problem, it's simpler to have the dedicated container. The third case, however, is probably the more winning argument here, as it ensures that we only fetch middleware in the context of marshaling middleware for the pipeline and/or routing. |
@Ocramius , @froschdesign , @webimpress, @ezimuel, @xtreamwayz — any feedback on design/implementation? Thoughts I've had since implementing (some of which are due to discussions with @ezimuel and @xtreamwayz):
Essentially, for users upgrading from v2, we'd update their $app = $container->get(Application::class);
$factory = $container->get(MiddlewareFactory::class);
$routes = $container->get(RouteMiddleware::class);
require 'config/pipeline.php';
require 'config/routes.php'; These files would then look like the following: // config/pipeline.php:
use function Zend\Stratigility\path;
$app->pipe($factory->lazy(ErrorMiddleware::class));
$app->pipe(path('/api', $factory->pipeline(
CorsMiddleware::class,
AuthenticationMiddleware::class,
AuthorizationMiddleware::class
));
// Since we already have it instantiated, we can pipe the routing middleware as
// an instance:
$app->pipe($routes);
$app->pipe($factory->lazy(ImplicitHeadMiddleware::class));
$app->pipe($factory->lazy(ImplicitOptionsMiddleware::class));
$app->pipe($factory->lazy(DispatchMiddleware::class));
$app->pipe($factory->lazy(NotFoundMiddleware::class));
// config/routes.php:
$routes->get('/', $factory->lazy(HomeMiddleware::class));
$routes->post('/api/books', $factory->pipeline(
BookValidationMiddleware::class,
CreateBookMiddleware::class
)); Essentially, separating these concerns further means we can have more type-safety, less overall code, and more flexibility for users. The proxy class provides both a migration tool, but also potentially a usability layer for developers who do not want to always use the factory to prepare middleware for piping or routing, but instead just provide the arguments. Updates
|
About everything you write sounds good. I'm not sure about the The proxy class for backward compatibility sounds good as well. |
The $runner = $container->get(ApplicationRunner::class);
$runner->run(); Internally, |
May i suggest a following change: (require 'config/pipeline.php')($app, $factory, $router);
(require 'config/routes.php')($app, $factory, $router); use Zend\Expressive\Application;
use function Zend\Stratigility\path;
return function (Application $app, MiddlewareFactory $factory, RouteMiddleware $routes) {
$app->pipe(ErrorMiddleware::class);
$app->pipe(path('/api', $factory->pipeline(
CorsMiddleware::class,
AuthenticationMiddleware::class,
AuthorizationMiddleware::class
));
// Since we already have it instantiated, we can pipe the routing middleware as
// an instance:
$app->pipe($routes);
$app->pipe(ImplicitHeadMiddleware::class);
$app->pipe(ImplicitOptionsMiddleware::class);
$app->pipe(DispatchMiddleware::class);
$app->pipe(NotFoundMiddleware::class);
} |
I really like that idea! |
This is a good functionality to be split into separate package to be used with any request handler. |
You have shown me this before. I really like it. |
The pattern used to be very common in node, before the |
@weierophinney I really like the idea of having routes specified on a I see the need for a $app->pipe(path('/api', $factory->pipeline(
CorsMiddleware::class,
AuthenticationMiddleware::class,
AuthorizationMiddleware::class
))); I think we should continue to support array as a way to specify a pipeline. I think this is a very intuitive idea to think about an ordered sequence of middleware (a pipeline). I would like to propose this change: $app->pipe(path('/api, [
CorsMiddleware::class,
AuthenticationMiddleware::class,
AuthorizationMiddleware::class
])); We can accomplish this managing the array of middleware in the This routing is very intuitive, even for people not familiar with Expressive: $routes->post('/api/books', [
BookValidationMiddleware::class,
CreateBookMiddleware::class
]); Regarding the other proposals, I'm in favor of it. It will be awesome to see a complete skeleton application to analyze the changes from a user API point of view. |
I'm just about done handling the changes as suggested in my previous large design comment, and in doing so, discovered something interesting: separating the routing concerns, removing the application running concerns, and making the As such, I'm re-creating the
The class then implements both What's interesting about this approach is that it keeps the existing signatures and API entirely. This then moves the discussion to: how do we want to write the skeleton? It could literally stay exactly the same as it is currently. Alternately, we could do like @Xerkus suggested above, and have the routes and pipeline files return callbacks that accept specific arguments (likely the middleware factory, and then one of either the middleware pipeline or route middleware). What's interesting to me is that this refactoring exercise leaves us with far more flexibility; simpler, more maintainable code; stronger typing; and choice in how we have users consume the project. Once the changes are complete, I'll push here. |
All major refactors are now complete. The only bits I'm mulling over at this time are:
Thoughts on these proposals and/or the shape of the refactor at this time? |
src/MiddlewareFactory.php
Outdated
* Creates and returns a PathMiddlewareDecorator instance after first | ||
* passing the $middleware argument to prepare(). | ||
* | ||
* @param string|array|MiddlewareInterface $middleware |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing @param for first parameter. I don't know if all IDEs will interpret this properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is standard across major IDEs, at this point, and phpdocumentor infers types from typehints as well. We've already decided for zend-coding-standard to require annotations only if they're adding information, or the type is unspecified.
return new ApplicationRunner( | ||
$container->get(Application::class), | ||
$container->get(EmitterInterface::class), | ||
$container->get(ServerRequestFactory::class), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ServerRequestFactory and ServerRequestErrorResponseGenerator are not real classes, shouldn't they be used as string literals?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I go back and forth on this, particularly when the service namespace doesn't match the current one.
We can address later.
use Psr\Container\ContainerInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Zend\Expressive\Middleware\RouteMiddleware; | ||
use Zend\Expressive\Router\RouteInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, should be RouterInterface
src/Middleware/RouteMiddleware.php
Outdated
* Add a route for the route middleware to match. | ||
* | ||
* Accepts either a Route instance, or a combination of a path and | ||
* middleware, and optionally the HTTP methods allowed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This description is wrong, Route instance is not accepted
I'm 👍 for this. IMHO the For the shape of the refactor, I need to review it with more time tomorrow, if you can wait one more day before merging. I missed the notification of this PR. 😄 Just a few comments from what I've read so far:
btw, congrats for the great work done in PSR-15 and Expressive 3 :) |
@Xerkus has indicated he could use this for the zend-mvc refactor as well, so we will definitely extract it. My thought is to also extract the emitter interface and emitters from zend-stratigility either into their own package, or into the same package as the runner (which will consume them).
This makes usage more difficult within the I'll think on it.
The My thought is that we could bring the If we were to go that route, I'd suggest:
Thoughts on that approach, @danizord? |
…onseGenerator This is what I'd intended originally.
This patch provides a ConfigProvider, which will allow offloading much of the initial configuration provided in the skeleton to the component itself.
Instead of using `path()` to create a `PathMiddlewareDecorator`, just `pipe()` both arguments to the `Application` instance. To make this work properly, the patch also does some additional logic to no longer create a `PathMiddlewareDecorator` if the the `$path` is `/`.
Also, discovered test case file did not reflect its class name.
This delegator factory decorates the application instance created by the callback by injecting a pipeline and routes based on configuration pulled from the container. The functionality is directly from the ApplicationConfigInjectionTrait, which we can deprecate and remove now that this functionality is in place.
This functionality is now in the ApplicationConfigInjectionDelegator.
This patch marks the two public injection methods in the delegator factory as static, allowing them to be used without instantiating the factory. It also correctly places the tests for the delegator factory, and moves required test assests in a tree beneath it.
This is better accomplished using `Zend\Stratigility\path()` + the factory.
The return type could potentially NOT be an `Application` in the situation that `$callback` returns something else.
…ssive-router v3 This patch updates zend-expressive to consume the `DispatchMiddleware` and `PathBasedRoutingMiddleware` classes from zend-expressive-router v3.0.0alpha1 and up. Doing so allows removal of those classes and related tests from this package, but requires: - `Application` now needs to depend on `PathBasedRoutingMiddleware` - `ApplicationConfigInjectionDelegator` needs to use the new classes when injecting routing and dispatch middleware. - tests needed updating to refer to the new classes.
This patch removes the `ApplicationRunner`, and replaces it with zend-httphandlerrunner's `RequestHandlerInterface` and emitters.
This patch updates the `MiddlewareContainer` and `MiddlewareFactory` to allow them to detect PSR-15 request handlers, and decorate them using zend-stratigility's `RequestHandlerMiddleware`. This ensures type-safety when used in either pipelines or with routed middleware, but also ensures we can use the full-spectrum of available handlers with the system. A new method was also added to `MiddlewareFactory`: `handler()`. This method accepts a `RequestHandlerInterface` instance and returns a `RequestHandlerMiddleware` instance decorating it, making it simple to use request handlers with the explicit functionality of zend-expressive-router's `PathBasedRoutingMiddleware` API.
4d5ea20
to
4d5fb79
Compare
Removes the zendframework#543 entry indicating the changed `NotFoundDelegate`, instead adding a "Removed" entry for that class. Updates the "Changed" entry for the `NotFoundMiddleware` to indicate its new constructor arguments.
Removes the zendframework#543 entry indicating the changed `NotFoundDelegate`, instead adding a "Removed" entry for that class. Updates the "Changed" entry for the `NotFoundMiddleware` to indicate its new constructor arguments.
Removes the zendframework#543 entry indicating the changed `NotFoundDelegate`, instead adding a "Removed" entry for that class. Updates the "Changed" entry for the `NotFoundMiddleware` to indicate its new constructor arguments.
This patch implements an idea [proposed by @Xerkus](zendframework/zend-expressive#543 (comment)): having the `pipeline.php` and `routes.php` files return _closures_, and updating `public/index.php` to capitalize on that in order to pass in arguments. In this particular case, we pass the application, middleware factory, and PSR-11 container instances as arguments. This provides developers with all the tools they should need in order to create the pipeline and/or routes.
This patch implements an idea [proposed by @Xerkus](zendframework/zend-expressive#543 (comment)): having the `pipeline.php` and `routes.php` files return _closures_, and updating `public/index.php` to capitalize on that in order to pass in arguments. In this particular case, we pass the application, middleware factory, and PSR-11 container instances as arguments. This provides developers with all the tools they should need in order to create the pipeline and/or routes.
This patch implements an idea [proposed by @Xerkus](zendframework/zend-expressive#543 (comment)): having the `pipeline.php` and `routes.php` files return _closures_, and updating `public/index.php` to capitalize on that in order to pass in arguments. In this particular case, we pass the application, middleware factory, and PSR-11 container instances as arguments. This provides developers with all the tools they should need in order to create the pipeline and/or routes.
This patch implements the changes as outlined in the RFC: Expressive 3 Design Changes, as well as those as outlined in this comment and this comment, below.
In particular:
Updates to consume and implement PSR-15.
The following changes were made to middleware marshaling:
A new class,
MiddlewareContainer
, implementing PSR-11'sContainerInterface
and decorating aContainerInterface
. This class ensures that middleware pulled from the container implements the PSR-15MiddlewareInterface
. It also allows retrieving middleware by class name if the class does not require constructor arguments.A new class,
MiddlewareFactory
, accepts a PSR-11ContainerInterface
to its constructor, which it decorates internally as aMiddlewareContainer
. It then exposes methods for marshaling middleware:callable(callable $middleware) : CallableMiddlewareDecorator
lazy(string $middleware) : LazyLoadingMiddleware
pipeline(...$middleware) : MiddlewarePipeline
path(string $path, $middleware) : PathMiddlewareDecorator
prepare($middleware) : MiddlewareInterface
; this one proxies to the other methods.Double-pass middleware is not supported.
A new class,
ApplicationRunner
, composes:RequestHandlerInterface
instance (typically, aMiddlewarePipeInterface
)EmitterInterface
instance (typically, anEmitterStack
composing aSapiEmitter
)ServerRequestInterface
instanceWhen
run()
is called, the class marshals a request, potentially generates an error response, and otherwise passes handling of the request to the handler; it then passes the returned response to the emitter.This class can potentially be extracted to its own library.
The
RouteMiddleware
has been updated to add the methodsroute
,get
,post
, etc. fromApplication
. UnlikeApplication
, they only acceptMiddlewareInterface
instances.New factories (in the
Zend\Expressive\Container
namespace):RouteMiddlewareFactory
DispatchMiddlewareFactory
EmitterFactory
should be mapped toZend\Diactros\Response\EmitterInterface
.ServerRequestFactoryFactory
should be mapped toZend\Expressive\ServerRequestFactory
ServerRequestErrorResponseGeneratorFactory
should be mapped toZend\Expressive\ServerRequestErrorResponseGenerator
.Application
has been completely rewritten. It now composes:MiddlewareFactory
instanceMiddlewarePipeInterface
instance, generally aMiddlewarePipe
RouteMiddleware
instanceApplicationRunner
instanceIt implements
RequestHandlerInterface
andMiddlewareInterface
, and composes theApplicationConfigInjectionTrait
. It defines the same public API as previously, minus the various getters (as none of them are applicable anymore). Each method now proxies to the appropriate collaborator, pre-processing arguments as necessary:handle()
delegates to theMiddlewarePipeInterface
process()
delegates to theMiddlewarePipeInterface
run()
delegates to theApplicationRunner
pipe()
delegates to theMiddlewarePipeInterface
, after first passing its arguments to theMiddlewareFactory
, and, in the case of two arguments, theZend\Stratigility\path()
utility function.route()
and related methods delegate to theRouteMiddleware
, after first passing the$middleware
argument to theMiddlewareFactory
pipeRoutingMiddleware
andpipeDispatchMiddleware
are removed; users will now pipe these middleware just like any other middleware.Zend\Expressive\Delegate\NotFoundDelegate
was renamed toZend\Expressive\Handler\NotFoundHandler
.Zend\Expressive\Middleware\NotFoundHandler
was renamed toZend\Expressive\Middleware\NotFoundMiddleware
; its related factory in theZend\Expressive\Container
namespace was similarly renamed.Tests were updated to reflect the changes, as necessary.
Updates