Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Lopsum's avatar

CORS errors when making POST request to external API

Hi Laravelers ! I'm using a Laravel 10 application that I'm trying to make communicate with an external API (several POST and GET requests). To do this, I'm using Javascript's fetch API. Where I'm running into a problem is that the GET requests are working without a hitch (with the right headers) whereas the POST requests are causing problems. I get a CORS 'Access-Control-Allow-Origin' error. When I make the POST request, I see 2 HTTPS requests in my console: one OPTION and one POST. In both requests, there is no "Access-Control-Allow-Origin". I contacted API support who assured me that the correct headers were present. Hence my question... Plus, everything works fine in Postman

Here's my code:

fetch('xxxxxx', {
method: 'POST',
headers: {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST',
    'Access-Control-Allow-Headers': 'Content-Type, X-CSRF-TOKEN',
},
body: JSON.stringify(ExpOptions)
})
.then(response => {
    if (!response.ok) {
        throw new Error('Network error.');
    }
    return response.json();
})
.then(data => {
    console.log(data);
})
.catch(error => {
    console.error('Error with the request:', error);
});

Here the response header for the OPTION request :

HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Wed, 04 Oct 2023 10:09:06 GMT
Content-Type: application/vnd.sun.wadl+xml
Content-Length: 458
Connection: keep-alive
Allow: POST, OPTIONS
Content-Language: fr-FR

And the request header :

OPTIONS xxxxxx HTTP/1.1
Host: xxxxxx
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type
Referer: xxxxx
Origin: xxxx
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

Is there anything I need to configure in terms of JS or my server? I've seen that there's HandleCors middleware and cors.php which I've configured as follow:

    'paths' => ['api/*', 'sanctum/csrf-cookie', '*'],
    'allowed_methods' => ['POST', 'GET', 'DELETE', 'PUT', '*'],
    'allowed_origins' => ['xxxxxx'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['X-Custom-Header', 'Upgrade-Insecure-Requests', '*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,

Am I missing something, or is there an issue with the external API? Thanks for your feedback 😇

0 likes
5 replies
DhPandya's avatar

@vable You have to except your API routes from the CSRF. Add your routes within the VerifyCsrfToken middleware.

protected $except = [
        'your_routes'
    ];
Lopsum's avatar

Thanks for your response. I've added the endpoint of the external API to which I'm trying to communicate in the VerifyCsrfToken middleware, I've restarted the application but nothing has changed: I get exactly the same error.

DhPandya's avatar

@Vable In which file you're declaring your API routes? If it is api.php then you don't need to except that routes. Can you please add your request url and route file here?

Lopsum's avatar

I'm on the the page https://lproject.uu/send-parcel. It's a standard page in my Laravel application, from a web route. (not api.php) So, I juste have in my web.php something like that :

Route::get('sending-a-parcel', [ShippingController::class, 'index'])->name('client.shipping.index');

The controller function just diplay a view.

In that view, when I click on a button on the page, an AlpineJS function is launched, prepares the data and then the fetch takes place. The fetch makes a POST request to an external private API (which I don't manage and which is located on its own domain name).

For this example, let's imagine that the external API has this url: https://www.api/endpoint

I hope it's more clear like that 😇

Lopsum's avatar

I've just carried out another test, this time using HTTP on the Back side rather than Fetch in JavaScript. When I make my request with Guzzle, I get the full headers (see screenshot from Telescope) and everything is fine :

Telescope Capture

In fact, is there anything else I need to do with Laravel when I want to fetch an external API in Javascript? Could this be due to the HandleCors middleware that removes certain headers? Thanks in advance 😀

Please or to participate in this conversation.