NGINX - How to redirect on 504 gateway timeout - nginx

I'm using NGINX as a reverse proxy to a glassfish. When the glassfish returns 50x errors, I'm able to identify and redirect to another resource from a cdn.
But if it simply times out, NGINX will respond to the user with 504 gateway timeout instead of redirecting to a good resource at the CDN through rewrite.
I'd like to do the same thing in this case, if NGINX times out, I want to redirect to another URL, the same way I do in #redir_404 .
How can I achieve that?
Thank you.
server {
listen *:80;
ssl off;
access_log /var/log/nginx/access-.log;
error_log /var/log/nginx/error-.log;
client_max_body_size 60m;
location #redir_404 {
rewrite /ad/(.*?)(\?.*)?$ $scheme://cdn.company.com/ad/$1/index.html break;
rewrite /tag(.*?)$ $scheme://cdn.company.com/tag/pixel.png break;
}
location / {
proxy_intercept_errors on;
set_real_ip_from 192.23.45.16;
real_ip_recursive on;
real_ip_header X-Forwarded-For;
proxy_pass http://localhost:8080;
# Force timeouts if one of the backend is dead #
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
# Set headers #
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Umotion-Ip $remote_addr;
proxy_set_header User-Agent $http_user_agent;
add_header Front-End-Https on;
# By default we don't want to redirect #
proxy_redirect off;
# Force cache-control to no-cache for /tag and /ad
location ~ ^/(tag|ad) {
proxy_pass http://localhost:8080;
add_header Cache-Control "private, no-cache, no-store, must-revalidate, proxy-revalidate";
}
error_page 403 404 405 500 501 502 503 504 = #redir_404;
}
}

Add error_page location to redirect within your server block.
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
internal;
}
We can customise the error pages as required(/50x.html is cutom designed page)

Related

Preflight + proxy_cache = "GET + Preflight" + CORS error. Without proxy_cache everything is ok. Is there a way to use proxy_cache?

I got the next 2 errors in console:
Access to XMLHttpRequest at 'https://api.domain1.com/rest/v1/reviews' from origin 'https://domain1.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET https://api.domain1.com/rest/v1/reviews net::ERR_FAILED 200
Network tab of Chrome's inspector shows a list of requests, but just 2 requests are relevant to my issue:
Name: reviews; Method: Options; Status 200; Type: preflight.
Name: reviews; Method: GET + Preflight; Status: CORS error; Type: xhr
My Nginx config:
proxy_cache_path /tmp/backend_cache levels=1:2 keys_zone=backend_cache:250m max_size=250m inactive=2d use_temp_path=off;
proxy_cache_key "$scheme$request_method$http_domain$host$request_uri";
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_lock_age 30s;
proxy_cache_revalidate on;
proxy_cache_valid 200 302 30m;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
upstream fastapi {
ip_hash;
server backend-fastapi:80;
}
server {
listen 80 default_server;
server_name api.domain1.com api.domain2.com;
charset utf-8;
keepalive_timeout 5;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1m;
proxy_connect_timeout 1m;
proxy_pass http://fastapi;
proxy_cache backend_cache;
}
}
Preflight happens because I have custom header.
If I remove the line proxy_cache backend_cache; everything works without problem. Is there a way to use cache and avoid error?

Why is nginx not intercepting errors enve with proxy_intercept_errors on?

I'm setting proxy_intercept_errors on but nginx is not intercepting the 404 sent back from the server.
Any thoughts on what I should try?
error_page 403 404 500 502 503 504 /error.html;
location = /error.html {
ssi on;
internal;
}
location / {
proxy_intercept_errors on;
proxy_set_header host __THE HOST__;
proxy_set_header X-Real-IP $remote_addr;
resolver 8.8.8.8;
proxy_pass https://__THE IP__$request_uri;
proxy_redirect off;
}

nginx reverse proxy 302 custom handler not working

location / {
fastcgi_intercept_errors on;
proxy_pass https://drive.google.com/uc?$query_string;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host drive.google.com;
proxy_set_header Referer https://drive.google.com;
error_page 301 302 307 = #handle_redirects;
}
location #handle_redirects {
set $redirect_location '$upstream_http_location';
proxy_pass $redirect_location;
proxy_cache ngx-cache;
proxy_cache_key $query_string;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
curl -I -A "ua" https://server/dl?id=trhtyjkfktkghjsutrtujyuk return 302 directly rather than go to handle_redirects section,this config works on my another vps with server Tengine,but it doens't work on my another vps with original edition nginx,have no idea where gone wrong.any help would be appreciated.thanks!!
I believe you need to add:
proxy_intercept_errors on;
Stolen from Intercepting backend 301/302 redirects (proxy_pass) and rewriting to another location block possible?
I had a similar issue while trying to proxy the images from https://picsum.photos website. They return a 302 redirect to a HMAC-signed URL when requesting a particular picture.
The working solution for me is:
server {
listen 80;
server_name dog.localhost.direct;
location / {
proxy_ssl_server_name on;
proxy_intercept_errors on;
error_page 301 302 307 = #handle_redirect;
proxy_pass https://picsum.photos/id/237/536/354;
}
location #handle_redirect {
set $saved_redirect_location '$upstream_http_location';
resolver 8.8.8.8;
proxy_pass $saved_redirect_location;
}
}
Hope this will help somebody.

Nginx - Upstream redirect not working

Hoping someone can point out my failing with my config.
I have an issue where my upstream redirect does not work as it should (must be a config issue) , it redirects from https to http, which I do not have running at the moment. Obviously I require my https server to only serve secure traffic and not redirect to http.
This is what I receive in my browser bar :
http://nginx.dev1.whispir.net/tmpl/home.tmpl#!/web_com/View_Workspace?rd=1307
But I require it to go to upstream over https.
In the debug of the browser I see :
GET http://nginx.dev1.whispir.net/tmpl/home.tmpl net::ERR_CONNECTION_REFUSED
Cannot fathom out why it is hitting port 80.
I have turned off http on port 80, as I require the https working.
I hope someone can help here, driving me insane.
thanks for looking.
This is my current config for port 443
upstream HttpsMainWorker {
# Sticky session
ip_hash;
server 10.1.161.59:8080;
server 10.1.161.56:8080;
}
upstream HttpsReportWorker {
# Sticky session
ip_hash;
server 10.1.161.64:8080;
}
upstream HttpsApiWorker {
# Sticky session
ip_hash;
server 10.1.161.51:8080;
}
server {
listen 443 ssl;
server_name nginx.dev1.whispir.net;
keepalive_timeout 70;
ssl on;
ssl_certificate /etc/nginx/certs/2016/61d2d567aece769c.crt;
ssl_certificate_key /etc/nginx/certs/2016/wildcard.dev1.whispir.netclear.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/app17web/access.log main;
error_log /var/log/nginx/app17web/error.log debug;
root /data/htdocs/app17web.dev1.whispir.net;
index index.jsp;
rewrite_log on;
location ~* \.(?:ico|css|js|gif|jpe?g|png|pdf)$ {
expires 1d;
add_header Pragma public;
add_header Cache-Control "public";
}
error_page 401 /401.html;
error_page 403 /403.html;
error_page 500 502 /500.html;
error_page 503 /503.html;
error_page 400 404 /404.html;
location = /404.html {
internal;
}
error_page 500 502 503 /50x.html;
location = /50x.html {
root html;
}
location /{
try_files $uri #backend;
}
location #backend {
proxy_pass http://HttpsMainWorker;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ \.jsp$ {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /ivr/ivrRequest.ivr {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /app/cfu/* {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /tmpl/* {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
Most likely the upstream application (running on port 8080) is issuing the redirect. Either it needs to be configured to use https in a redirect, or it needs to be informed that the frontend connection arrived over https.
Your configuration inserts a header X-Forwarded-Proto for that purpose, but only for one of the locations.
The proxy_set_header directive is inherited from the outer block, only if no other proxy_set_header directives are set in the location.
So, either add a proxy_set_header X-Forwarded-Proto $scheme; statement into each affected location block, or move all of your proxy_set_header directives into the server block scope.
For example:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location #backend {
proxy_pass http://HttpsMainWorker;
}
location ~ \.jsp$ {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /ivr/ivrRequest.ivr {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /app/cfu/* {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
location /tmpl/* {
proxy_pass http://HttpsMainWorker;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 5s;
}
See this document for details.

nginx unknown directive "keepalive"

I am using the following configuration
upstream site {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 80;
error_page 400 404 500 502 503 504 /50x.html;
location /50x.html {
internal;
root /usr/share/nginx/www;
}
location /static {
root /opt/site/static;
access_log off;
expires max;
}
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://site;
proxy_intercept_errors on;
}
}
I have saved it to /etc/nginx/sites-available/site.conf and symlinked to it /etc/sites-enabled/site.conf , and when I restart nginx it gives me the following error:
Restarting nginx: [emerg]: unknown directive "keepalive" in /etc/nginx/sites-enabled/site.conf:3
There are no keepalive directive. Use keepalive_timeout instead. And you can't put it inside upsream, use inside http, server or location.
Option "keepalive" is provided by keepalive module. And since 1.1.4 keepalive functionality is included in the main code.

Resources