Назад | Перейти на главную страницу

Пользовательская страница Nginx 502 с вложенными прокси

Я знаю, как создать настраиваемую страницу 502 для ошибки восходящего потока, и делал это без проблем много раз, однако в этом конкретном случае, когда один прокси-ответ передается другому прокси, я не могу найти правильную конфигурацию.

Общий рабочий процесс выглядит следующим образом: пользователь запрашивает миниатюру изображения, nginx передает этот запрос в хранилище изображений. Если хранилище возвращает 404, то nginx передает этот запрос серверу приложений, который генерирует эскиз с запрошенным URI и возвращает его с кодом 200, который передается пользователю через nginx.

Однако, если пользователь запрашивает миниатюру полностью несуществующего изображения, сервер приложений возвращает 502. Я хотел бы в этом случае отображать настраиваемую страницу вместо встроенного nginx «502 Bad Gateway».

Как я уже упоминал в начале, я знаю, как создать пользовательскую страницу 502, но я думаю, что эта конкретная сложная настройка с двойным проксированием требует некоторой дополнительной конфигурации, которую я не могу найти :( Я пробовал местоположение с внутренний вариант, я пробовал расположение с прямым URL-адресом на html-страницу, и я пробовал "@" localtion, но nginx всегда отображал свою встроенную страницу. Оба файла 502.html и 502x.html существуют в / var / www / html и доступны для чтения nginx:

ll /var/www/html
total 20
drwxr-xr-x 2 root root 4096 May  3 11:21 ./
drwxr-xr-x 4 root root 4096 Mar 24 11:50 ../
-rw-r--r-- 1 root root   36 Apr 28 10:49 502.html
-rw-r--r-- 1 root root   36 May  3 11:21 502x.html

Конфигурация Nginx:

server {
listen 443 ssl http2;
server_name cdn.domain.tld;

ssl_certificate /etc/letsencrypt/live/cdn.domain.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cdn.domain.tld/privkey.pem;

client_max_body_size 10m;

client_body_buffer_size 128k;
proxy_connect_timeout 75;
proxy_send_timeout 300;
proxy_read_timeout 500;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_http_version 1.1;
proxy_buffering on;
proxy_redirect off;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

#locations for redirection of 502 response received from thumbnail generator. Not working :(
#error_page 502  @502;
#error_page 502  https://cdn.domain.tld/502x.html;
error_page 502  /502.html;
location =/502.html {
   root /var/www/html;
   internal;
}
location @502 {
   root /var/www/html;
   try_files /502x.html 502;
}
location = /502x.html {
   root /var/www/html;
   index 502x.html;
}

location  / {
    proxy_pass http://192.168.10.5/thumbs$request_uri;

    #Sets caching time for different response codes. If only caching time is specified  then only 200, 301, and 302 responses are cached.
    proxy_cache_valid 30m;

    add_header X-Proxy-Thumbs-Cache $upstream_cache_status;

    #intercept 404 from backend
    #from nginx docs:
    #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 (equal sign does that)
    #So we proxy 404 to app which generates thumbnail and returns it with 200 code
    proxy_intercept_errors on;
    error_page 404 = @not-found;

    access_log /var/log/nginx/cdn.access.log cachelog;
    error_log /var/log/nginx/cdn.error.log;
}

location @not-found {
   proxy_pass http://192.168.10.12/thumbgen?key=$request_uri;

   add_header X-Proxy-Thumbs-Cache2 $upstream_cache_status;

   proxy_intercept_errors on;

   access_log /var/log/nginx/cdn-404.access.log cachelog;
   error_log /var/log/nginx/cdn-404.error.log;
}

}

Я нашел ответ в этой теме: http://mailman.nginx.org/pipermail/nginx/2011-July/027966.html

Мне пришлось добавить recursive_error_pages on; в раздел сервера, поэтому моя окончательная конфигурация выглядит так:

server {
    listen 443 ssl http2;
    server_name cdn.domain.tld;

    ssl_certificate /etc/letsencrypt/live/cdn.domain.tld/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cdn.domain.tld/privkey.pem;

    client_max_body_size 10m;

    client_body_buffer_size 128k;
    proxy_connect_timeout 75;
    proxy_send_timeout 300;
    proxy_read_timeout 500;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
    proxy_http_version 1.1;
    proxy_buffering on;
    proxy_redirect off;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    #we need this to enable redirection of 502 code inside @not-found location
    recursive_error_pages on;

    #location for redirection of 502 responses received from thumbnail generator.
    location =/502.html {
       root /var/www/html;
       internal;
    }

    location  / {
        proxy_pass http://192.168.10.5/thumbs$request_uri;

        #Sets caching time for different response codes. If only caching time is specified  then only 200, 301, and 302 responses are cached.
        proxy_cache_valid 30m;

        add_header X-Proxy-Thumbs-Cache $upstream_cache_status;

        #intercept 404 from backend
        #from nginx docs:
        #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 (equal sign does that)
        #So we proxy 404 to app which generates thumbnail and returns it with 200 code
        proxy_intercept_errors on;
        error_page 404 = @not-found;

        access_log /var/log/nginx/cdn.access.log cachelog;
        error_log /var/log/nginx/cdn.error.log;
    }

    location @not-found {
       proxy_pass http://192.168.10.12/thumbgen?key=$request_uri;

       add_header X-Proxy-Thumbs-Cache2 $upstream_cache_status;

       proxy_intercept_errors on;
       error_page 502  /502.html;

       access_log /var/log/nginx/cdn-404.access.log cachelog;
       error_log /var/log/nginx/cdn-404.error.log;
    }
}