2

I want to route all 404 requests to a php script, How should I do that? My nginx config is:

server {
    listen 81;
    listen [::]:81;
    root /srv/http/paste.lan/www;
    autoindex on;
    client_max_body_size 20M;
    index index.txt index.html index.htm index.php;
    server_name paste.lan;
    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    # pass PHP scripts to FastCGI server
    #
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
    #
    #   # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    #   # With php-cgi (or other tcp sockets):
    #   fastcgi_pass 127.0.0.1:9000;
    }


    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny all;
    }
}

Things I have tried:

Attempt #1:

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ /index.php;
    }
  • This only works for URI's that does not end with .php , for example /DoesNotExist.ph is passed to index.php , but /DoesNotExist.php get the standard nginx 404 page.

Attempt #2:

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
    error_page 404 /index.php;

This sort-of works, all 404 requests are passed to index.php but this forces the response code to be 404, even if index.php contains:

<?php
http_response_code(200);
die("index.php");

it will still be served with response code 404 :(

Attempt #3:

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
    error_page 404 =200 /index.php;

This also sort-of works, all 404 requests are passed to index.php but this forces the response code to be 200, even if index.php contains:

<?php
http_response_code(400);// HTTP 400 Bad Request
die("index.php");

it will still be served as HTTP 200 OK :(

2
  • 1
    Almost there, the one you want is error_page 404 = /index.php; to respond with the code it returns. Also, you may want to add try_files $uri =404; to your location ~ \.php$ block to catch non-existent PHP files. Mar 10, 2023 at 11:12
  • @RichardSmith dang that works! and i don't need to add anything to the \.php$ block! want to post it as an answer?
    – hanshenrik
    Mar 10, 2023 at 11:19

1 Answer 1

3

The error_page directive includes an option to change the response code to another.

From the manual page:

If an error response is processed by a proxied server or a FastCGI/uwsgi/SCGI/gRPC server, and the server may return different response codes (e.g., 200, 302, 401 or 404), it is possible to respond with the code it returns:

error_page 404 = /404.php;

You should use:

error_page 404 = /index.php;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .