public
Created

Proxy Windows 8 notification image requests to Windows Azure Storage after interpreting query parameters resulting from addImageQuery

  • Download Gist
server.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/*
Copyright (c) Microsoft
All rights reserved.
Licensed under the Microsoft Limited Public License (the “License”); you may not
use this file except in compliance with the License.
You may obtain a copy of the License at http://msdn.microsoft.com/en-us/cc300389.
 
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
win
See the Microsoft Limited Public License (Ms-LPL) for specific language governing
permissions and limitations under the License.
*/
 
var url = require('url');
var http = require('http');
 
// Azure Storage Account host
var AZURE_URI = "STORAGE_ACCOUNT.blob.core.windows.net";
var AZURE_PROTOCOL = "http";
var AZURE_PORT = 80;
 
// only build specific URLs for the following
var CUSTOM_LANGUAGES = []; // ["en-US", "fr-FR"];
 
var constructImageUri = function(img, l, c, s) {
 
var lastSlash = img.lastIndexOf("/");
if(lastSlash == -1) return img;
 
// interpret last segment in URL as file name
var imagePath = img.substring(0, lastSlash);
var imageFile = img.substring(lastSlash + 1);
var imageName = imageFile;
var imageExt;
 
// add language only if it's one with distinct images
if(CUSTOM_LANGUAGES.indexOf(l) != -1) imagePath = imagePath + "/" + l;
 
// add constrast name
if(c != null) imagePath = imagePath + "/" + c;
 
// modify file name to include scale-XXX nomenclature
if(s != null) {
var lastDot = imageFile.lastIndexOf(".");
if(lastDot == -1) lastDot = imageFile.length;
imageName = imageFile.substring(0, lastDot);
imageExt = imageFile.substring(lastDot) || "";
 
imageName = imageName + ".scale-" + s + imageExt;
}
 
return imagePath + "/" + imageName;
}
 
var retrieveImage = function(res, uris) {
 
// no more URIs to try; recursion fails and no image is served
if(uris.length == 0) {
res.writeHead(404);
res.end();
}
 
// full URI to Azure storage
var fullUri = AZURE_PROTOCOL + "://" + AZURE_URI + uris[0];
 
// create HTTP/HTTPS request to storage
var options = { host: AZURE_URI, port: AZURE_PORT, method: "HEAD", path: uris[0] };
require(AZURE_PROTOCOL).request(options, function(r) {
console.log(" checking: " + fullUri + " - " + r.statusCode + "\r\n");
 
// recurse if candidate URI not found
if(r.statusCode == 404) {
retrieveImage(res, uris.slice(1));
 
// if URI found, redirect
} else if(r.statusCode == 200) {
res.writeHead("307", { location: fullUri });
res.end();
 
// pass on any other response (likely error)
} else {
res.writeHead(r.statusCode, r.headers);
r.on('data', function(c) {
res.write(c);
});
r.on('end', function() {
res.end();
});
}
}).on('error', function(e) {
console.log(" error: " + e.message + "\r\n");
res.writeHead("400", null, e.message);
res.end();
}).end();
}
 
http.createServer(function(req, res) {
console.log("Image request: " + req.url + "\r\n");
 
// parse request URL
var parsedUrl = url.parse(req.url, true);
var imgPath = parsedUrl.pathname;
 
// list of candidate image URLs
var candidateUris = [];
 
// if there's a query string addImageQuery must have been set in template
if(Object.keys(parsedUrl.query).length > 0) {
var scaleArg = parsedUrl.query["ms-scale"] || "100";
var contrastArg = parsedUrl.query["ms-contrast"] || "standard";
var localeArg = parsedUrl.query["ms-lang"] || "";
 
if(CUSTOM_LANGUAGES.indexOf(localeArg) >= 0) {
candidateUris.push(constructImageUri(imgPath, localeArg, contrastArg, scaleArg));
candidateUris.push(constructImageUri(imgPath, localeArg, contrastArg, null));
candidateUris.push(constructImageUri(imgPath, localeArg, null, scaleArg));
candidateUris.push(constructImageUri(imgPath, localeArg, null, null));
}
candidateUris.push(constructImageUri(imgPath, null, contrastArg, scaleArg));
candidateUris.push(constructImageUri(imgPath, null, contrastArg, null));
candidateUris.push(constructImageUri(imgPath, null, null, scaleArg));
}
 
// push the default image URL
candidateUris.push(imgPath);
 
// get the image
retrieveImage(res, candidateUris);
 
}).listen(process.env.PORT || 8080);

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.