The application I'm working on (CMS) has a few interesting requirements:
* Custom user domains
* Very heavily page cached.
* Any page can be POSTed to (page has a form on it)
In Apache, this was easily handled. If GET, then look in the cache, then
fall to Passenger. Otherwise, just go straight to Passenger.
I have been unable to get nginx working for my needs and am wondering if
anyone else has any insight into how to solve this problem.
Basically what I want is the following (but can't because try_files
can't be in an if):
location / {
if ($request_method ~* ^(GET|HEAD)$) {
try_files /cache/$domain/$uri
/cache/$domain/$uri.html
/cache/$domain/$uri/index.html
/maintenance.html
@passenger;
break;
}
try_files /maintenance.html @passenger;
}
location @passenger {
passenger_enabled on;
}
I initially had the idea that try_files was more of a switch-statement,
and tried to do something like:
try_files @cache maintenance.html @passenger;
then in @cache simply break if the request is not a GET, but that
obviously only ever went to @passenger, because @cache wasn't a real
file on the system.
I've tried the error_page 405 = @passenger route, but that has a very
severe problem in that it turns my POST request into a GET, and I was
unable to find out how to stop that. Is there a way?
I've also tried doing an internal redirect to a different location
block, something like:
location /post {
internal;
passenger_enabled on;
}
but then I end up with $uris that have /post/(uri i want) and don't know
how to tell nginx to ignore /post when sending down to passenger. Would
also appreciate ideas here if there are any.
Any other suggestions? I'm almost to resorting to a number of if
statements and really don't want to end up there.
I am using nginx release: 1.2.6 on ubuntu 12.04 and Passenger
Enterprise.
Thanks
Jason
on 2013-01-09 00:13
on 2013-01-09 02:32
On 8 January 2013 23:13, Jason R. <lists@ruby-forum.com> wrote: > if ($request_method ~* ^(GET|HEAD)$) { > > location @passenger { > passenger_enabled on; > } Does try_files accept a variable generated from a map based on the $request_method variable, perhaps? That's the way I usually avoid ifs. Jonathan -- Jonathan Matthews // Oxford, London, UK http://www.jpluscplusm.com/contact.html
on 2013-01-09 09:41
On 9 Jan 2013 00h13 CET, lists@ruby-forum.com wrote: > I have been unable to get nginx working for my needs and am > /cache/$domain/$uri/index.html > } You're mixing different things. break is a rewrite phase directive, like if. So they're executed well before try_files and the content phase handlers. You should use the map directive. At the http level: map $request_method $idempotent { default 0; GET 1; HEAD 1; } then at the server level (vhost config): location / { error_page 418 = @idempotent; if ($idempotent) { return 418; } try_files /cache/$domain/$uri /cache/$domain/$uri.html /cache/$domain/$uri/index.html /maintenance.html @passenger; } location @idempotent { try_files /maintenance.html @passenger; } location @passenger { passenger_enabled on; } Try it. --- appa
on 2013-01-09 15:22
"António P. P. Almeida" <appa@perusio.net> wrote in post #1091574: > On 9 Jan 2013 00h13 CET, lists@ruby-forum.com wrote: > > error_page 418 = @idempotent; > > if ($idempotent) { > return 418; > } > > location @idempotent { > try_files /maintenance.html @passenger; > } I never knew about the map directive, that's quite interesting. One question though, will this make sure that a POST that hits the error_page 418 stays a POST when it goes through the @idempotent location? Thanks for the info! Jason
on 2013-01-09 16:47
On 9 Jan 2013 15h22 CET, lists@ruby-forum.com wrote: >> try_files /maintenance.html @passenger; >> } > > I never knew about the map directive, that's quite interesting. One > question though, will this make sure that a POST that hits the > error_page 418 stays a POST when it goes through the @idempotent > location? Perhaps I misunderstood. The way it is configured above is such that the @idempotent location will only be used for GET and HEAD requests. All other requests are handled by the / location using the lenghty try_files. I thought that was your desired config. > Thanks for the info! You're welcome. --- appa
on 2013-01-09 20:39
"António P. P. Almeida" <appa@perusio.net> wrote in post #1091605: > On 9 Jan 2013 15h22 CET, lists@ruby-forum.com wrote: > >>> try_files /maintenance.html @passenger; >>> } >> >> I never knew about the map directive, that's quite interesting. One >> question though, will this make sure that a POST that hits the >> error_page 418 stays a POST when it goes through the @idempotent >> location? > > Perhaps I misunderstood. The way it is configured above is such that > the @idempotent location will only be used for GET and HEAD requests. > All other requests are handled by the / location using the lenghty > try_files. > > I thought that was your desired config. > >> Thanks for the info! > > You're welcome. > > --- appa Sorry if I mispoke then, what I want is the exact opposte because POST should never hit a cache file. We ended up going a slightly different route in that we hack the cache file location according to the request type (we have $cache_host because there's some other processing we do, not relevant here): # Set cache_path to a non-existant directory so try_files fails if we cannot # serve the request from the cache. set $cache_path "no-cache"; set $cache_host $host; if ($request_method ~* ^(GET|HEAD)$) { set $cache_path "cache"; } try_files /$cache_path/$cache_host/$uri /$cache_path/$cache_host/$uri.html /$cache_path/$cache_host/$uri/index.html /maintenance.html @passenger; This way there's no possible way a valid file is found when POST-ing. This was the simplest solution we could come up with at this time. Thanks for everyone's help. Jason
on 2013-01-10 14:05
On 9 Jan 2013 20h39 CET, lists@ruby-forum.com wrote: > cannot > /$cache_path/$cache_host/$uri.html > /$cache_path/$cache_host/$uri/index.html > /maintenance.html > @passenger; > > This way there's no possible way a valid file is found when > POST-ing. This was the simplest solution we could come up with at > this time. > > Thanks for everyone's help. It's even simpler then. No need for map. location / { error_page 418 = @post; if ($request_method = POST) { return 418; } try_files /cache/$domain/$uri /cache/$domain/$uri.html /cache/$domain/$uri/index.html /maintenance.html @passenger; } location @post { try_files /maintenance.html @passenger; } location @passenger { passenger_enabled on; } --- appa
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.