The rewrite
directive in Nginx is powerful but often misunderstood, particularly when it comes to flag behavior. Many developers struggle with subtle differences between break
and last
flags, which can lead to unexpected routing behavior.
# Example showing different processing paths
location /test {
rewrite ^/test/foo /bar last;
rewrite ^/test/bar /baz break;
# These lines will only execute for 'break' case
proxy_pass http://backend;
}
The critical distinction lies in how Nginx continues processing after the rewrite:
- last: Stops current processing and starts new location search
- break: Stops all rewrite processing immediately
Consider this configuration for handling both static assets and API requests:
location /api {
rewrite ^/api/v1/(.*)$ /v1_handler.php?endpoint=$1 last;
rewrite ^/api/(.*)$ /legacy_handler.php?path=$1 break;
fastcgi_pass php_backend;
}
location /v1_handler.php {
internal;
# Special processing for modern API
}
Add these directives to observe the processing flow:
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;
Using last
incorrectly can create loops:
# DON'T DO THIS - infinite loop risk
location /admin {
rewrite ^/admin/(.*) /admin/$1 last;
}
Instead, use break
when you need to prevent further rewrites:
location /secure {
rewrite ^/secure/(.*) /internal/$1 break;
proxy_pass http://internal_server;
}
The choice impacts Nginx processing:
last
causes additional location matching phasebreak
continues with current location's remaining directives
Here's a complete working example demonstrating the difference:
server {
listen 80;
server_name example.com;
location /shop {
rewrite ^/shop/cart /checkout last;
rewrite ^/shop/(.*) /products/$1 break;
# This only executes for break case
try_files $uri $uri/ =404;
}
location /checkout {
# Process checkout requests
}
}
Use last when:
- You need to change processing context
- Redirecting to another named location
- Implementing API versioning
Use break when:
- Final URL should be processed in current location
- Preventing further rewrites
- Handling static file rewrites
In Nginx URL rewriting, both break
and last
flags terminate current rewrite processing, but their subsequent behavior differs significantly:
rewrite ^/old-path /new-path break;
rewrite ^/old-path /new-path last;
The last
flag stops current rewrite phase and starts a new matching cycle against the new URI, while break
stops processing altogether without initiating a new cycle.
Consider this configuration showing different outcomes:
location /test/ {
rewrite ^/test/(.*) /new/$1 last;
rewrite ^/new/(.*) /final/$1;
}
location /new/ {
# This block will be processed with 'last'
}
With break
instead of last
, Nginx would never reach the second rewrite
rule nor the /new/
location block.
When to use 'last':
# Use when you want subsequent location blocks to process the rewritten URI
rewrite ^/api/v1/(.*) /internal/$1 last;
When to use 'break':
# Use for final URI processing within current context
rewrite ^/static/(.*)$ /cdn/$1 break;
Remember that last
initiates a new matching cycle, which has slightly more overhead than break
. For high-traffic scenarios with many rewrites, this can become noticeable.
Add these directives to observe the rewrite flow:
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;