Building web applications with Microservices Architecture comes with a couple of fixable issues. One of such issues is CORS. Most commonly, you face this issue when you try to test decoupled applications locally on your machine.

Say we had a RESTful API built with Laravel and a SPA built with VueJS, attempting to make a request from the Vue App running on port 8080 to the Laravel backend running on PORT 8000 might lead to an error like such:

image

Thankfully, we can fix this easily in Laravel with the Laravel-cors package.

Installation

The Laravel-Cors package can be installed using composer. Navigate to your Laravel application folder in the terminal and run:

composer require fruitcake/laravel-cors

If you do not have composer installed, or do not have Laravel setup, I have written a guide to help you get started.

And some content to get up to speed with Laravel-Vue.

Configuration

After a successful installation, you should now have the Laravel-cors package added to your packages, you can check that you have it in your composer.json file.

"fruitcake/laravel-cors": "^1.0",

Next, we’ll need to add the HandleCors middleware in the $middleware property of Kernel class. Open app/Http/Kernel.php and add this line in the $middleware property:

protected $middleware = [
  ...
  \Fruitcake\Cors\HandleCors::class, # this line
];

Finally, we need to publish the package so the configuration file can be copied from the package directory to our application directory.

php artisan vendor:publish --tag="cors"

A new file (config/cors.php) should be added to your config folder. This file should contain default configurations for CORS. You can use the default configuration or tweak it however you wish. Let’s dig in a bit and see what options this file provides us.

<?php
return [
    'paths' => [],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => false,
    'max_age' => false,
    'supports_credentials' => false,
];
  • paths: This option takes an array value and allows us to enable cors for multiple paths. Some example configurations would be:

    'paths' => ['api/*', 'api/admin/*', 'api/users/*', '*']
    
  • allowed_methods: This option indicates what HTTP request methods to allow on the specified paths. [*]allows all methods. Some examples of option values would be:

    'allowed_methods' => ['POST', 'GET', 'DELETE', 'PUT', '*']
    
  • allowed_origins: This option specifies what source requests should be allowed from. If you would want to test from your local machine, you would have to add “localhost” + the port to the list of allowed origins.

    'allowed_origins' => ['http://localhost:8080', 'https://client.myapp.com']
    
  • allowed_origins_patterns: This option matches the request origin with patterns.

    'allowed_origins_patterns' => ['Google\']
    
  • allowed_headers: This option is used to set the Access-Control-Allow-Headers, which is used in response to a preflight request which includes the Access-Control-Request-Headers to indicate which HTTP headers can be used during the actual request.

    'allowed_headers' => ['X-Custom-Header', 'Upgrade-Insecure-Requests', '*']
    
  • exposed_headers: This option is used to set the value of Access-Control-Expose-Headers response header. This response header indicates which headers can be exposed as part of the response by listing their names.

  • max_age: This option is used to set the Access-Control-Max-Age response header. The Access-Control-Max-Age response header indicates how long the results of a preflight request ( the information contained in the Access-Control-Allow-Methods and Access-Control-Allow-Headers headers) can be cached.

  • supports_credentials: This option sets the Access-Control-Allow-Credentials header. The Access-Control-Allow-Credentials response header tells browsers whether to expose the response to frontend JavaScript code when the request’s credentials mode (Request.credentials) is included.

Now we have an understanding of the function of each of the options. You can configure these options however you want. Once you’re done, you want to reload your Laravel configurations and allow your changes to reflect.

php artisan config:cache

This should clear your configuration cache and recache the updated configurations (including your changes). From here you can serve your application.

php artisan serve

I hope this post helps you resolve any of your Laravel CORs issues.

Cheers ☕️