# Nginx rewrite: last & break

**URL:** <https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012>\
**Category:** NGINX\
**Created:** [October 20, 2011, 6:12pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012 "2011-10-20T18:12:23Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [October 20, 2011, 6:12pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/1 "2011-10-20T18:12:23Z")

</div>

Hello,

According to document: [Module ngx\_http\_rewrite\_module](http://wiki.nginx.org/HttpRewriteModule#rewrite)

It said “break - completes processing of rewrite directives and  
breakes location lookup cycle by not doing any location lookup and  
internal jump at all”

However, seems my config below is an exception?

server {  
listen 80;

```
    server_name .example.com
    root /data/example/;

    if ($request_uri ~ "foo") {
        rewrite ^/foo /bar break;
    }

    location /bar {
        echo "error";
    }

```

}

When I curl using: curl [http://example.com/foo](http://example.com/foo)

the string “error” was returned.

However, isn’t the break will skip any following location block? So it  
shouldn’t matche the location below, right?

Thanks.

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 20, 2011, 6:39pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/2 "2011-10-20T18:39:07Z")

</div>

Hello!

On Fri, Oct 21, 2011 at 12:12:01AM +0800, Ryan C. wrote:

> server {  
> echo “error”;  
> }  
> }
> 
> When I curl using: curl [http://example.com/foo](http://example.com/foo)
> 
> the string “error” was returned.
> 
> However, isn’t the break will skip any following location block? So it  
> shouldn’t matche the location below, right?

Processing of rewrite directives at server level may be stopped  
via break, but the location lookup will follow anyway (as there is  
no location at this stage where request may be processed).

Note original documentation doesn’t say anything about “breakes  
location lookup cycle …”. It’s looks like it was added by  
Agentzh here:

> **[GitHub - nginxinc/nginx-wiki: ARCHIVED -- Source for the now archived NGINX Wiki...](https://github.com/nginxinc/nginx-wiki)**
>
> ARCHIVED -- Source for the now archived NGINX Wiki section of https://www.nginx.com

I’ve reverted it as it’s incorrect and obviously causes confusion.

Maxim D.

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 20, 2011, 6:55pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/3 "2011-10-20T18:55:18Z")

</div>

On 20 October 2011 19:38, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > internal jump at all"  
> > rewrite ^/foo /bar break;

> **[GitHub - nginxinc/nginx-wiki: ARCHIVED -- Source for the now archived NGINX Wiki...](https://github.com/nginxinc/nginx-wiki)**
>
> ARCHIVED -- Source for the now archived NGINX Wiki section of https://www.nginx.com

> I’ve reverted it as it’s incorrect and obviously causes confusion.

Still quite confusing because the “last” portion goes on to say “after  
which searches for corresponding URI and location”. As the “break”  
part does not say anything, it implies that “after which DOES NOT  
search for corresponding URI OR location”. I.E. It implies what  
agentzh wrote.

Perhaps needs some clarification about it being appropriate at server  
level (If I understand you — totally confused lol).

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 21, 2011, 6:20am UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/4 "2011-10-21T06:20:07Z")

</div>

On Fri, Oct 21, 2011 at 12:38 AM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 

Yes, I forgot to take into account server-level rewrites. And sorry  
about that. But what I said is correct for location-level rewrites,  
no?

We definitely need more clarification here. And in fact, location jump  
actually happens in post-rewrite phase handler for location-wise  
rewrites! LOL

Regards,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 22, 2011, 5:31am UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/5 "2011-10-22T05:31:23Z")

</div>

Hello,

On Fri, Oct 21, 2011 at 12:19 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> We definitely need more clarification here. And in fact, location jump  
> actually happens in post-rewrite phase handler for location-wise  
> rewrites! LOL
> 
> Regards,  
> -agentzh
> 
> * * *

Thanks.

Anyone would like to do a quick summary for the issue?

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 21, 2011, 5:14am UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/6 "2011-10-21T05:14:45Z")

</div>

On Fri, Oct 21, 2011 at 12:54 AM, Nginx U. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Still quite confusing because the “last” portion goes on to say “after  
> which searches for corresponding URI and location”. As the “break”  
> part does not say anything, it implies that “after which DOES NOT  
> search for corresponding URI OR location”. I.E. It implies what  
> agentzh wrote.
> 
> Perhaps needs some clarification about it being appropriate at server  
> level (If I understand you — totally confused lol).

Agreed.

Perhaps need some examples as well.

It is quit dangerous because sometimes we think it just worked and it  
is ok, but in fact we are wrong

e.g.:  
[http://serverfault.com/questions/131474/nginx-url-rewriting-difference-between-break-and-last](http://serverfault.com/questions/131474/nginx-url-rewriting-difference-between-break-and-last)

I spent a whole day to debug this issue..

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 22, 2011, 4:25pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/7 "2011-10-22T16:25:49Z")

</div>

## Nginx U. Wrote:

> Adding Maxim’s statement above into account,  
> outside a location block,  
> “break” behaves just like “last” does since there  
> are no location  
> directives to run here.
> 
> Someone just needs to update the docs if this is  
> correct.

I have experienced situations when “rewrite something target last;” in  
the server {} section generates the 503 page, while “rewrite something  
target break;” instead works OK. It means that “break” does not behave  
like “last” in the server section of the virtual host either.

Andrejs

Posted at Nginx Forum:  
[http://forum.nginx.org/read.php?2,216965,217052#msg-217052](http://forum.nginx.org/read.php?2,216965,217052#msg-217052)

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 22, 2011, 1:05pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/8 "2011-10-22T13:05:05Z")

</div>

On 22 October 2011 06:30, Ryan C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Anyone would like to do a quick summary for the issue?

Minaev’s answer in the serverfault link you provided is the clearest  
explanation I have seen to date of this.

To paraphrase, he says, within a location block, when you use “last”  
the rewrites are stopped and a new subrequest is generated which will  
take all all locations into account. When you use “break” the rewrites  
are stopped and processing continued within the location you are in.

Adding Maxim’s statement above into account, outside a location block,  
“break” behaves just like “last” does since there are no location  
directives to run here.

Someone just needs to update the docs if this is correct.

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 23, 2011, 6:40am UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/9 "2011-10-23T06:40:27Z")

</div>

Hello,

On Sat, Oct 22, 2011 at 7:04 PM, Nginx U. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 

This is also my understanding, so if it is right, please update the  
wiki as this feature is quite important.

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 23, 2011, 5:26pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/10 "2011-10-23T17:26:39Z")

</div>

Hello!

On Sat, Oct 22, 2011 at 02:04:21PM +0300, Nginx U. wrote:

> On 22 October 2011 06:30, Ryan C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Anyone would like to do a quick summary for the issue?
> 
> Minaev’s answer in the serverfault link you provided is the clearest  
> explanation I have seen to date of this.
> 
> To paraphrase, he says, within a location block, when you use “last”  
> the rewrites are stopped and a new subrequest is generated which will

Just a side note: “subrequest” is incorrect term here.

> take all all locations into account. When you use “break” the rewrites  
> are stopped and processing continued within the location you are in.
> 
> Adding Maxim’s statement above into account, outside a location block,  
> “break” behaves just like “last” does since there are no location  
> directives to run here.
> 
> Someone just needs to update the docs if this is correct.

Reading rewrite module docs carefully enough will tell basically  
the same:

…  
If the URI changed as a result of the execution of directives  
inside location, then location is again determined for the new  
URI. This cycle can be repeated up to 10 times, after which Nginx  
returns a 500 error.  
…

…  
Example:

```
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;

```

But if we place these directives in location /download/, then it  
is necessary to replace flag “last” by “break”, otherwise Nginx  
will hit the 10 cycle limit and return error 500:

```
location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
    return 403;
}

```

…

The translation though looks awful and needs re-translation;  
additionally, it was already polluted with user comments, and this  
doesn’t improve readability either.

Maxim D.

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 25, 2011, 2:12am UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/11 "2011-10-25T02:12:59Z")

</div>

On 23 Out 2011 16h26 WEST, removed\_email\_address@domain.invalid wrote:

Hello Maxim,

Can this be reasoned like this?

1. last means the _last_ rewrite, after which the location matching  
phase reoccurs, in search of a content handler.

2. break means that the rewrite phase is done and we proceed to the  
next phase. There must be a content handler (be a location) for  
this to be true.

3. Outside a location block there’s no content handler, hence using  
last or break is basically the same.

Thx,  
— appa

---

<div class="post-metadata">

**Author:** ![mindel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/bc8723/32.png) [@mindel](https://www.ruby-forum.com/u/mindel)\
**Post date:** [October 23, 2011, 5:32pm UTC](https://www.ruby-forum.com/t/nginx-rewrite-last-break/213012/12 "2011-10-23T17:32:49Z")

</div>

Hello!

On Sat, Oct 22, 2011 at 10:25:29AM -0400, locojohn wrote:

> > correct.
> 
> I have experienced situations when “rewrite something target last;” in  
> the server {} section generates the 503 page, while “rewrite something  
> target break;” instead works OK. It means that “break” does not behave  
> like “last” in the server section of the virtual host either.

The 500, likely. This might happen with nginx before 1.1.6 due to  
completely different reason: if there were no matching location  
found, the rewrite directives specified at server level were  
executed inside an implicit location again.

It is fixed in 1.1.6:

```
*) Bugfix: the ngx_http_rewrite_module directives specified at 

```

“server”  
level were executed twice if no matching locations were defined.

Simple and effective way to prevent such sort of problems is to  
always define “location /”.

Maxim D.
