9

I am trying to build a separated frontend web application using Vuejs and fetching data from Laravel 9 API that I have built, when I try to access the data from the frontend that is the response in the browser console:

Access to XMLHttpRequest at 'http://localhost:8000/api' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The backend code (Laravel 9)

1- api.php file

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Models\User;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::get('/', function () {
    $users = User::all();
    return response()->json($users, 200);
});

2- cors.php file (default configurations)

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => false,

];

The frontend code (Vuejs)

> 1- main.js file (contains vue setup code)
import { createApp } from 'vue'

import axios from 'axios'
import VueAxios from 'vue-axios'

import App from './App.vue'

const app = createApp(App)

app.use(VueAxios, axios)
app.mount('#app')

2- Users.vue (component that fetches the data)

<template>
  <div class="users">
    test
    <button @click="getUsers()">Get Users</button>
    {{ users }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: [],
    }
  },
  methods: {
    getUsers() {
      this.axios.get('http://localhost:8000/api').then((response) => {
        // this.users = response;
        // console.log(this.users);
        console.log(response);
      }).catch(err => console.log('error: ' + err));
    }
  }
}

update: more illustration

I have used a google extension that allow CORS for the browser and the extension add the following headers to response automatically:

a) access-control-allow-methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
b) access-control-allow-methods: *

but I think it is not a solution to use an extension as I want to solve the problem for the production not only in the debugging mode

and the following are some screenshots of the response in the browser.

1- CORS error response in the browser

CORS error response in the browser

2- number of the header responses before enabling the extension (only 9 headers):

number of the header responses before enabling the extension

3- details of header responses before enabling the extension (only 9 headers):

details of response headers before using the extensions

4- number of the header responses after enabling the extension ( 11 headers):

number of the header responses after enabling the extension ( 11 headers)

5- Details of the header responses after enabling the extension ( 11 headers)

enter image description here

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Amr Ragab
  • 329
  • 1
  • 2
  • 14
  • 2
    Any chance that you're encountering an issue on your backend side? Can you post a screenshot or details in your network tab when inspecting the request? – Potato Science Apr 15 '22 at 16:16
  • I don't know much about laravel, but it may be the trailing slash in paths from cors.php that cause the problem. your client is requesting `http://localhost:8000/api`, maybe try to add also 'api' in cors paths. – Igor Moraru Apr 15 '22 at 16:53
  • I have updated the question with more details about the browser responses – Amr Ragab Apr 15 '22 at 21:02
  • 1
    cors.php is not helping at all – Amir Khan Jul 14 '22 at 05:54

4 Answers4

9

I find a solution for my problem, I was trying to fetch data from http://localhost:8000/api and when I checked cors.php file I find the paths key contains 2 values like the following:
'paths' => ['api/*', 'sanctum/csrf-cookie']
so like I said I was navigating to api path not api/* only so the array should contain a value of the 'api' like the following:
'paths' => ['api/*', 'sanctum/csrf-cookie', 'api']

Amr Ragab
  • 329
  • 1
  • 2
  • 14
  • You also need to change the path when your laravel installation is not installed in the root. Example 'backend/api/*' – RandomUsername Feb 12 '23 at 18:50
  • @RandomUsername What do you mean by 'not installed in the root' ? Anything to see with using packages and routes in packages ? – DevonDahon Mar 15 '23 at 17:32
  • @DevonDahon I had my laravel installed in a sub folder of the webserver and the CORS config would not work for me with just 'api'. I needed to put the subfolder in the config also for it to work correctly. – RandomUsername Mar 15 '23 at 20:25
6

I personally had the same problem when connecting NuxtJs to Laravel API. In Laravel cors.php file all I had done was set the value of 'supports_credentials' to true. The default value was 'false'. I hope it saves up your time.

Ahmad Reza Azimi
  • 534
  • 5
  • 16
0

I have found a unique issue regarding the CORS issue.

I don't find any CORS issue on the server side in Laravel 9.

I have found an issue on the client-side.

If you don't include the request header: Accept: application/json then your request will get a 302 Found redirect response code and that's where you will get a CORS error.

I hope this will save your time. :)

Indrasinh Bihola
  • 2,094
  • 3
  • 23
  • 25
-1

Add a new Middleware app\Http\Middleware\Cors.php

namespace App\Http\Middleware;

use Closure;

class Cors {
    
    public function handle($request, Closure $next) {
        
        $response = $next($request);
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set('Access-Control-Allow-Methods', 'POST, GET');
        $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application', 'ip');
        return $response; 
    }
}

add this line into app\Http\Kernel.php

protected $middleware = [
         .....,
        \App\Http\Middleware\Cors::class,
    ];
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Ajmal PGS
  • 1
  • 1
  • 2
    Dont do that. Laravel >=8 already has a cors policy middleware by default. See your middleware stack. It's under the Illuminate namespace. – JarsOfJam-Scheduler Dec 11 '22 at 07:40
  • 1
    @JarsOfJam-Scheduler so what's the solution? Even if laravel already has it i got error: "has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'" – exSnake Jan 25 '23 at 15:56