Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Responsive Images with node.js
<!doctype html>
<html>
<head>
<script>
var uri = 'http://localhost:1337/?width=' + window.innerWidth;
document.write('<script src="' + uri + '"><\/script>');
</script>
<title>Responsive Images Test</title>
<style type="text/css">
.image-container {
padding: 1em;
border: 1px solid #ccc;
background-color: #eee;
float: left;
}
</style>
</head>
<body>
<h1>Responsive Images Test</h1>
<div class="image-container">
<img src="http://localhost:1337/sandbox/timeout/cat-in-tree.jpg" />
</div>
</body>
</html>
var
http = require('http'),
url = require('url'),
registry = {};
http.createServer(function (req, res) {
var
parts = url.parse(req.url, true),
id = req.headers['user-agent'] + '@' + req.connection.remoteAddress,
serviceImageRequest = function () {
var location;
attempts += 1;
console.log('Attempt ' + attempts + ' to service ' + req.url);
if (registry[id]) {
console.log('Found ' + id + ' in registry - responding.');
console.log(req.url);
if (registry[id] > 1500) {
console.log("Redirecting to desktop image");
location = 'http://localhost' + matches[1] + '-desktop.' + matches[2];
} else {
console.log("Redirecting to mobile image");
location = 'http://localhost' + matches[1] + '-mobile.' + matches[2];
}
res.writeHead(302, {
'Location': location
});
res.end();
} else if (attempts >= 10) {
console.log('Too many attempts (' + attempts + ') to find ' + id + ' in registry. Just sending mobile version');
location = 'http://localhost' + matches[1] + '-mobile.' + matches[2];
res.writeHead(302, {
'Location': location
});
res.end();
} else {
console.log('Not found ' + id + ' in registry - defering');
setTimeout(function () {
serviceImageRequest();
}, 100);
}
},
imagePattern = /^(.+)\.(jpe?g|gif|png)$/,
matches,
attempts = 0;
console.log('Received request: ' + req.url);
console.log('This browser given id: ' + id);
if (parts.query && parts.query.width) {
console.log('Device info received - this client has width ' + parts.query.width);
registry[id] = parts.query.width;
res.writeHead(200, {'Content-Type': 'application/javascript'});
res.end();
} else if (matches = req.url.match(imagePattern)) {
console.log('Image request');
serviceImageRequest();
} else {
console.log('Unrecognised request');
res.writeHead(404);
res.end();
}
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');
Owner

Geraint commented Dec 7, 2011

Rather than using (the dangerously non-unique) IP+User Agent String as an ID, perhaps the server could generate an unique ID for the page request.

If that ID gets included in the URI for image requests and Device Capabilities Notification Request, it should be possible to associate all the image requests with the device.

Downside is that we have to do this for every page request, so +1 HTTP request, and possible deferment.

We also need to clear out the item from the registry after some period of time (setTimeout()). Having a page request id, rather than a device id, makes this safer.

It may be possible to use https://github.com/rsms/node-imagemagick to return a resized image directly (if not already cached), rather than relying on a redirect (and the associated additional HTTP requests).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment