Score:0

Can something in my Nginx config imply why my backend is not sending the 'Access-Control-Allow-Origin' header in POST request?

in flag

*Edit 1: The error seem to be only with POST requests

I have a frontend website on localhost. There is a registration page on localhost/register

The website calls a backend function to register a user at localhost:8080/api/register

I use Axios to POST the username and password. The browser sends two requests: OPTIONS pre-flight request, and then the POST request.

The user is created successfully, however the browser throws an error for the POST request:

Reason: CORS header ‘Access-Control-Allow-Origin’ missing

And indeed it's missing in the response to the POST. Assuming my backend cors file is configured properly, could the issue be from the combination of my Docker + Nginx setup that blocks it or proxy the headers to a wrong place?

This is my nginx config:

server {
    listen 8080;
    index index.php index.html;    
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {        
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    
}

  server {    
    listen       80;       
      location / {      
      proxy_pass      http://node:3000;
      
    }
  }

and this is my docker-compose.yml:

networks:
    mynetwork:
        driver: bridge

services:
    nginx:
        image: nginx:stable-alpine
        container_name: nginx
        ports:
            - "8080:8080"
            - "80:80"            
        volumes:            
            - ./php:/var/www/html 
            - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
            
        depends_on:
            - php
            - node
        networks:
            - mynetwork
    
    php:        
        build:
            context: ./php
            dockerfile: Dockerfile
        container_name: php
        user: "1000:1000"
        volumes:
            - ./php:/var/www/html
        ports:
            - "9000:9000"
        networks:
            - mynetwork

    node:
        build:
            context: ./react
            dockerfile: Dockerfile
        container_name: next        
        volumes:
            - ./react:/var/www/html                
        ports:
            - "3000:3000"       

        networks:
            - mynetwork


           

**Edit 2:

The backend is Laravel and it has a CORS middleware that is supposed to take care of it. And in fact it does seem to be working because GET and OPTIONS request pass without error, only the POST request throws this error.

This is the CORS config file (cors.php) in Laravel:

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

'allowed_methods' => ['*'],

'allowed_origins' => ['http://localhost'],

'allowed_origins_patterns' => ['*'],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true
us flag
There is nothing in this configuration that would add the CORS header. You need to take care of it.
Stackerito avatar
in flag
Thank you. You are right that nginx does not have anything, but the backend has a middlware that takes care of that, and in fact when I send `GET` and `OPTIONS` request it does send the correct headers. But with `POST` not. As you said, in order to fix the `POST` request issue, I added the following to the PHP server block and it now works: `if ( $request_method = POST ){ add_header 'Access-Control-Allow-Origin' 'http://localhost'; add_header 'Access-Control-Allow-Credentials' 'true'; }`. But why I don't need that for `GET` and `OPTIONS`? added the backend code
us flag
We can only guess what the thought process of the middleware developer has been when they have implemented it.
Stackerito avatar
in flag
So for now I should keep my code inside the server block for `POST` requests? Does my new config seem OK to you, or I'm missing something that might cause issues? (It's working, but maybe I can make it better)
us flag
Yes, the `server` block is fine. However, the best practice is to reverse proxy a path to the backend URL instead of using another port for different backend access.
Stackerito avatar
in flag
Can you explain to me how to change my current config to do it? I thought that's what I'm already doing by proxying to my backend at port 8080?
us flag
The term reverse proxy above was not accurate actually. You need to do a `location /api` block inside the `server` block with port 80, and then move the configuration for port 8000 under that section. That is, you should serve the backend via port 80 too, just with a different prefix.
Stackerito avatar
in flag
I did something slightly different: I used sub-domain instead of `/api` route. The way I did it was to first add `api.mysite.local` to the `hosts` file and then added a server block that listens on port `80` and redirects requests to the server block that listens on port `8080` like so: `return 301 https://api.mysite.local$request_uri;` - is this also a good practice?
Michael Hampton avatar
cz flag
This really looks like an issue with Laravel rather than your nginx configuration. Have you sought help with it on [so]? You may wish to do so.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.