PSR-15 proposes a standard around PHP middleware that consumes PSR-7 HTTP message instances. One goal of the standard is to create interfaces that can co-exist with existing projects, which would allow adoption without necessarily leading to backwards compatibility breaks.
The most recent proposal has the following interfaces:
namespace Interop\Http\Middleware;
use PSR\Http\Message\RequestInterface;
use PSR\Http\Message\ResponseInterface;
use PSR\Http\Message\ServerRequestInterface;
interface DelegateInterface
{
public function process(RequestInterface $request) : ResponseInterface;
}
interface ServerMiddlewareInterface
{
public function process(ServerRequestInterface $request, DelegateInterface $delegate) : ResponseInterface;
}
interface MiddlewareInterface
{
public function process(RequestInterface $request, DelegateInterface $delegate) : ResponseInterface;
}
DelegateInterface
is roughly analogous to Zend\Stratigility\Next
, while
ServerMiddlewareInterface
is analogous to
Zend\Stratigility\MiddlewareInterface
.
We'd take a tiered approach, over a minor version and a following major version.
First, we can update Next
to implement DelegateInterface
. At first, this
would be adding a process()
method that proxies to __invoke()
, and making
the ResponseInterface
argument optional:
namespace Zend\Stratigility;
use Interop\Http\Middleware\DelegateInteface;
use PSR\Http\Message\RequestInterface;
use PSR\Http\Message\ResponseInterface;
use PSR\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response;
class Next implements DelegateInteface
{
public function __invoke(
ServerRequestInterface $request,
ResponseInterface $response = null,
$err = null
) {
/* ... */
}
public function process(RequestInterface $request)
{
return $this($request);
}
}
We'd also mark __invoke()
as deprecated via annotation.
For the next major version, we'd modify __invoke()
to proxy to process()
. Since
one suggested change for v2
includes removal of the $err
argument already, this version would also drop
the $response
argument, so that it now reads:
namespace Zend\Stratigility;
use Interop\Http\Middleware\DelegateInteface;
use PSR\Http\Message\RequestInterface;
use PSR\Http\Message\ResponseInterface;
use PSR\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response;
class Next implements DelegateInteface
{
public function __invoke(ServerRequestInterface $request)
{
return $this->next($request);
}
public function next(RequestInterface $request)
{
/* ... */
}
}
At the same time, we'd also mark the __invoke()
method as deprecated; we might
potentially also raise an E_USER_DEPRECATED
error within the __invoke()
method to encourage usage of the process()
method.
For a minor version:
- We'd update
MiddlewarePipe
to also allow PSR-15ServerMiddlewareInterface
andMiddlewareInterface
implementations. - We'd update
Dispatch
to check forServerMiddlewareInterface
andMiddlewareInterface
instances; if found, it would invoke them with only the passed request. - We'd mark
MiddlewareInterface
as deprecated. We'd add a class that can decorate callable middleware to be invoked as(See comment below for details on why this is now omitted.)ServerMiddlewareInterface
implementations. This would check the arity of the callable to ensure that it can be invoked per the PSR-15 specification.
For a major version:
- We'd remove
MiddlewareInterface
entirely. Next
would check if the handler is aServerMiddlewareInterface
implementation before dispatch (see the error handler proposal for details on why this goes inNext
and notDispatch
).- We'd update
MiddlewarePipe
to only allowServerMiddlewareInterface
andMiddlewareInterface
implementations.
PSR-15 is not yet accepted, and could still undergo revision, making it a moving target.
The one issue I'm running up against in current implementation of the next minor release is within
Next::__invoke()
: lack of a$response
argument means:$response
argument to be null$done
argumentThis latter presents a problem, as it may require:
Next
with a prototype response to use in these situations$response
provided as the prototype