Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'm using Nginx 0.7.64, Passenger 2.2.9, Rails 2.3.5. I have my page caching directory set to /public/cache, and I'd like to be able to serve cached pages when requested over HTTP, but always hit the Rails app when requested over HTTPS.

The bulk of my config looks like this:

server {
  listen 80;
  server_name website.com www.website.com;
  proxy_set_header X-Forwarded-Proto http;
  root /home/deploy/website/current/public;
  passenger_enabled on;

  if (-f $document_root/cache/$request_filename.html) { 
    rewrite (.*) $document_root/cache/$1.html break;
  }
}

server {
  listen       443;
  server_name website.com www.website.com;
  root /home/deploy/website/current/public;
  passenger_enabled on;
  proxy_set_header X-Forwarded-Proto https;

  ssl                  on;
  ssl_certificate      /home/deploy/website/shared/ssl/www.website.com.combined.crt;
  ssl_certificate_key  /home/deploy/website/shared/ssl/www.website.com.key;
}

I anticipate that when I request website.com/about, I should be served /public/cache/about.html, but instead I hit the Rails server (tailing the log shows it).

Thinking I might have an inappropriate slash (and not seeing $document_root in most examples), I've also tried all of the following variations, none of which work:

if (-f cache$request_filename.html) { 
  rewrite (.*) cache$1.html break;
}

if (-f /cache$request_filename.html) { 
  rewrite (.*) /cache$1.html break;
}

if (-f cache/$request_filename.html) { 
  rewrite (.*) cache/$1.html break;
}

if (-f /cache/$request_filename.html) { 
  rewrite (.*) /cache/$1.html break;
}

I've also thrown the root, passenger_enabled, and rewrite rules into a separate location / block, but that also does not work. I've also reordered the statements so that passenger_enabled would come at the end. I've also tried using $uri. Clearly I'm misunderstanding something!

This is a little bit simplified, since I also have an XML api that is cached in places (presumably the rewrite rule will be the same except for the .html parts), as well as I'll need to serve public/cache/index.html when the root of website.com is requested. I just want to get any single piece of it working. :)

Any help is appreciated!

Update

The conditional

if (-f $document_root/cache$request_uri.html)

Seems to work! However, what I would think would be the rewrite does not work! Trying

if (-f $document_root/cache$request_uri.html) {
  rewrite (.*) /cache$1.html break;
  break;
}

Rewrites the URL as /cache/cache/about.html.html and sends it to Rails, which promptly barfs. It looks doubled, yes! But if I rewrite to just /cache$1 it sends /cache/cache/about to Rails, and $1.html sends /about.html.html to Rails, and just $1 sends simply /about which goes to Rails and does not hit the cache. Obviously this is not correct behavior Is Nginx rewriting it and then Passenger is rewriting it, too?

share|improve this question
    
here is manual nginx.org/en/docs/http/converting_rewrite_rules.html for converting apache rewrites –  SaveTheRbtz Jan 28 '10 at 15:03
add comment

2 Answers

up vote 1 down vote accepted

The answer was found here: http://stackoverflow.com/questions/1177979/nginx-rewrite-rules-with-passenger

The config ended up being:

# root
if (-f $document_root/cache/$uri/index.html) {
  rewrite (.*) /cache/$1/index.html break;
}

# pages like /about, cached with .html but accessed without
if (-f $document_root/cache/$uri.html) {
  rewrite (.*) /cache/$1.html break;
}

# pages like /api/v1/something.xml, cached as xml
if (-f $document_root/cache/$uri) {
  rewrite (.*) /cache/$1 break;
}
share|improve this answer
    
there is try_files directive for that –  SaveTheRbtz Jan 25 '10 at 10:23
    
@SaveTheRbtz would you mind show the try_files way (and edit the answer) please? –  lulalala Jul 3 '12 at 9:39
add comment

try_files version:

server {
  listen 80;
  server_name website.com www.website.com;
  location / {
    root /home/deploy/website/current/public;
    try_files $uri /cache/$uri/index.html /cache/$uri.html /cache/$uri @passenger;
  }
  location @passenger {
    root /home/deploy/website/current/public;
    proxy_set_header X-Forwarded-Proto http;
    passenger_enabled on;
  }
}

note that it might or might not work with passenger. I'm sure it works with unicorn, mongrel, etc though.

share|improve this answer
    
This does not appear to work with Passenger as of 2.2.9. Cached files are served appropriately, but uncached requests do not hit the Rails app. –  Ian Terrell Jan 28 '10 at 15:34
    
(In a separate, much less important comment, static files like CSS and JS are accesses directly from $uri, so that needs added to the list.) –  Ian Terrell Jan 28 '10 at 15:34
    
oh right, add it as the first. The main problem is there's no way to fallback to passenger. When using unicorn and co, the content of @passenger is the proxy_pass to backend. –  edogawaconan Jan 29 '10 at 12:06
    
or try adding root to location @passenger block. location @passenger { root /home/deploy/website/current/public; proxy_set_header X-Forwarded-Proto http; passenger_enabled on; } –  edogawaconan Jan 30 '10 at 2:09
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.