0

I have an Nginx server used for a store. That store has an API which is in a different folder for which i'm using an alias. Here is my example.com from sites-enabled in Nginx:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name www.example.com;

    root /var/www/store/public;

    #certificated go here [edited]

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name example.com;

    root /var/www/store/public;

    index index.php;

    #certificates go here [edited]

    location /admin {
            index index.php;
    }

    location /api {
            alias /var/www/api/public;
            
            try_files $uri $uri/ @api;

            location ~ \.php$ {
                    include snippets/fastcgi-php.conf;
                    fastcgi_param SCRIPT_FILENAME $request_filename;
                    fastcgi_split_path_info ^(.+\.php)(/.+)$;
                    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
            }
    }

    location @api{
            rewrite /api/(.*)$ /api/index.php?/$1 last;
    }
  
    #the rest of the store config block [edited]

}

The problem that i have is that if i send a POST request using ajax to 'example.com/api' it is changed to a GET and all the parameters are lost.

Here is my Ajax code:

var foo = 'foo';
var bar = 'bar';

$.ajax({
    type: 'POST',

    beforeSend: function(request) {
        request.setRequestHeader("Authorization", 'xyz');
    },
    url: "https://example.com/api",
    data: { foo: foo, bar: bar},
    processData: false,
    success: function(data) {
        console.log(data);
    }
});

To test this i simply dumped $_SERVER['REQUEST_METHOD'].

If i call for example.com/api/index.php the request type is as it should be POST but if i call just example.com/api it is changed to GET.

How can i preserve the request type and parameters for a request?

emma
  • 103
  • 2
  • 2
    That's because with that request nginx produces an internal 301 redirection `/api` -> `/api/`. Why don't simply change that AJAX URL to `https://example.com/api/` and do not invent a complex workarounds? – Ivan Shatsky Jul 09 '20 at 11:52
  • @IvanShatsky that was ...easy. Thank you so much! – emma Jul 09 '20 at 12:02

1 Answers1

1

Your use of a location @api and a rewrite doesn't make much sense here. As it stands, your requests have to get processed through three different location blocks before they are finally sent upstream to PHP.. It is also reversed from the normal pattern I would expect to see.

It looks like the request is getting mangled by the automated 301 redirect from /api to /api/ that web servers always apply to paths that correspond to a directory, as Ivan Shatsky mentioned in a comment.

I would rewrite these location blocks as:

# This doesn't even need a location
rewrite /api(/.*)? /api/index.php?$1 last;

location /api/index.php {
    alias /var/www/api/public;

    try_files $uri =404;

    include snippets/fastcgi-php.conf;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}

This should also allow you to use /api as a path without the trailing slash, though as Ivan Shatsky also pointed out, this is not a good practice to get into.

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
  • @MichaleHampton i'm getting an error when i run `nginx -t`: `nginx: [emerg] "try_files" directive is duplicate in /etc/nginx/snippets/fastcgi-php.conf:5` – emma Jul 09 '20 at 12:05
  • maybe because i have this location a bit lower into the config block: `location / { try_files $uri @store; } `? – emma Jul 09 '20 at 12:09
  • @emma Yes, that would cause that error, though that appears unrelated to this issue. – Michael Hampton Jul 09 '20 at 12:21
  • it appears only when i change my block with the one in this comment because of this `try_files $uri =404;` line i think. Is there a workaround? – emma Jul 09 '20 at 12:35
  • 1
    @emma About your `try_files` issue. You `snippets/fastcgi-php.conf` file most likely contains `include fastcgi.conf;` line (or maybe slightly other file name). Replace `include snippets/fastcgi-php.conf;` with that line in your main nginx config, you don't need anything else. `fastcgi_split_path_info` doesn't needed too. And since the only PHP file you need to serve is `index.php`, you can replace `fastcgi_param SCRIPT_FILENAME $request_filename;` with `fastcgi_param SCRIPT_FILENAME /var/www/api/public/index.php` (or whatever it's full path actually is). – Ivan Shatsky Jul 09 '20 at 13:47