Skip to content

Instantly share code, notes, and snippets.

@lerouxb
Created May 19, 2012 14:04
Show Gist options
  • Select an option

  • Save lerouxb/2730932 to your computer and use it in GitHub Desktop.

Select an option

Save lerouxb/2730932 to your computer and use it in GitHub Desktop.
var
express = require('express'),
gm = require('gm'),
http = require('http'),
request = require('request'),
urlmod = require('url'),
app = express.createServer();
app.use(express.logger('tiny'));
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
function checkURL(options, callback) {
// TODO: some kind of timeout would be nice
var
url = options.url,
supportedTypes = options.supportedTypes,
maxSize = options.maxSize;
request.head(url, function(err, response, data) {
if (err) {
// Probably anything from a timeout to network error.
console.error(err);
callback({name: "ServerError"});
} else if (response.statusCode != 200) {
// Assume not found for now.
// What about other success statuses?
callback({name: "NotFound"});
} else {
var
contentType = response.headers['content-type'],
contentLength = response.headers['content-length'];
if (supportedTypes.indexOf(contentType) == -1) {
callback({name: "UnknownType"});
} else if (!contentLength || contentLength < maxSize) {
// looks OK so far
callback(null, {
url: response.request.uri.href, // account for redirects
contentType: contentType,
contentLength: contentLength
});
} else {
callback({name: "TooBig"});
}
}
});
};
function identifyImageURL(options, callback) {
// TODO:
// * some kind of timeout would be nice
// * and maybe a whitelist of supported image formats
// * perhaps we should also make sure that only websafe features like
// colour profiles or modes are used
var
url = options.url,
maxSize = options.maxSize;
//maxSize = 0, // HACK
total = 0;
checkURL({
url: url,
supportedTypes: ['image/png', 'image/jpeg', 'image/gif'],
maxSize: maxSize
},
function(err, info) {
//console.log("checkURL", err, data);
if (err) {
callback(err);
} else {
http.get(urlmod.parse(info.url), function(res) {
res.on('data', function(chunk) {
total += chunk.length;
//console.log(chunk.length, total);
if (total > maxSize) {
//console.log('hanging up');
res.destroy();
}
});
var image = gm(res);
image.identify(function(err, features) {
if (err) {
if (total > maxSize) {
callback({name: "TooBig"});
} else {
callback({name: "ServerError"});
}
} else {
if (total > maxSize) {
callback({name: "TooBig"});
} else {
var data = {
url: info.url,
contentType: info.contentType,
contentLength: total,
format: features.format,
width: features.size.width,
height: features.size.height
};
callback(null, data);
}
}
});
});
}
});
};
app.get('/check/image', function(req, res) {
var
url = req.query.url,
maxSize = 5*1024*1024; // 5Mb
identifyImageURL({
url: url,
maxSize: maxSize
},
function(err, data) {
if (err) {
res.send({error: err.name});
} else {
res.send(data);
}
});
});
app.listen(3000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment