Rewrite "break" directive - a strange behavior
Maxim Dounin
mdounin at mdounin.ru
Fri Apr 5 09:58:11 UTC 2013
Hello!
On Fri, Apr 05, 2013 at 05:38:22AM -0400, andrea.mandolo wrote:
> Hi,
>
> I'd like to report a strange behaviour of REWRITE "break" directives inside
> a "location" block, when it is used a SET directive subsequently.
>
> Now, i quote a little example, with a basic Nginx configuration that
> simulate the issue.
[...]
> server {
> listen 0.0.0.0:80;
> server_name _;
>
> set $cache_max_age "600";
> set $cache_crossdomain "2";
>
> location ~* "/crossdomain\.xml$" {
> rewrite ^/pippo/(.*) /$1 break;
> set $cache_max_age "$cache_crossdomain";
> proxy_pass http://media_server;
> }
>
> add_header Test-Cache-Control "max-age=$cache_max_age";
> }
> ############### END #########################
>
> I expect the response to a request ( performed via WGET for example ) to
> "http://localhost/pippo/crossdomain.xml"
> contains the HEADER "Test-Cache-Control: max-age=2"
This is wrong expectation. As "rewrite ... break" stops
processing of rewrite module directives, and "set" is the rewrite
module directive, the
set $cache_max_age "$cache_crossdomain";
is never executed due to break. The add_header configured
uses previously computed value of the $cache_max_age variable,
i.e. "600".
The confusion likely comes from the fact that rewrite module
directives are imperative, in contrast to other parts of the nginx
config, which is declarative.
Reading docs here (in particular, preface and internal
implementation sections) should be helpfull to understand how it
works:
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
> Instead, i get a wrong answer with HEADER "Test-Cache-Control:
> max-age=600",
> as if the variable "$cache_max_age" is not re-setted with the new value
> "2".
This is expected behviour.
If you want "set ..." to be executed, you have two basic options:
1) Don't use "rewrite ... break" but use "break" after rewrite
module directives, i.e.
rewrite ...
set ...
break;
proxy_pass ...
2) Just switch order of "rewrite" and "break" directives in your
config:
set ...
rewrite ... break;
proxy_pass ...
[...]
> I searched inside the official documentation:
> - REWRITE "break" descriptions say:
> -- http://wiki.nginx.org/HttpRewriteModule#rewrite
> --- "completes processing of current rewrite directives and non-rewrite
> processing continues within the current location block only."
> -- http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
> --- "stops processing the current set of ngx_http_rewrite_module
> directives."
>
> I haven't found anything that justifies this behaviour.
>
> Maybe, the set directive is considerated an "ngx_http_rewrite_module
> directive" ?
> or, is this a potential issue ?
The "set" directive _is_ rewrite module directive.
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#set
--
Maxim Dounin
http://nginx.org/en/donation.html
More information about the nginx
mailing list