Reverse Proxy a request to Azure blob storage URL's with Nginx

Reverse Proxy a request to Azure blob storage URL's with Nginx

Nowadays, everyone is trying to adopt cloud technologies. Currently, there are a few famous cloud service providers in the market such as AWS, Microsoft Azure, GCP, etc. Web developers often use cloud storage to dump static data, such as images, videos, document files, etc.

But the challenge is we don't want our customers to know that the assets are being served from the other server or we generally avoid redirecting. To solve this we will use a very known concept in the world of servers, reverse proxy.

If you want to know what is the difference between proxy(or forwarded proxy) and reverse proxy, then refer to this article.

The prerequisite of this article is:

  • You have setup Nginx on your server

  • You have the blob URL ready with you.

In this article, my site name is jrdeveloper.online and my blob storage URL is /{your_blob}/{buket_name}/content/assets/do_2136825431517347841122/test.mp4

Now what I trying to achieve here is whenever I hit jrdeveloper.online/web-assets/{path_to_asset} it should proxy this request to the actual blob storage URL and return the requested asset, while I'm on the same URL in the browser.

The /etc/nginx/sites-available/jrdeveloper.online will look like below:

Now, this will handle all the URLs. But when users ask specifically for jrdeveloper.online/web-assets/{path_to_asset} in that case, we need to proxy this request to the /{your_blob}/{subfolder}/{path_to_asset}`

For example:

jrdeveloperdevpublic.blob.core.windows.net/web-assets/content/do_12121/marathon.mp4

Let's define a new variable $bucket and keep the bucket name like below

set $bucket "jrdeveloperdevpublic.blob.core.windows.net";

Then let's add a new location for web-assets. We will look for web-assets in the request URL, if it gets matched, the following block of code will be executed:

location /web-assets  {
      resolver             8.8.8.8;
      proxy_http_version   1.1;
      proxy_redirect       off;
      proxy_set_header     Connection "";
      proxy_set_header     Authorization '';
      proxy_set_header     Host $bucket;
      proxy_set_header     X-Real-IP $remote_addr;
      proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_hide_header    Set-Cookie;
      proxy_ignore_headers Set-Cookie;
      add_header           Cache-Control max-age=31536000;
      proxy_pass           http://$bucket;
    }

This will internally redirect all the requests to blob storage.

Sometimes, we may have different URLs in applications than blob storage URLs. In that case, we need to modify the incoming request to a specific format so that it can satisfy the path on blob storage.

Let's take an example. As of now, the subfolder name web-assets was the same in both the requested URL and the actual blob storage URL. Now let's say, the application has changed the path to jrdeveloper.online/storage/{path_to_asset} . In this case, we need to serve requests from the same blob storage.

To solve this we need to alter the requested URL before proxying the request as below:

There are multiple ways to do it, 2 approaches are given below:

  1. Using condition proxy:
location ~* "/storage/(.*)"  {
      resolver             8.8.8.8;
      proxy_http_version   1.1;
      proxy_redirect       off;
      proxy_set_header     Connection "";
      proxy_set_header     Authorization '';
      proxy_set_header     Host $bucket;
      proxy_set_header     X-Real-IP $remote_addr;
      proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_hide_header    Set-Cookie;
      proxy_ignore_headers Set-Cookie;
      add_header           Cache-Control max-age=31536000;
      proxy_pass    http://$bucket/web-assets/$1;            
}

# same can be written as below
# location /storage {
# Add header here...
#    if ($request_uri ~* "/storage/(.*)") {
#        proxy_pass https://$bucket/web-assets/$1 
#    }
# }
  1. Using rewrite directive:
rewrite ^/storage/(\w+) /web-assets/$1
location /web-assets  {
      resolver             8.8.8.8;
      proxy_http_version   1.1;
      proxy_redirect       off;
      proxy_set_header     Connection "";
      proxy_set_header     Authorization '';
      proxy_set_header     Host $bucket;
      proxy_set_header     X-Real-IP $remote_addr;
      proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_hide_header    Set-Cookie;
      proxy_ignore_headers Set-Cookie;
      add_header           Cache-Control max-age=31536000;
      proxy_pass           https://$bucket;
}

Once updated the conf file don't forget to check if everything is fine on nginx with nginx -t

And then reload the server with service nginx reload

Did you find this article valuable?

Support Vivek Kasture by becoming a sponsor. Any amount is appreciated!