I'm having issues with resizing and caching images. Here is my non-performant setup without caching:
- Client makes request for website.com/static/image.jpeg
- NGINX routes to API
- API authenticates user, generates S3 presigned URL, returns 302
- NGINX handles redirect, resizes image, returns image to user, ignorant of the presigned URL
I'm able to do both caching resizing, but the cache is queried before authentication. So if user 1 authenticates and unauthenticated user 2 asks for the same asset with the same dimensions, they receive it. Here's what that looks like (See Config 2, below):
- Client requests image
- Server 1 caches, proxy_passes to Server 2
- Server 2 proxy_passes to API
- API authenticates, generates presigned URL, returns 302
- Server 2 handles redirect, resizes, and returns to user
Here's what I want to do, but I feel like I'm struggling with syntax
- Client requests image
- Server 1 proxy_passes to API
- API authenticates, generates presigned URL, returns 302
- Server 1 handles redirect, will cache response after resizing (using client request as cache key), redirects/proxy_passes to server 2
- Server 2 resizes
How can I protect my assets properly and resize/cache assets?
Here is Config 2:
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=nginx_cache:100M max_size=1G inactive=40d;
server
{
listen 80;
server_name api.example.com;
server_tokens off;
location /.well-known/acme-challenge/
{
root /var/www/certbot;
}
location /
{
return 301 https://$host$request_uri;
}
}
server
{
listen 443 ssl;
server_name api.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /api
{
proxy_pass http://example-api:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/
{
proxy_pass http://127.0.0.1:10177/;
proxy_cache nginx_cache;
proxy_cache_key “$proxy_host$uri$is_args$args”;
proxy_cache_valid 1d;
expires 1d;
}
}
server
{
listen 10177;
server_name s3;
location /
{
proxy_connect_timeout 5m;
proxy_send_timeout 5m;
proxy_read_timeout 5m;
client_max_body_size 20M;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
proxy_redirect off;
proxy_pass http://example-api:8080/int/static/;
proxy_ssl_server_name on;
recursive_error_pages on;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirect;
}
## The API server granted the user access to the media
## Redirect to a presigned AWS S3 URL to the media
location @handle_redirect
{
resolver 8.8.8.8; # We need NGINX to be able to resolve the AWS url
set $saved_redirect_location '$upstream_http_location'; # Save the url location the API is redirecting to
set $saved_request_id '$upstream_http_x_request_id'; # Save the Request ID returned from the API server
## Override the connection timeouts
proxy_connect_timeout 5m;
proxy_send_timeout 5m;
proxy_read_timeout 5m;
## Override the request headers to AWS to what S3 is expecting
proxy_http_version 1.1;
proxy_set_header Connection "";
## Make sure we're sending the correct client information to the API server and not
## the NGINX server
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
## Override any authentication information so AWS can authenticate from the signed url
proxy_set_header Authorization '';
## Hide any headers that AWS returns from returning back to the client
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-meta-...;
proxy_hide_header x-amz-server-side-encryption;
## We don't want AWS to set any coookie information
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
## Make sure to unset/hide any authorization requests from AWS so the client does not get an annoying popup
proxy_hide_header WWW-Authorization;
proxy_hide_header Authorization;
## Make the request to AWS using the presigned URL
proxy_pass $saved_redirect_location;
## Intercept any errors that AWS returns
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirect; # Handle a redirect from AWS (i.e. bucket domain name)
set $width 1024;
if ($arg_w ~ /(\d+)/)
{
set $width $1;
}
image_filter resize $width -;
image_filter_jpeg_quality 75;
image_filter_buffer 8M;
}
}