I'm trying to achieve some redirection with location
and return
but nginx always seems to ignore/skip all of the location
blocks and I don't understand why... I need to strip the /CustomContext
part from the URL.
server {
listen 8120 ssl; # legacy HTTPS port
server_name server.domain.com;
error_log /var/log/nginx/error.log debug;
location / {
return 444;
}
location ~ "^/CustomContext/(.*)$" {
return 301 https://custom.domain.com/$1$is_args$args;
}
return 444;
}
I'd expect some "test location" entries after "rewrite phase: 1" in the log but there are none:
2025/06/24 11:45:18 [debug] 20#20: *1 http process request line
2025/06/24 11:45:18 [debug] 20#20: *1 http request line: "GET /CustomContext/services/version HTTP/1.1"
2025/06/24 11:45:18 [debug] 20#20: *1 http uri: "/CustomContext/services/version"
2025/06/24 11:45:18 [debug] 20#20: *1 http args: ""
2025/06/24 11:45:18 [debug] 20#20: *1 http exten: ""
2025/06/24 11:45:18 [debug] 20#20: *1 posix_memalign: 00007F47955376D0:4096 @16
2025/06/24 11:45:18 [debug] 20#20: *1 http process request header line
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Host: server.domain.com:8120"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Connection: keep-alive"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Pragma: no-cache"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Cache-Control: no-cache"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "sec-ch-ua: "Microsoft Edge";v="137", "Chromium";v="137", "Not/A)Brand";v="24""
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "sec-ch-ua-mobile: ?0"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "sec-ch-ua-platform: "Windows""
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Upgrade-Insecure-Requests: 1"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Sec-Fetch-Site: none"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Sec-Fetch-Mode: navigate"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Sec-Fetch-User: ?1"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Sec-Fetch-Dest: document"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Accept-Encoding: gzip, deflate, br, zstd"
2025/06/24 11:45:18 [debug] 20#20: *1 http header: "Accept-Language: en-US,en;q=0.9,de;q=0.8,de-DE;q=0.7"
2025/06/24 11:45:18 [debug] 20#20: *1 http alloc large header buffer
2025/06/24 11:45:18 [debug] 20#20: *1 posix_memalign: 00007F4795546020:512 @16
2025/06/24 11:45:18 [debug] 20#20: *1 malloc: 00007F4795664AE0:8192
2025/06/24 11:45:18 [debug] 20#20: *1 http large header alloc: 00007F4795664AE0 8192
2025/06/24 11:45:18 [debug] 20#20: *1 http large header copy: 240
2025/06/24 11:45:18 [debug] 20#20: *1 SSL_read: 517
2025/06/24 11:45:18 [debug] 20#20: *1 SSL_read: -1
2025/06/24 11:45:18 [debug] 20#20: *1 SSL_get_error: 2
[...]
2025/06/24 11:45:18 [debug] 20#20: *1 http header done
2025/06/24 11:45:18 [debug] 20#20: *1 event timer del: 14: 176555899
2025/06/24 11:45:18 [debug] 20#20: *1 generic phase: 0
2025/06/24 11:45:18 [debug] 20#20: *1 rewrite phase: 1
2025/06/24 11:45:18 [debug] 20#20: *1 http finalize request: 444, "/CustomContext/services/version?" a:1, c:1
2025/06/24 11:45:18 [debug] 20#20: *1 http terminate request count:1
2025/06/24 11:45:18 [debug] 20#20: *1 http terminate cleanup count:1 blk:0
2025/06/24 11:45:18 [debug] 20#20: *1 http posted request: "/CustomContext/services/version?"
2025/06/24 11:45:18 [debug] 20#20: *1 http terminate handler count:1
2025/06/24 11:45:18 [debug] 20#20: *1 http request count:1 blk:0
2025/06/24 11:45:18 [debug] 20#20: *1 http close request
2025/06/24 11:45:18 [debug] 20#20: *1 http log handler
2025/06/24 11:45:18 [debug] 20#20: *1 free: 00007F47955352F0, unused: 112
2025/06/24 11:45:18 [debug] 20#20: *1 free: 00007F47955376D0, unused: 2672
2025/06/24 11:45:18 [debug] 20#20: *1 close http connection: 14
2025/06/24 11:45:18 [debug] 20#20: *1 SSL_shutdown: 1
2025/06/24 11:45:18 [debug] 20#20: *1 reusable connection: 0
2025/06/24 11:45:18 [debug] 20#20: *1 free: 00007F4795664
Switching to rewrite
statement works:
server {
listen 8120 ssl; # legacy HTTPS port
server_name server.domain.com;
rewrite ^/CustomContext/(.*)$ https://custom.domain.com/$1$is_args$args permanent;
return 444;
}
To fix the described problem, remove the server-block return:
server {
...
location / {
return 444;
}
...
# return 444; <-- delete this
}
It's redundant, but also problematic.
The return directive can be used in a server
context - but if it is, it's expected to be used alone as it applies unconditionally to all requests. This explains the observed behavior but also the debug logs - there are no test location
debug log messages not because nginx is ignoring the location blocks - but the request ends before reaching the phase to check them.
Without that server
return, requests that don't match any other location block will be processed by the location /
block - which acts as the fallback. So the end result matches the intent.