If an Nginx location block is not redirecting, first prove which server and location handled the request, then replace ambiguous rewrite logic with an explicit return. Nginx selects locations by a strict precedence algorithm; an exact match, a longer prefix, a ^~ prefix, or a regular expression can prevent the block you edited from running. A try_files, error_page, proxy, or upstream application can also perform a later internal or external redirect.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
The dependable workflow is: inspect the loaded configuration with nginx -T, compare the real URI with every competing location, use return 301 (or a temporary status while testing) for a client-visible redirect, validate with nginx -t, reload the correct Nginx instance, and observe one request with curl and the access and error logs.
As an Amazon Associate I earn from qualifying purchases.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What Nginx is actually doing when a location does not redirect
A location block is not selected because it appears first in the file or because its text looks most specific. Nginx first chooses the appropriate server block for the connection, host, and port. It then tests the request URI against the locations in that server. The query string is not part of location matching, so /old?ref=mail is matched as /old.
NGINX documentation describes the process this way: it tests request URIs against the parameters of all location directives and applies the directives in the matching location. Understanding that process usually explains an apparently ignored redirect.
#1 Best Overall
Location precedence
| Syntax | What it matches | Effect on selection |
|---|---|---|
location = /path |
Only the exact URI /path |
Wins immediately; Nginx does not continue searching. |
location /path/ |
A prefix beginning with /path/ |
The longest matching prefix is retained as the current candidate. |
location ^~ /path/ |
A prefix beginning with /path/ |
If this is the longest prefix, regular-expression locations are not tested against the request. |
location ~ pattern or location ~* pattern |
A case-sensitive or case-insensitive regular expression | After the prefix phase, the first matching regex in configuration order can take over, unless the retained prefix used ^~. |
For example, location /old can be overtaken by a regex such as location ~ .php$ for /old/index.php. Conversely, location ^~ /old/ keeps that request in the prefix location and prevents the regex from overriding it. An exact block such as location = /old is decisive for that one URI, but it does not match /old/ or /old/index.php.
Start with the active configuration, not the file you edited
Multiple configuration files, include directories, containers, packages, or service instances can make an apparently correct edit ineffective. Inspect the complete expanded configuration from the same Nginx installation that will be reloaded.
- Identify the binary and compiled paths. Run
nginx -Vwith the privileges required on your system. Its output exposes the configure arguments, including compiled-in paths that can differ from the file you expected. - Dump the loaded configuration. Run
sudo nginx -T. Search the output for the intendedserver_name, itslistendirectives, everyinclude, and all locations that could match the URI. The dump is more authoritative than an unreferenced file on disk. - Confirm the selected virtual server. Check the request’s host and port against
server_nameandlisten. A request sent to an IP address, an alternate port, or a different hostname can reach the default server instead of the block you changed. - Check that the request reaches this Nginx instance. In environments with a load balancer, reverse proxy, container, or multiple hosts, verify that DNS and the destination address point to the process whose configuration you inspected.
If the intended location is absent from nginx -T, fix the include path or edit the configuration actually loaded. Do not proceed by repeatedly reloading a different instance.
Compare the real URI with the location patterns
Write down the exact request path, including its leading slash, trailing slash, percent encoding, and case. Then compare it with each candidate location. These small differences are common causes of a missed match:
/oldand/old/are different for an exact match.- A case-sensitive regex does not match a different case;
~*makes the regex case-insensitive. /old/filemay match a prefix block even when you intended only the single path/old.- The query string, such as
?next=/new, does not influence location selection. - Percent-encoded characters and normalized paths can make what the client displays differ from the URI Nginx evaluates.
Use an exact location when one URL must redirect and a prefix location when an entire subtree must redirect. Add a trailing-slash rule deliberately rather than assuming a prefix will cover both forms.
Rank #2
Use return for a straightforward client redirect
For a redirect visible to the browser or API client, return is the clearest directive. NGINX documentation calls it the easiest way to issue this kind of response. It can be placed in server or location context.
Free tools Windows power users keep installed
One-click scans. No signup required.
Exact-path example
server {
listen 80;
server_name example.com;
location = /old {
return 301 https://example.com/new;
}
}
A request for http://example.com/old receives a 301 response with a Location: https://example.com/new header. The browser then makes a second request to the destination. The exact block does not redirect /old/; add a separate exact rule or choose an intentional prefix rule if both URLs should move.
Redirecting a subtree
location ^~ /legacy/ {
return 301 https://example.com/current$request_uri;
}
Here $request_uri preserves the original path and query string. Use variables only when you have verified the resulting destination; an accidental variable can create malformed URLs or reflect an untrusted host. If the old and new paths have different structures, write the destination explicitly instead of blindly appending the old URI.
Place a server-wide redirect at server context when appropriate
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
This pattern redirects every request handled by that HTTP server to HTTPS before any location-specific content processing. Do not put it in the TLS server as well unless you intentionally want another redirect; a duplicate rule can create a loop or obscure which block responded.
Choose the right status code while testing and deploying
| Status | Use | Important behavior |
|---|---|---|
| 301 | Permanent move after the destination is confirmed | Browsers and caches may retain it, making later tests appear to use an old result. |
| 302 | Temporary redirect during a short-term change or test | Clients generally recheck the original URL more readily than with a 301. |
| 307 | Temporary redirect when the HTTP method and request body must be preserved | Useful for method-sensitive APIs; test the client behavior explicitly. |
A 301 is not a better debugging status simply because it is common. Use a temporary response while proving the match, then change it to a permanent status only when the move is final and caches should be updated.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #3
Use rewrite only when you need conditional or captured logic
rewrite evaluates a regular expression and can construct a new URI from captures. It is useful for many source paths, conditional transformations, or rules that need flags, but it has more moving parts than return.
External rewrite
location /old/ {
rewrite ^/old/(.*)$ https://example.com/new/$1 redirect;
}
The redirect flag produces a temporary client redirect. A permanent external rewrite can use permanent, which sends a 301. For a fixed destination, an explicit return remains easier to audit.
Internal rewrite and the last flag
location /legacy/ {
rewrite ^/legacy/(.*)$ /current/$1 last;
}
location /current/ {
# Content handling for the rewritten URI
}
last stops the current rewrite set and starts a new location search using the rewritten URI. That is intentional when another location must process /current/, but it also means the request can enter a different block than the one where the rule appears.
The break flag
location /legacy/ {
rewrite ^/legacy/(.*)$ /current/$1 break;
# Continue processing in this same location
}
break stops the current rewrite directives without performing a new location lookup. Use it when the current location should continue handling the changed URI. Choosing last when you meant break, or the reverse, is a frequent reason that a redirect appears to be ignored or that unexpected content is served.
Prevent rewrite cycles
Never rewrite a URI into a path that re-enters the same rule without a terminating condition. For example, a rule that changes /old to another URI still matched by the same expression can repeatedly trigger internal redirects. Check both the source and destination against every regex and prefix location. If Nginx reports too many internal redirects, remove the cycle, use a more precise pattern, or replace the rule with a direct return.
Rank #4
Check directives that can run after location selection
Finding the expected location does not prove that its response is the final response. Several directives and upstream components can change the request flow.
try_files can internally redirect
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /old {
return 301 https://example.com/new;
}
try_files checks files and directories and can internally redirect to its final argument. If the request is handled by a broad location containing try_files, it may end up at an application entry point instead of producing the redirect you expected. Put a precise redirect location ahead of the broad handling logic, and verify that the actual URI still matches it.
index and slash normalization
A directory request can cause an internal redirect to an index URI, and Nginx may redirect a directory-like path to a trailing-slash form in some configurations. Decide whether /game, /game/, or both should redirect, then test each separately.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteerror_page and proxy responses
An error_page can route an error to another URI. A proxied server can return its own 3xx response, and an upstream application can emit a Location header even when Nginx itself did not issue the redirect. Inspect the response status and headers with verbose client output and correlate them with the logs before changing the location rule.
Diagnose with a controlled request
- Test headers without following the redirect. Run
curl -I http://example.com/old. Record the status and everyLocationheader. - See the complete exchange. Run
curl -v http://example.com/old. Confirm the host, scheme, destination address, request path, status, and whether a second response is coming from an upstream. - Test the exact variants. Repeat for
/old/, a representative child path, different case where relevant, and a query string. This distinguishes an exact-match mistake from a broader routing issue. - Prevent client-side follow-up from hiding the first response. Do not start with
-L. If you later usecurl -IL, inspect every hop, because a first redirect can be followed by a second redirect or a loop. - Use the intended scheme and port. Test HTTP and HTTPS separately when both servers exist. Include a non-default port in the URL when the listener requires it.
Read access and error logs while making one request
Tail the configured access and error logs, issue one controlled request, and match its timestamp. The access log shows which request produced the status; the error log often explains rewrite processing, file checks, upstream behavior, or redirect loops.
Best Value
The error_log directive sets up the error log. An error_log inside a server or location overrides inherited logging settings, so inspect the effective scope in nginx -T instead of assuming all messages go to one global file.
If normal logs are insufficient and the build supports it, temporarily raise the error_log level or enable debug logging for a controlled client address. Reproduce one request, collect the evidence, and return the logging level to normal; verbose debug logs can be large and may expose request details.
Recommended Free Tools
Validate and reload the same Nginx instance
- After editing, run
sudo nginx -t. Do not reload if syntax or referenced-file validation fails. - Use the configuration path and binary identified by
nginx -Vif several installations exist. - Reload that instance using the service mechanism for your system, then confirm the worker processes received the new configuration.
- Run the same
curlrequest again and compare the status,Location, host, scheme, and trailing slash with the previous result.
A successful syntax test means the configuration parses; it does not prove that the intended server handles the request or that the selected location is the one you expected. Keep the log and header check in the loop after every reload.
Common symptoms and targeted fixes
| Symptom | Likely cause | What to check |
|---|---|---|
| The old page is served with 200 | A different location or server won, or a broad handler such as try_files processed it. |
nginx -T, host/port, exact URI, and access logs. |
| A redirect occurs for one spelling but not another | Exact matching, case sensitivity, or trailing-slash differences. | Test each URI variant and adjust exact, prefix, or regex syntax. |
| Your regex never runs | A longer ^~ prefix prevented regex evaluation. |
Compare all prefixes and remove or narrow ^~ only if regex handling is required. |
The response has an unexpected Location header |
A proxy or upstream application issued it, or an error_page changed the flow. |
Verbose headers, upstream logs, proxy settings, and error-page directives. |
| Nginx reports an internal redirect cycle | rewrite ... last, try_files, or an error-page target re-enters the same rule. |
Map source and destination URIs and add a terminating condition or use break where appropriate. |
| Changes have no effect | The edited file is not included or a different Nginx process was reloaded. | nginx -T, nginx -V, process/service identity, and reload output. |
| Only cached clients show the old behavior | A previous 301 was cached. | Use a temporary status during testing and inspect the first response with curl. |
A repeatable configuration pattern
For a single legacy URL, keep the rule isolated and exact:
server {
listen 80;
server_name example.com;
location = /old {
return 302 https://example.com/new;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Use the 302 while verifying the destination and client behavior. Once the move is permanent, change only the status to 301 after testing both the source URL and any variants that should or should not match. For a subtree, replace the exact location with a deliberately scoped prefix and document whether a regex location is allowed to override it.
Production checklist
- The request reaches the intended
server_nameandlistensocket. nginx -Tcontains the edited location and shows all competing locations and includes.- The location syntax matches the actual path, case, and trailing-slash policy.
- An exact match is used for one URL; a prefix or regex is used only when its broader scope is intended.
^~is present only when regex locations must not override the prefix.- A fixed client-visible move uses
return;rewriteis reserved for conditional or captured transformations. lastandbreakare chosen according to whether a new location search is required.try_files,index,error_page, proxy behavior, and upstream redirects have been checked.nginx -tsucceeds before reload, and the same instance identified bynginx -Vis reloaded.curl -Iorcurl -vconfirms the first status andLocationheader without hiding it behind automatic follow-up requests.- Access and error logs are correlated with one test request, with temporary debug logging removed afterward.
Following those checks turns an “ignored location” into a traceable routing decision: identify the winning server and location, make the response explicit, account for internal rematching, and verify the final headers from the running process.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




