A number of repositories have pull requests in place to use webimpress/http-middleware-compatibility in order to allow usage with the various iterations of the PSR-15 specification; this package provides polyfill support for the various versions.
I think we need to put a halt to this for now.
While I would really love to support all versions of the specification, it’s simply non-trivial. For those who are not aware of the history of the specification, the following is a summary of the various versions:
- The 0.2.0 version of the http-interop/http-middleware package, which we followed for initial releases of Expressive, defined the namespace
Interop\Http\Middleware
with the interfacesServerMiddlewareInterface
andDelegateInterface
, each defining the methodprocess()
. - The 0.4.1 version of the http-interop/http-middleware package, supported by the 2.0 releases of Expressive, defined the
Interop\Http\ServerMiddleware
namespace, and renamed theServerMiddlewareInterface
toMiddlewareInterface
. - The 0.5.0 version of the http-interop/http-middleware package renamed the namespace to
Interop\Http\Server
, renamedDelegateInterface
toRequestHandlerInterface
, and, futher, renamed the delegate’sprocess()
method tohandle()
. - That package was then split into two, http-interop/http-server-handler and http-interop/http-server-middleware; the two combined provide the
RequestHandlerInterface
andMiddlewareInterface
, respectively. - Assuming no more changes occur and PSR-15 is accepted with the current architecture, we will have two new packages, psr/http-server-handler and psr/http-server-middleware, using the namespace
Psr\Http\Server
.
We run into a few problems trying to support the various versions.
First, the new http-interop packages (http-server-handler and http-server-middleware) declare themselves as conflicting with http-interop/http-middleware versions >= 0.5.0. This is okay , as the two packages combined declare the same namespace and interfaces. You require one or the other. For our purposes, we’d likely include http-interop/http-server-middleware, as that package has a requirement on http-server-handler as well.
Second, we cannot support each of the previous two versions of http-interop/http-middleware (0.4.1 and 0.2.0) simultaneously, as they are the same package; we can support one or the other UNLESS we define alternative interface definitions for the version not installed.
Third, the change in interface name from DelegateInterface
to RequestHandlerInterface
makes defining middleware within Stratigility and Expressive that supports multiple versions impossible, as it’s impossible to create a process()
method that will comply with any version; it must comply with a single version at a time.
Fourth, middleware authors not only need to select the interface version they plan to target, but potentially also update any calls to the delegate/request handler. If they were targeting the DelegateInterface
previously, and now target the RequestHandlerInterface
, they also must update calls to process()
within their own code to handle()
.
What webimpress/http-middleware-compatibility tried to do was:
- pin a project to the http-interop/http-middleware version already in use, or, if on a new install, prompt the user for the version to use.
- adapt the various interfaces by providing polyfills and providing alternative interfaces that extend those from multiple versions
- provide a constant that references the appropriate delegate/request handler method name for use when calls to the delegate are needed
This worked fine… until the interfaces were split into two packages. At that point, the logic for choosing the package broke, as previously, you could just indicate the version to use, and now it would need to prompt for the package as well.
At this point, I wish we hadn’t updated Stratigility to use the compat package, as it’s causing more headaches than it should (in particular, developers are not aware what the various versions mean, nor that Expressive does not support the most recent versions at all); we should have just pinned to the 0.4.1 series of http-middleware and left it at that.
My inclination going forwards is that we create alpha or beta MAJOR releases that reference the new packages across any repository that currently implements or typehints against the interfaces, to allow developers to start testing against the latest spec revision. Then, when PSR-15 is approved, we do a new alpha or beta pinning to the final release, and the next MAJOR version supports PSR-15 only. In the meantime, we also start writing tools to migrate existing code as follows:
- Update middleware to implement the new interface(s)
- Update middleware delegation to use the new
RequestHandlerInterface::handle()
method
This approach would also be used here in zend-mvc for the MiddlewareListener
.
So, in sum, my proposal for each affected repository is:
- Either create a new branch for the new major version, or mark the
develop
branch as targeting the next major version (update thebranch-alias
config incomposer.json
). - Have that branch pin to http-interop/http-server-middleware
^1.0.1
. - Update the minimum PHP version to 7.1 (per our next major release milestone announcement)
- Update affected code:
- Update any
MiddlewareInterface
implementations:- Ensure
MiddlewareInterface
is imported from the correct namespace. - Import
RequestHandlerInterface
instead ofDelegateInterface
. - Ensure any middleware
process()
methods referenceRequestHandlerInterface
instead ofDelegateInterface
. - Ensure any calls to the delegate call
handle()
instead ofprocess()
.
- Ensure
- Update any
DelegateInterface
implementations (should only affect zend-stratigility and zend-expressive):- Implement
RequestHandlerInterface
instead, and ensure that class is correctly imported. - Rename the
process()
method tohandle()
.
- Implement
- Update any
- Create tooling for updating existing
MiddlewareInterface
implementations targeting http-interop 0.4.1 to the latest specification version.