Server level url rewrite & config rewrite or internal redirection cycle

Hi,

I am using “nginx version: nginx/0.7.64”, the latest stable version.
I notice that rewrite on the server level won’t respect the ‘break’ or
‘last’ flag. Is this a feature or a bug? According to the module doc, it
should be a bug.

server {
listen 80;
server_name hellogrow.corp.yahoo.com;
root /home/test;

error_log   logs/host.error.log notice;
rewrite_log on;

rewrite ^/favicon.ico(?.|)$
/frontend/template/default/img/favicon.ico break;
rewrite ^/img/(.
.(jpg|png|gif))$ /frontend/template/default/img/$1
break;
rewrite ^/js/(..js)$ /frontend/template/default/js/$1 break;
rewrite ^/b_js/(.
.js)$ /bframe/frontend/cache/js_cache/$1 break;
rewrite ^/css/(..css)$ /frontend/template/default/css/$1 break;
rewrite ^/html/(.
)$ /frontend/html/$1 break;
}

rewrite_log:

2009/12/05 17:15:08 1352#0: 1 "^/favicon.ico(?.|)$" does not match
“/img/fdsf.gif”, client: 10.80.20.11, server: hellogrow.corp.yahoo.com,
request: “GET /img/fdsf.gif?fdskaf=dkfksk HTTP/1.1”, host:
hellogrow.corp.yahoo.com
2009/12/05 17:15:08 1352#0: 1 "^/img/(..(jpg|png|gif))$" matches
“/img/fdsf.gif”, client: 10.80.20.11, server: hellogrow.corp.yahoo.com,
request: “GET /img/fdsf.gif?fdskaf=dkfksk HTTP/1.1”, host:
hellogrow.corp.yahoo.com
2009/12/05 17:15:08 1352#0: *1 rewritten data:
“/frontend/template/default/img/fdsf.gif”, args: “fdskaf=dkfksk”,
client: 10.80.20.11, server: hellogrow.corp.yahoo.com, request: “GET
/img/fdsf.gif?fdskaf=dkfksk HTTP/1.1”, host: “hellogrow.corp.yahoo.com
2009/12/05 17:15:08 1352#0: 1 "^/favicon.ico(?.|)$" does not match
“/frontend/template/default/img/fdsf.gif”, client: 10.80.20.11, server:
hellogrow.corp.yahoo.com, request: “GET /img/fdsf.gif?fdskaf=dkfksk
HTTP/1.1”, host: “hellogrow.corp.yahoo.com

Another question is that if there’s a hidden config directive that
controls the cycle numbers of internal redirection or rewrite since this
cycle can be used to mimic the ‘next|N’ flag in Apache rewrite module.

Thanks,
-ET

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,28189,28189#msg-28189

Hi Igor and fellows,

Sorry, but can you please take a look at this?

Thanks,
-ET

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,28189,28345#msg-28345

Hi Igor,

Thanks a lot for the reply.

Below are what I want:

  1. some static files can be directly accessed. but also, access static
    files with a fake query string is also allowed since this is useful to
    walk around browser cache for debug purpose
    e.g. /favor.ico or /favor.ico?xxx=yyy => /new_path/favor.ico

  2. all other request will be passed to a single PHP file ‘common.php’,
    but search engine friendly url needs to be parsed into files + query
    strings.
    e.g. /module/func/param1-value1-param2-value2… =>
    /common.php?mod=module&func=func&param1=value1&param2=value2…

  3. common.php will be handled by upstream PHP fastcgi env.

  4. prevent any direct access to /common …

Usually, 2 is done by many web frameworks on the application level, but
I want to make it into the web server to see if there’s a tiny
performance gain. I’ve already done above for Apache and Lighttpd. Both
work well.

Since Nginx ignores rewrite flag ‘break’ or ‘last’ on the server level
and no ‘N|Next’ flag like Apache, rewrite rules to achieve above took me
some time. My solution is as below. Any suggestions to make it better?

As I’ve asked, is there a hidden config directive to control the number
of internal rewrite cycles? The current value 10 restricts the number of
params to only 7, namely
/module/func/param1-value1-param2-value2-p3-v3-p4-v4-p5-v5-p6-v6-p7-v7
(no more p-v pairs on the tail).

server {

root /var/html/webroot;

location / {
    rewrite ^/favicon.ico$ 

/frontend/template/default/img/favicon.ico break;
rewrite ^/img/(..(jpg|png|gif))$
/frontend/template/default/img/$1 break;
rewrite ^/js/(.
.js)$ /frontend/template/default/js/$1 break;
rewrite ^/b_js/(..js)$ /bframe/frontend/cache/js_cache/$1
break;
rewrite ^/css/(.
.css)$ /frontend/template/default/css/$1
break;
rewrite ^/html/(.)$ /frontend/html/$1 break;
rewrite ^(.
)$ :///:$1;
}
location :///: {
rewrite ^:///:/common(|[.-/]+.)$ :///////:/?mod=404 last;
rewrite ^:///:/([^.-/=&]+)[-/]
(.) :///:$2?mod=$1;
rewrite ^:///:([^.-/=&]+)[-/]
(.) :///:$2?func=$1;
rewrite ^:///:(.
)$ ://///:$1;
}

location ://///: {
    rewrite ^://///:([^.\-/=&]+)[\-/]([^.\-/=?&]+)[\-/]*(.*) 

://///:$3?$1=$2 last;
rewrite ^://///:(.*)$ :///////:$1;
}

location :///////: {
    rewrite .* /path/to/common.php break;
    include /home/y/conf/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
}

}

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,28189,28380#msg-28380

On Sun, Dec 06, 2009 at 12:03:40PM +0300, Igor S. wrote:

location ~ ^/js/(.*\.js)$ {

location  /html/ {
    root  /frontend/;
}

without these ugly rewrites.

Probably, you need to prepend /home/test in all directives.
Also probably, you do not need regexes at all:

 location = /favicon.ico {
     root  /home/test/frontend/template/default/img;
 }

 location  /img/ {
     root  /home/test/frontend/template/default;
 }

 location  /js/ {
     root  /home/test/frontend/template/default;
 }

 location  /b_js/ {
     alias /home/test/bframe/frontend/cache/js_cache/;
 }

 location  /css/ {
     root  /home/test/frontend/template/default;
 }

 location  /html/ {
     root  /home/test/frontend/;
 }


Igor S.
http://sysoev.ru/en/

On Sat, Dec 05, 2009 at 04:33:15AM -0500, et wrote:

rewrite_log on;

rewrite ^/favicon.ico(?.|)$ /frontend/template/default/img/favicon.ico break;
rewrite ^/img/(.
.(jpg|png|gif))$ /frontend/template/default/img/$1 break;
rewrite ^/js/(..js)$ /frontend/template/default/js/$1 break;
rewrite ^/b_js/(.
.js)$ /bframe/frontend/cache/js_cache/$1 break;
rewrite ^/css/(..css)$ /frontend/template/default/css/$1 break;
rewrite ^/html/(.
)$ /frontend/html/$1 break;
}

What do you want to get ? Probably you need just:

location = /favicon.ico {
    root  /frontend/template/default/img;
}

location ~ ^/img/(.*\.(jpg|png|gif))$ {
    root  /frontend/template/default;
}

location ~ ^/js/(.*\.js)$ {
    root  /frontend/template/default;
}

location ~ ^/b_js/(.*\.js)$ {
    alias  /bframe/frontend/cache/js_cache/$1;
}

location ~ ^/css/(.*\.css)$ {
    root  /frontend/template/default;
}

location  /html/ {
    root  /frontend/;
}

without these ugly rewrites.


Igor S.
http://sysoev.ru/en/

Thanks Igor.

You can say it’s over-engineering. But make the cycle number controlled
by the user should be reasonable and a trivial work.

I also suggest to mention in the doc of rewrite module that the
‘break’/‘last’ flag not supported on the server level config.

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,28189,28470#msg-28470

On Sun, Dec 06, 2009 at 10:58:38AM -0500, et wrote:

Hi Igor,

Thanks a lot for the reply.

Below are what I want:

  1. some static files can be directly accessed. but also, access static files with a fake query string is also allowed since this is useful to walk around browser cache for debug purpose
    e.g. /favor.ico or /favor.ico?xxx=yyy => /new_path/favor.ico

nginx does not a query string in location, since anyone may request
anything in the query string, so

location = /favor.ico {
root /new_path;
}

will work for any query string.

  1. all other request will be passed to a single PHP file ‘common.php’, but search engine friendly url needs to be parsed into files + query strings.
    e.g. /module/func/param1-value1-param2-value2… => /common.php?mod=module&func=func&param1=value1&param2=value2…

  2. common.php will be handled by upstream PHP fastcgi env.

  3. prevent any direct access to /common …

Usually, 2 is done by many web frameworks on the application level, but I want to make it into the web server to see if there’s a tiny performance gain. I’ve already done above for Apache and Lighttpd. Both work well.

The configuration below looks to me as overengineered thing.
I never understand why PHP developers can not parse an original request
to get arguments. I believe, you will no see any performance gain,
at least in nginx and Apache case.

Since Nginx ignores rewrite flag ‘break’ or ‘last’ on the server level and no ‘N|Next’ flag like Apache, rewrite rules to achieve above took me some time. My solution is as below. Any suggestions to make it better?

On the application level.

As I’ve asked, is there a hidden config directive to control the number of internal rewrite cycles? The current value 10 restricts the number of params to only 7, namely /module/func/param1-value1-param2-value2-p3-v3-p4-v4-p5-v5-p6-v6-p7-v7 (no more p-v pairs on the tail).

10 is hardcodeded limit.

    rewrite ^/js/(.*\.js)$ /frontend/template/default/js/$1 break;
}
}

}


Igor S.
http://sysoev.ru/en/

On Sun, Dec 06, 2009 at 10:58:49PM -0500, et wrote:

Thanks Igor.

You can say it’s over-engineering. But make the cycle number controlled by the user should be reasonable and a trivial work.

I also suggest to mention in the doc of rewrite module that the ‘break’/‘last’ flag not supported on the server level config.

Yes, rewrite module was not well-though-out from the very start, since
I never considered it as a normal configuration method. Why not to
configure
in clean and nice way:

 location / {
     fastcgi_pass  127.0.0.1:9000;
     fastcgi_param SCRIPT_FILENAME  /home/test/common.php;
     include       fastcgi_params;
 }

 location = /common.php {
     retrun 404;
 }

 location = /favicon.ico {
     root  /home/test/frontend/template/default/img;
 }

 location  /img/ {
     root  /home/test/frontend/template/default;
 }

 location  /js/ {
     root  /home/test/frontend/template/default;
 }

 location  /b_js/ {
     alias /home/test/bframe/frontend/cache/js_cache/;
 }

 location  /css/ {
     root  /home/test/frontend/template/default;
 }

 location  /html/ {
     root  /home/test/frontend/;
 }


Igor S.
http://sysoev.ru/en/

Thank you Igor. I see your point.

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,28189,28736#msg-28736