views:

510

answers:

2

So I'm moving my site away from Apache and onto Nginx, and I'm having trouble with this scenario:

User uploads a photo. This photo is resized, and then copied to S3. If there's suitable room on disk (or the file cannot be transferred to S3), a local version is kept.

I want requests for these images (such as http://www.mysite.com/p/1_1.jpg) to first look in the p/ directory. If no local file exists, I want to proxy the request out to S3 and render the image (but not redirect).

In Apache, I did this like so:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^p/([0-9]+_[0-9]+\.jpg)$ http://my_bucket.s3.amazonaws.com/$1 [P,L]

My attempt to replicate this behavior in Nginx is this:

location /p/ {
if (-e $request_filename) {
break;
}
proxy_pass http://my_bucket.s3.amazonaws.com/;
}

What happens is that every request attempts to hit Amazon S3, even if the file exists on disk (and if it doesn't exist on Amazon, I get errors.) If I remove the proxy_pass line, then requests for files on disk DO work.

Any ideas on how to fix this?

A: 

break isn't doing quite what you expect nginx will do the last thing you ask of it, which makes sense if you start digging around making modules... but basically protect your proxy_pass with the does-not-exist version

if (-f $request_filename) {
    break;
}
if(!-f $request_filename)
    proxy_pass  http://s3;
}
ozone
I tried that initially, but Nginx won't start if I have the full `http://my_bucket.s3.amazonaws.com/` in the `proxy_pass` call. I get the following error:`Restarting nginx: 2010/01/11 20:53:36 [emerg] 1485#0: "proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in /etc/nginx/sites-enabled/my_site.com:39`If I remove the trailing slash, Nginx will start, but my requests do not get routed correctly any more. Any ideas?
Coomer
A: 

I ended up solving this by checking to see if the file doesn't exist, and if so, rewriting that request. I then handle the re-written request and do the proxy_pass there, like so:

location /p/ {
  if (!-f $request_filename) {
    rewrite ^/p/(.*)$ /ps3/$1 last;
    break;
  }
}

location /ps3/ {
  proxy_pass http://my_bucket.s3.amazonaws.com/;
}
Coomer