Hello, I am new to nginx, and am still learning my way. I use nginx to serve static html pages to users, and in particular, I want users who visit 'www.example.com/public/doc/abc123?para=data' to be served with the file '/home/www/example/public/doc/abc123/abc123.html' on the server, but 'www.example.com/public/doc/abc123?para=data' stays in the user's browser address bar. So there are two issues here: 1. map URI pattern '/public/doc/blah' to file '/home/www/example/public/doc/blah/blah.html' on the server; 2. keep query string '?parap=data' in the address bar. I wonder if these can be solved by using `try_files` within a location block. For example, substring the $uri to take out '/blah' part, and append it to the $uri followed by '.html'. And possibly append $args after '.html'? How exactly do we do this in nginx? Thanks! Posted at Nginx Forum: http://forum.nginx.org/read.php?2,231672,231672#msg-231672
on 2012-10-11 15:19
on 2012-10-11 18:58
On Thu, Oct 11, 2012 at 09:19:23AM -0400, mrtn wrote: Hi there, > I use nginx to serve static html pages to users, and in particular, I want > users who visit 'www.example.com/public/doc/abc123?para=data' to be served > with the file '/home/www/example/public/doc/abc123/abc123.html' on the > server, but 'www.example.com/public/doc/abc123?para=data' stays in the > user's browser address bar. For this sort of thing, "rewrite" (http://nginx.org/r/rewrite) is probably the directive you want. rewrite (.*)/(.*) $1/$2/$2.html break; can do what you want in this case. What do you want to happen if the user asks for any of: http://www.example.com/public/doc/abc123 http://www.example.com/public/doc/abc123?para=nodata http://www.example.com/public/doc/abc123/abc123.html http://www.example.com/public/doc/one/two The rewrite directive above may or may not do what you want for those. > So there are two issues here: 1. map URI pattern '/public/doc/blah' to file > '/home/www/example/public/doc/blah/blah.html' on the server; 2. keep query > string '?parap=data' in the address bar. 1) is in the rewrite (or any similar configuration which maps url to file) 2) is by virtue of not doing an external rewrite, which is a redirection. f -- Francis Daly francis@daoine.org
on 2012-10-11 22:00
Hi Francis,
Thanks for introducing me to rewrite directive. Just to confirm, this is
how
I should use your rewrite:
root /home/www/example;
location /public/doc/ {
rewrite (.*)/(.*) $1/$2/$2.html break;
}
Ideally, for the other cases you raised, I want the following to happen:
>http://www.example.com/public/doc/abc123
>http://www.example.com/public/doc/abc123?para=nodata
when the query string (e.g. ?para=blah) part is missing or incomplete, I
want to serve a generic error page (e.g. /error.html)
>http://www.example.com/public/doc/abc123/abc123.html
when the user tries to access the actual html page directly, I want to
block
it by either returning a 404 or serving a generic error page as above
>http://www.example.com/public/doc/one/two
when the user queries an URI that has no corresponding .html file on the
server, I want to simply return a 404.
Can all these be implemented using rewrite only? Thanks.
Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,231672,231682#msg-231682
on 2012-10-11 22:32
On Thu, Oct 11, 2012 at 03:59:24PM -0400, mrtn wrote: Hi there, > Thanks for introducing me to rewrite directive. Just to confirm, this is how > I should use your rewrite: > > root /home/www/example; > > location /public/doc/ { > rewrite (.*)/(.*) $1/$2/$2.html break; > } It can work outside of all locations, or else in the one location that handles this request. So this config can work. > Ideally, for the other cases you raised, I want the following to happen: > > >http://www.example.com/public/doc/abc123 > >http://www.example.com/public/doc/abc123?para=nodata > > when the query string (e.g. ?para=blah) part is missing or incomplete, I > want to serve a generic error page (e.g. /error.html) The above rewrite pays no attention to query strings. So you'll want to do something based on $arg_para -- maybe an "if" or something involving "map". I guess (without testing): if ($arg_para != data) { return 404; } inside that location{} would probably work. > >http://www.example.com/public/doc/abc123/abc123.html > > when the user tries to access the actual html page directly, I want to block > it by either returning a 404 or serving a generic error page as above The above rewrite does that (assuming that the "rewritten" file is absent). > >http://www.example.com/public/doc/one/two > > when the user queries an URI that has no corresponding .html file on the > server, I want to simply return a 404. The above rewrite does that; but which html file should it look for here? /home/www/example/public/doc/one/two/two.html, or /home/www/example/public/doc/one/two/one/two.html? (As in: do you repeat everything after /public/doc, or do you repeat just the final after-slash part?) > Can all these be implemented using rewrite only? Thanks. With the extra "if" above, I think so. Your testing should be able to show any problems, or unexpected behaviour. f -- Francis Daly francis@daoine.org
on 2012-10-11 23:23
Hi Francis, >I guess (without testing): > >if ($arg_para != data) { return 404; } > >inside that location{} would probably work Hmm, I read on nginx website and elsewhere that if statement may not work consistently within a location directive, and is generally discouraged. Should I worry in this case? >The above rewrite does that; but which html file should it look for here? > >/home/www/example/public/doc/one/two/two.html, or >/home/www/example/public/doc/one/two/one/two.html? > >(As in: do you repeat everything after /public/doc, or do you repeat >just the final after-slash part?) I only want to repeat the final after-slash part, so any '/public/doc/blahA/blahB' should only look for '/public/doc/blahA/blahB/blahB.html'. Would that change anything in the config proposed here? Thanks again! Mrtn Posted at Nginx Forum: http://forum.nginx.org/read.php?2,231672,231685#msg-231685
on 2012-10-12 00:13
On Thu, Oct 11, 2012 at 05:22:54PM -0400, mrtn wrote: Hi there, > >I guess (without testing): > > > >if ($arg_para != data) { return 404; } > > > >inside that location{} would probably work > > Hmm, I read on nginx website and elsewhere that if statement may not work > consistently within a location directive, and is generally discouraged. > Should I worry in this case? What precisely did you read? And does it apply here? (I think I know the answers to those; but there's no reason for you to believe my words instead of words written elsewhere. If the words are all consistent, then you can choose to believe them all. If the words are contradictory, then you must choose which source to consider incorrect.) > >(As in: do you repeat everything after /public/doc, or do you repeat > >just the final after-slash part?) > > I only want to repeat the final after-slash part, so any > '/public/doc/blahA/blahB' should only look for > '/public/doc/blahA/blahB/blahB.html'. Would that change anything in the > config proposed here? What happened when you tried it? mkdir -p /home/www/example/public/doc/blahA/blahB/blahA echo This is in blahB > /home/www/example/public/doc/blahA/blahB/blahB.html echo This is in blahA > /home/www/example/public/doc/blahA/blahB/blahA/blahB.html curl -i http://www.example.com/public/doc/blahA/blahB As it happens, the rewrite suggested should end up fetching the "in blahB" file, because it only repeats the part after the last slash. When you understand *why* it does that, you'll have a better chance of writing your own regex-based rewrites. Good luck with it! f -- Francis Daly francis@daoine.org
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.