user1945821
user1945821

Reputation: 161

nginx rewrite - proxy if file not exists

I have a local directory (uploads) and an S3 bucket setup. when the user is uploading an image the file is stored on the local directory: /uploads/member_id/image_name and after 30 minutes the system is uploading the files to S3 with the same path: s3.amazonaws.com/bucket/member_id/image_name;

I have setup this rewrite rule on my nginx server but it's not working. this rule should check if the file is exists locally, and if not, open a proxy to S3..

Any idea how to fix it?

location /uploads/
{
    rewrite  ^/uploads/(.*)/([A-Za-z0-9\._]*)$ /uploads/$1/$2?imgname=$2&member=$1;
    try_files $uri @fallback;
}

location @fallback
{
    resolver 8.8.8.8;
    proxy_pass $scheme://s3.amazonaws.com/bucket/$arg_member/$arg_imgname;
    proxy_set_header Host s3.amazonaws.com;
}

Upvotes: 5

Views: 6919

Answers (1)

davidjb
davidjb

Reputation: 8727

You should adjust your location block to use a combination of a rewrite and a proxy_pass directive, such that each request is rewritten dynamically. As your configuration stands, the variables don't appear to be resolved on a per-request basis - according to Nginx's documentation, only the server name, port, and URI can be specified by variables.

What you need is something akin to this, rewriting the URI and definitively specifying a proxy:

location @fallback 
{
    resolver 8.8.8.8;
    rewrite ^.*$ /bucket/$arg_member/$arg_imgname break;
    proxy_pass http://s3.amazonaws.com;
    proxy_set_header Host s3.amazonaws.com;
}

and to satisfy your switchable scheme (HTTP and HTTPS), the best option is likely to have two separate server blocks, with two different @fallback locations - one for HTTP and the other for HTTPS. The proxy_pass location cannot resolve $scheme in this context. Details are somewhat sketchy on what is supported (and why), but Nginx's documentation is all we have to go on.

Upvotes: 3

Related Questions