Fix CORS Issues in Laravel APIs
Tags: laravel, php, programming
Published: 2023-06-05 16:18:08


Building web applications with Microservices Architecture comes with a couple of fixable issues. One such issue is CORS. You commonly 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:

![Error message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zqvyl8r0nvt8jsnj7wt4.png)

## Installation

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

```bash
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.

{% embed https://devjavu.space/post/the-hitchhiker-s-guide-to-laravel-setup/ %}

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

{% embed https://devjavu.space/post/build-a-simple-blog-multiple-image-upload-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.

```json
"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:

```php
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.

```bash
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
<?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:

```php
'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:

```php
'allowed_methods' => ['POST', 'GET', 'DELETE', 'PUT', '*']
```

- **allowed_origins:** This option specifies what source requests should be allowed from. If you want to test from your local machine, you would have to add “localhost” + the port to the list of allowed origins.

```php
'allowed_origins' => ['http://localhost:8080', 'https://client.myapp.com']
```

- **allowed_origins_patterns:** This option matches the request origin with patterns.

```php
'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](https://developer.mozilla.org/en-US/docs/Glossary/preflight_request) which includes the [Access-Control-Request-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers) to indicate which HTTP headers can be used during the actual request.

```php
'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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods) and [Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/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](https://developer.mozilla.org/en-US/docs/Web/API/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.

```bash
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.

```bash
php artisan serve
```

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

---

Cheers ☕️