phpdockernginxerror-handlingcontainers

curl: (47) Maximum (50) redirects followed when configuring custom error pages


so first i want to explain my current situation and what i want to achieve:

I wanted to make an php file which take code as parameter and then handle every passed error code, sadly this did not work as expected as it always returned the custom page with errorcode of 0 even tho the actual error code were different (403 or 404).

server {
    listen 80;
    server_name genefit.cc www.genefit.cc;
    root /var/www/html;
    index index.htm index.html index.php;

    charset utf-8;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }

    access_log off;
    error_log /var/log/nginx/error.log error;

    sendfile off;

    client_max_body_size 100m;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass genefit.cc:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors on;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }

    location ~ /\.ht {
        deny all;
    }

    # Error page configuration
    error_page 400 401 402 403 404 500 502 503 504 /error.php?code=$request_uri;


    location ~ /error.php$ {
        root /var/www/html;
        try_files $uri $uri/ =404;
        internal;
        fastcgi_pass genefit.cc:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/error.php;
        fastcgi_param QUERY_STRING $query_string;
    }
}
<?php
$status_code = isset($_GET['code']) ? intval($_GET['code']) : 500;
http_response_code($status_code);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Error</title>
    <style>
        body {
            text-align: center;
            font-family: Arial, sans-serif;
            color: red;
        }
        .container {
            margin-top: 50px;
        }
        img {
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Error <?php echo $status_code; ?></h1>
        <p>Something went wrong. Please try again later.</p>
        <img src="https://http.cat/<?php echo $status_code; ?>" alt="Error <?php echo $status_code; ?>">
    </div>
</body>
</html>

=======

After trying to solve above's issue for around 1h, i gave up and started making seperate php files in an error directory such as error/403.php and error/404.php. This then caused the too many redirect error mentioned in the title of this post:

server {
    listen 80;
    server_name genefit.cc www.genefit.cc;
    root /var/www/html;
    index index.htm index.html index.php;

    charset utf-8;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    sendfile off;

    client_max_body_size 100m;

    location ~ /\.ht {
        deny all;
    }

    # PHP files handling
    location ~ \.php$ {
        include fastcgi_params;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass genefit.cc:9000;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }

    # Error pages
    error_page 400 /error/400.php;
    error_page 401 /error/401.php;
    error_page 402 /error/402.php;
    error_page 403 /error/403.php;
    error_page 404 /error/404.php;
    error_page 500 /error/500.php;
    error_page 502 /error/502.php;
    error_page 503 /error/503.php;
    error_page 504 /error/504.php;
    
    location / {
        try_files $uri $uri/ /error/404.php;
    }

    # Serve error pages from the /error/ directory
    location /error/ {
        internal;
        root /var/www/html/;
        alias /var/www/html/error/;
        try_files $uri $uri/ =404;

        # PHP files handling
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass genefit.cc:9000;
            fastcgi_intercept_errors off;        
        }
    }
}
<?php
// Define the static variable for the error code
$error_code = 404;

// Set the HTTP response code
http_response_code($error_code);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Error <?php echo $error_code; ?></title>
    <style>
        body {
            text-align: center;
            font-family: Arial, sans-serif;
            color: red;
        }
        .container {
            margin-top: 50px;
        }
        img {
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Error <?php echo $error_code; ?></h1>
        <p>Page not found. Please check the URL or try again later.</p>
        <img src="https://http.cat/<?php echo $error_code; ?>" alt="Error <?php echo $error_code; ?>">
    </div>
</body>
</html>

Solution

  • Looking at the second part of your question...

    You have fastcgi_intercept_errors on; which is probably necessary for handling errors from your other PHP scrips.

    However, your "error" handling scripts also set the HTTP response code to something other than "200 OK". Which may be the cause of a redirection loop.

    I say may be because Nginx usually avoids error_page processing, when it's still processing a previous error_page, to avoid nested errors.

    If this is the problem, you could create another location block to handle just the "error" scripts.

    For example:

    location ~ ^/error/.*\.php$ {
        include fastcgi_params;
    
        fastcgi_pass genefit.cc:9000;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
    

    Place this block above location ~ \.php$, as regular expression locations are evaluated in order until a match is found.