nginx decode base64 url for use with imgproxy

 i've been testing imgproxy, to handle our image serving needs, and it looks good.

our existing servers are php based, and we sign and encode our urls for images.  To test out imgproxy , I wanted to simply drop it in as a replacement for our servers by sending a % of traffic. 

There are many ways to do this, varnish was one, with custom code, but nginx is our go-to web server, so I had to find a way to have nginx sit in front of imgproxy and rewrite the decoded url.

I settled on using njs, the cut down version of javascript that plugs into nginx as a loadable module.  Then use proxy_pass to pass the uri to javascript that will return the imgproxy compatable url, and proxy to it.

a sample url would be

http://foo.bar/images/c2lnbmF0dXJlZm9vaHR0cDovL3MzLWV1LXdlc3QtMS5hbWF6b25hd3MuY29tL215YnVja2V0b2ZwaG90b3MvcGhvdG9fb2ZfYV9jYXQ1fHx8MTIwMHgxMjAwfHx8fHx8fHw==.jpeg

it has a sig, a bucket url, and parameters like image size.

Getting nginx setup

nginx.conf

load_module modules/ngx_http_js_module.so;
in /etc/nginx/sites-enabled/default

js_include "imgproxyurl.js";
js_set $imgproxyurl imgproxyurl;

server {
   location ~ /images/(.*) {
     aio threads;
     proxy_buffering off;
     proxy_pass $imgproxyurl;
   }


the javascript file


  function imgproxyurl(r) {
        var splitUrl = r.uri.split('\/');
        var filePart = splitUrl[2];
        var decodedUrl =  Buffer.from(filePart, 'base64url'); // don't make a string, it can have binary data , base64url takes care of + /
        
        // skip anything up to position 48, which is the bucket part of the url
        var justParams = decodedUrl.slice(48).toString(); // string it after slicing the binary contents
        var splitParams = justParams.split('|');
        var bucketUrl = splitParams[0];
	
    	// take parameters from the url and use them to shape the imgproxy url
        var imgMode = 'fit';
        if (splitParams[3] != '') var imgSize = splitParams[3];
        if (splitParams[6] != '') {
                var imgSize = splitParams[6];
                imgMode = 'fill';
        }
        var imgSizeParts = imgSize.split('x');
        var imgH = imgSizeParts[0];
        var imgW = imgSizeParts[1];
        
        // make image format based on extension in url
        var imgFormat = 'jpg';
        if (r.uri.substring(r.uri.length -4, r.uri.length)  === "webp") imgFormat = 'webp';
        
        // imgproxy is running localhost, no need to encode or encrypt url, it's invisible
        var newUrl = 'http://127.0.0.1:8080/donedeal/' + imgMode + '/' + imgH + '/' + imgW + '/ce/0/plain/' + bucketUrl + '@' + imgFormat;
        //r.headersOut['debug-hint'] = [newUrl];
        return(newUrl);
}

  

Comments

Popular posts from this blog

Baileys liquor Chocolate Chip and Cream desert

using t1n1wall, opnsense or pfsense on Google Compute Engine GCE