NGINX: Gibt CORS-Header zurück, wenn die Anforderungsmethode OPTIONS ist und die Datei vorhanden ist, andernfalls an PHP-FPM übergeben

NGINX: Gibt CORS-Header zurück, wenn die Anforderungsmethode OPTIONS ist und die Datei vorhanden ist, andernfalls an PHP-FPM übergeben

Ich habe ein NGINX mit einer PHP-FPM-Instanz dahinter. OPTIONSAnfragen für Pfade, für die eine Datei im Dateisystem vorhanden ist, sollten von NGINX bearbeitet werden. Für diese Anfragen sollte NGINX Access-Control-*CORS-Header zurückgeben. OPTIONSAnfragen, für die keine Datei vorhanden ist, sollten an PHP-FPM übergeben werden.

Die Logik sollte ungefähr so ​​aussehen:

    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;
    }

Das funktioniert allerdings nicht. Since try_filesist innerhalb einer ifAnweisung nicht zulässig ([emerg] 1#1: Die Direktive „try_files“ ist hier nicht zulässig).

Antwort1

Mit der Direktive können Sie error_pagedie OPTIONS-Anfragen für Pfade verarbeiten, für die eine Datei im Dateisystem vorhanden ist.

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;
}

Die try_filesDirektive wird verwendet, um Dateien direkt bereitzustellen, mit Fallback, index.phpfalls die Datei nicht existiert. Der ifBlock prüft, ob die Anforderungsmethode OPTIONS ist und ob im angeforderten Pfad eine Datei vorhanden ist. Wenn beide Bedingungen erfüllt sind, fügt NGINX der Antwort die erforderlichen CORS-Header hinzu und gibt den Statuscode 204 „Kein Inhalt“ zurück.

verwandte Informationen