This article is a guide on how to add a CORS implementation on an existing DotKernel3 project.

The issue

If you’re facing this message:

“Access to XMLHttpRequest at ‘url’ has been blocked by cors policy. No ‘Access-Control-Allow-Origin header is present on the requested resource.”

It means the server didn’t sent the header that lets you access its data through a local client (eg.: browser).

This issue is most common when trying to get some data (usually json) that you want to process using JavaScript.

The error looks similar to the image below:

The solution

A simple implementation would be using Tuupola’s Cors Middleware package.

This article was inspired by: https://akrabat.com/implementing-tuupola-cors-in-expressive/

Adding the package to your project

Run the following command in your project:

composer require tuupola/cors-middleware

At the time writing this article the current package version is: 0.9.4.

Follow the next steps to get your Zend Expressive or DotKernel3 project CORS friendly.

Create the CORS config file

Create a cors.global.php file in the config/autoload directory.

return [
'cors' => [
"origin" => ["*"],
"methods" => ["GET", "POST", "PUT", "PATCH", "DELETE"],
"headers.allow" => ["Content-Type", "Accept"],
"headers.expose" => [],
"credentials" => false,
"cache" => 0,
],
'dependencies' => [

],
];

We’ll come back at this file to register the CORS middleware.

Creating a factory for the middleware

The factory should look like the one below.

The code below extracts de config from the cors key if provided or initializes an empty array and instantiates the Tuupola CORS middleware.

<?php

namespace App\Cors;

use Tuupola\Middleware\CorsMiddleware;

class CorsMiddlewareFactory
{
    public function __invoke($container)
    {
        $corsConfig = $container->get('config')['cors'] ?? [];
        return new CorsMiddleware($corsConfig);
    }
}

Registering the CORS middleware

Back at cors.global.php we will register the cors middleware so our custom implemented factory will be used to create the middleware. (basic config example below)

<?php

use App\Cors\CorsMiddlewareFactory;
use Tuupola\Middleware\CorsMiddleware;

return [
'cors' => [
"origin" => ["*"],
"methods" => ["GET", "POST", "PUT", "PATCH", "DELETE"],
"headers.allow" => ["Content-Type", "Accept"],
"headers.expose" => [],
"credentials" => false,
"cache" => 0,
],
'dependencies' => [
'factories' => [
CorsMiddleware::class => CorsMiddlewareFactory::class,
]
]
];

Final step: Adding (registering) the CorsMiddleware in the pipeline

In this last step we only need to add the CorsMiddleware in config/pipelines.php

// don't forget the use statement
use Tuupola\Middleware\CorsMiddleware;

return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
    // ...
    $app->pipe(CorsMiddleware::class);
    // ...
};

Add the cors middleware after the Error handler and before the middleware providing the data you want to access to make sure everything runs smoothly.

This should get your project working with CORS.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.