nginx: Is it possible to have an 'catch all' error_page? - configuration

When looking at the documentation for nginx's error_page directive, it seems that one has to manually list out every possible status code that nginx (or an upstream server) could return.
For example:
error_page 404 /404.html;
error_page 502 503 504 /50x.html;
error_page 403 http://example.com/forbidden.html;
error_page 404 = #fetch;
Is there anyway of producing a wildcard for ALL status codes that are not specified directly... For example:
error_page 404 /404.html;
error_page 5xx /50x.html;
or
error_page 404 /404.html;
error_page 502 503 504 /50x.html;
error_page #catchall /5xx.html;

It is not possible.
Moreover, it is not recommended to blindly list all codes, as
nginx allows to redefine all response codes, including ones you don't really want to redefine except in a few very specific situations (e.g. you don't normally want to redefine 304 (Not Modified), and probably not 302 (Found) unless there are very specific reasons);
redefining some of the error codes might cause more harm than good (e.g. redefining 400 (Bad Request) is a bad idea).

location {
...
error_page
301 302 303 304 307 308
400 401 402 403 404 405 406 408 409 410 411 412 413 414 415 416 421 429
500 501 502 503 504 505 507
#errors;
location #errors {
internal;
default_type "text/plain; charset=utf-8";
return 200 "$status\n";
}
}
Responses can provide status messages like "404 Not Found" by defining a map for each HTTP code, as described in One location block for all Nginx error codes

Related

nginx returning index.html for js with 304 response

I have an nginx server that is showing a 200 response in my browser for requests like
https://server.com/app/static/js/2.8cc049f3.chunk.js
and showing a 304 on the server logs
"GET /static/js/2.8cc049f3.chunk.js HTTP/1.1" 304 0 "https://server.com/app"
There is another nginx in front of the nginx running on server.com that is removing the app from the path. Based on the nginx logs on server.com this is working correctly. The static folder is in my root /usr/share/nginx/html/.
The content my browser receives for the js file is the index.html. However when I login to the server and run
curl http://localhost/static/js/2.8cc049f3.chunk.js
I get the correct js content in response and in the logs the server prints 200
"GET /static/js/2.8cc049f3.chunk.js HTTP/1.1" 200 1570391 "-" "curl/7.80.0" "-"
Here is my nginx.conf
server {
listen 80;
root /usr/share/nginx/html/;
index index.html;
add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
try_files $uri $uri/ /index.html;
}
location ~ ^/(static)/ {
gzip_static on;
gzip_types
text/plain
text/xml
text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;
expires max;
}
}
I've read that a 304 means the file hasn't changed and tells your browser to use its local cache, so I cleared my browser cache. I also restarted nginx, thinking that the first request would give a 200 response on the server but it was still a 304.
Based on the local curl request being successful I don't think there is anything wrong with my nginx.conf. I don't know if nginx somehow has the index.html cached as the content of my js, or if I didn't clear my browser cache correctly.
I'm also confused why the response code is 304 on the server but 200 in my browser.
The HTTP 304 says "Not-Modified". This is because you are using another NGINX Proxy server in front of the NGINX Server we are talking about.
The 1st NGINX is requesting a resource on the 2nd NGINX and this one answers "Hey that file was not modified since the last time you have asked".
In this case it would be very helpful to check the configuration of the 1st NGINX Proxy instance or your turn of the caching in the first one and proxy_cache off; and check the result.

Nginx Ingress Controller trailling slash with HTTPS redirect

Nginx Ingress Controller trailling slash with HTTPS redirect
I'm trying to redirect requests from HTTP to HTTPS using an Ingress with Nginx Ingress Controller. My app is written in Django v3.0.7, my Nginx Controller is v0.46.0 and k8s v1.19.8.
I have the following ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: INGRESS-NAME
namespace: INGRESS-NS
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
cert-manager.io/cluster-issuer: "ISSUER-NAME"
nginx.ingress.kubernetes.io/permanent-redirect-code: '308'
spec:
tls:
...
rules:
- host: MY-DOMAIN
http:
paths:
- path: /api/v1/?(.*)
pathType: Prefix
backend:
service:
name: SVC-NAME
port:
number: SVC-PORT
Requests at https://.../api/v1/get-token/, raise this error:
[05/May/2021:20:39:49 +0000] "POST /api/v1/get-token// HTTP/1.1" 404 => POST get an extra / at the end. But the same request with HTTP or https://.../api/v1/get-token (no trailing /) is fine.
If I remove the
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
The redirect removes trailing / and it causes POST to turn into GET in all HTTP POST request causing an 403 - Method not allowed as shown in Nginx Logs:
[05/May/2021:20:54:52 +0000] "POST /api/v1/get-token HTTP/1.1" 308 164
[05/May/2021:20:54:53 +0000] "POST /api/v1/get-token HTTP/1.1" 301 0
[05/May/2021:20:54:53 +0000] "GET /api/v1/get-token/ HTTP/1.1" 405
but HTTP POST request works fine with http://.../api/v1/get-token// (two trailing /).
Is there a way to solve this problem? The 308 HTTP -> HTTPS redirect is important, so I can't remove it, but is there a way to force requests to have one, and only one, trailing /? Thanks.
There are two problems here
Problem #1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
causes requests sent to https://.../api/v1/get-token/ to end with HTTP 404 Not Found, but https://.../api/v1/get-token woks fine.
Why?
Because trailing / at the end of nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/ rewrite is added to the URL, and /api/v1/get-token// leads to a resource that does not exist.
What to do about it?
Change path key to /api/v1/?(.*\b)/. I'm not 100% sure it will work, but it's worth a try.
or
Remove trailing / from rewrite.
Now, doing that causes problem #2.
Problem #2
Requests to https://.../api/v1/get-token ends with 405 Method Not Allowed.
Why?
First redirection works fine (HTTP 308), however request is redirected again with HTTP 301.
MDN article on HTTP 301 states:
Even if the specification requires the method (and the body) not to be altered when the redirection is performed, not all user-agents align with it - you can still find this type of bugged software out there. It is therefore recommended to use the 301 code only as a response for GET or HEAD methods and to use the 308 Permanent Redirect for POST methods instead, as the method change is explicitly prohibited with this status.
Basically HTTP 301 causes POST to become GET, and GET is not allowed, hence HTTP 405.
What to do about it?
Make sure not to redirect requests twice, especially with HTTP 301.

HAProxy 1.5 - Serving static json file on 504 error

I'm trying to set up HAProxy to server a static JSON file on 504 errors. To test, we've set up the configuration file to timeout after 10 seconds, and to use the errorfile option:
defaults
log global
mode http
retries 3
timeout client 10s
timeout connect 10s
timeout server 10s
option tcplog
balance roundrobin
frontend https
maxconn 2000
bind 0.0.0.0:9000
errorfile 504 /home/user1/test/error.json
acl employee-api-service path_reg /employee/api.*
use_backend servers-employee-api if employee-api-service
backend servers-employee-api
server www.server.com 127.0.0.1:8000
Effectively, I'm trying to serve JSON instead of HTML on a timeout, so the backend service can fail gracefully. However, on testing, we could not get anything, neither HTML or JSON. On looking at the response, it simply says it failed, with no status code. Is my setup correct for errorfile? Does HAProxy 1.5 support this?
According to the documentation of errorfile:
<file> designates a file containing the full HTTP response. It is
recommended to follow the common practice of appending ".http" to
the filename so that people do not confuse the response with HTML
error pages, and to use absolute paths, since files are read
before any chroot is performed.
So, the file should contain a complete HTTP response but you're trying to serve JSON only.
The documentation further says that:
For better HTTP compliance, it is
recommended that all header lines end with CR-LF and not LF alone.
The example configuration, for example,
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
shows the common practice of .http extension for the error file.
You can find samples of some default error files here.
Sample (504.http):
HTTP/1.0 504 Gateway Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<html><body><h1>504 Gateway Time-out</h1>
The server didn't respond in time.
</body></html>
So, in your scenario, 504.http would be like this:
HTTP/1.0 504 Gateway Time-out
Cache-Control: no-cache
Connection: close
Content-Type: application/json
{
"message": "Gateway Timeout"
}
Also, you need to keep the file size under limit i.e. BUFSIZE (8 or 16 KB) as described in the documentation.
There might be some error logs for not serving your JSON file. You might want to look at HAProxy's logs again thoroughly. Just to be sure.

favicon.ico 503 (Service Unavailable)

When running a GET request for the root url of my deployment for the designated route, I get an HTTP Status 503 for /favicon.ico
http://blog-xyz-blog.1234.starter-us-east-1.openshiftapps.com/favicon.ico <- amended URL for privacy..
I then rsh onto the pod and curl the localhost url for the root url, and I get an HTTP 200, and same when I curl the /favicon.ico
I added the link to my index.html section, and the same issue occurring.
Any ideas why this is occurring?
Thanks

What is wrong with my .htaccess? 500 Internal server error

would you know what the issue is?
This works:
SetEnv PHP_VER 5_3
SetEnv REGISTER_GLOBALS 0
ErrorDocument 404 /index.html
ErrorDocument 403 http://www.dsfds.lu
This doesn't work and return a "500 Internal server error":
SetEnv PHP_VER 5_3
SetEnv REGISTER_GLOBALS 0
ErrorDocument 404 /index.html
ErrorDocument 403 http://www.dsfds.lu
Redirect 301 /biographie-dfd-fdd/ biographie.html
You need to use the full URL as the second argument
Redirect 301 /biographie-dfd-fdd/ http://website.com/biographie.html