Score:0

Image resizing and caching in NGINX after authentication and 302 redirect

lr flag

I'm having issues with resizing and caching images. Here is my non-performant setup without caching:

  1. Client makes request for website.com/static/image.jpeg
  2. NGINX routes to API
  3. API authenticates user, generates S3 presigned URL, returns 302
  4. 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):

  1. Client requests image
  2. Server 1 caches, proxy_passes to Server 2
  3. Server 2 proxy_passes to API
  4. API authenticates, generates presigned URL, returns 302
  5. 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

  1. Client requests image
  2. Server 1 proxy_passes to API
  3. API authenticates, generates presigned URL, returns 302
  4. Server 1 handles redirect, will cache response after resizing (using client request as cache key), redirects/proxy_passes to server 2
  5. 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;

  }


}
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.