Skip to content

Instantly share code, notes, and snippets.

@jimoneil
Created July 26, 2012 22:21
Show Gist options
  • Save jimoneil/3184950 to your computer and use it in GitHub Desktop.
Save jimoneil/3184950 to your computer and use it in GitHub Desktop.
Proxy Windows 8 notification image requests to Windows Azure Storage after interpreting query parameters resulting from addImageQuery
/*
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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment