Developing software in the Real World

Implementing CORS in Zend Expressive

On a recent project, I needed to implement CORS support for my Expressive API. The easiest way to do this is to use Mike Tuupola's PSR-7 CORS Middleware.

As this is a standard Slim-Style PSR-7 middleware implementation, we need to wrap it for Expressive, so we make a factory:


We then register this in our App\ConfigProvider::getDependencies() by adding to the factories key so that it looks something like this:

If you don't want to fully qualify, add use Tuupola\Middleware\Cors; to the top of the file so that you can just use Cors::class here.

Lastly, we register the middleware in config/pipeline.php:

Place it somewhere near the top of the list; personally, I place it just after piping the ServerUrlMiddleware::class.

We now have working CORS:

Failure looks like this:

By default, it doesn't tell you what went wrong, which isn't too helpful.

Providing JSON error responses

To provide a JSON error response, you need to set the error option to a callable and you can then return a JsonResponse:


As you can see, we've created a new error method that returns a JsonResponse. We can then encode the $arguments as that contains the information about what the problem is:

Responding with ProblemDetails

I'm a huge fan of RFC 7807, so prefer my error response to conform to this. The Problem Details component handles the creation of the correct Responses, so to use it with Cors, we change our error() method to this:

As error() is called statically, we need to define a static property $problemDetailsResponseFactory in the class to hold our ProblemDetailsResponseFactory when we grab it from the container in the __invoke() method:

You'll need a use Zend\ProblemDetails\ProblemDetailsResponseFactory; at the top too. The entire class can be seen in this gist.


It turns out that adding CORS support to an Expressive app is easy enough, mainly because Mike Tuupola has done most of the work for us!

3 thoughts on “Implementing CORS in Zend Expressive

  1. Why is the file name App/Factory/CorsMiddleware.php instead of App/Factory/CorsMiddlewareFactory.php

    Is this a typo or do you use some custom class loader?

Thoughts? Leave a reply

Your email address will not be published. Required fields are marked *