NGINX: Retorna cabeçalhos CORS quando o método de solicitação é OPTIONS e o arquivo existe, caso contrário, passe para PHP-FPM

NGINX: Retorna cabeçalhos CORS quando o método de solicitação é OPTIONS e o arquivo existe, caso contrário, passe para PHP-FPM

Eu tenho um NGINX com uma instância PHP-FPM por trás dele. OPTIONSsolicitações de caminhos para os quais existe um arquivo no sistema de arquivos devem ser tratadas pelo NGINX. Para essas solicitações, o NGINX deve retornar Access-Control-*cabeçalhos CORS. OPTIONSsolicitações para as quais não existe arquivo devem ser passadas para PHP-FPM.

A lógica deve ser algo nesse sentido:

    location / {
        # In this case: Check if file exists
        # - yes: return CORS headers
        # - no: pass request to PHP-FPM
        if ($request_method = 'OPTIONS') {
            # This causes an error
            try_files @cors;
        }

        # Normal request handling for all non-OPTIONS requests:

        # Try to serve file directly, fallback to index.php if file does not exist
        try_files $uri /index.php$is_args$args;
    }

    location @cors {
        if (-f $request_filename) {
            more_set_headers "Access-Control-Allow-Credentials: true";
            more_set_headers "Access-Control-Allow-Origin: example.com";
            more_set_headers 'Access-Control-Allow-Methods: POST, GET, DELETE, PUT, OPTIONS';
            more_set_headers 'Access-Control-Allow-Headers: content-type,ngsw-bypass';
            more_set_headers 'Access-Control-Max-Age: 3600';

            more_set_headers 'Content-Type: text/plain; charset=UTF-8';
            more_set_headers 'Content-Length: 0';

            return 204;
        }

        try_files /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass localhost:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param SCRIPT_FILENAME /var/www/public/index.php;
        fastcgi_param DOCUMENT_ROOT /var/www/public;
        fastcgi_param HTTPS $fastcgi_param_https;

        # Prevents URIs that include the front controller. This will 404:
        # http://domain.tld/index.php/some-path
        # Remove the internal directive to allow URIs like this
        internal;
    }

Mas isso não funciona. Uma vez que try_filesnão é permitido dentro de uma ifinstrução ([emerg] 1#1: a diretiva "try_files" não é permitida aqui).

Responder1

você pode usar a error_pagediretiva para lidar com as solicitações OPTIONS para caminhos para os quais existe um arquivo no sistema de arquivos.

location / {
    # Try to serve file directly, fallback to index.php if file does not exist
    try_files $uri /index.php$is_args$args;

    # Handle OPTIONS requests for paths for which a file exists in the file system
    if ($request_method = 'OPTIONS') {
        if (-f $request_filename) {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    }
}

# Pass all other requests to PHP-FPM
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

a try_filesdiretiva é usada para servir arquivos diretamente, com alternativa index.phpse o arquivo não existir. O ifbloco verifica se o método de solicitação é OPTIONS e se existe um arquivo no caminho solicitado. Se ambas as condições forem verdadeiras, o NGINX adicionará os cabeçalhos CORS necessários à resposta e retornará um código de status 204 No Content.

informação relacionada