Created
November 7, 2014 17:00
-
-
Save gaearon/717ed6d6c7771f95d50d to your computer and use it in GitHub Desktop.
An express app that redirects to largest SoundCloud artwork URL that doesn't 404.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var express = require('express'), | |
app = express(); | |
require('./config/development')(app, express); | |
require('./config/production')(app, express); | |
var redis = require('redis'), | |
request = require('request'), | |
Promise = require('bluebird'); | |
Promise.promisifyAll(redis.RedisClient.prototype); | |
var redisSettings = app.set('redis'), | |
redisClient = redis.createClient(redisSettings.port, redisSettings.host, redisSettings.options); | |
app.configure(function () { | |
app.use(express.bodyParser()); | |
app.use(app.router); | |
}); | |
function sendError(res, status, error) { | |
if (!(error instanceof Error)) { | |
error = new Error(JSON.stringify(error)); | |
} | |
return res | |
.status(status || 500) | |
.end(error && error.message || 'Internal Server Error'); | |
} | |
function generateCacheHeaders() { | |
var maxAge = 3600 * 24 * 365; | |
return { | |
'Cache-Control': 'public,max-age=' + maxAge, | |
'Expires': new Date(Date.now() + (maxAge * 1000)).toUTCString() | |
}; | |
} | |
function getCacheKey(url) { | |
return 'soundcloud-thumbnail-proxy:' + url; | |
} | |
app.get('/*', function (req, res) { | |
var originalUrl = req.params[0], | |
cacheKey = getCacheKey(originalUrl), | |
urls; | |
// https://developers.soundcloud.com/docs/api/reference#artwork_url | |
// This is a ridiculous naming scheme, by the way. | |
urls = [ | |
originalUrl, | |
originalUrl.replace('-large', '-t500x500'), | |
originalUrl.replace('-large', '-crop'), // 400x400 | |
originalUrl.replace('-large', '-t300x300'), | |
originalUrl.replace('-large', '-large') // 100x100 | |
]; | |
return redisClient.getAsync(cacheKey).then(function (cachedUrl) { | |
if (cachedUrl) { | |
return cachedUrl; | |
} | |
return Promise.reduce(urls, function (resolvedUrl, url) { | |
if (resolvedUrl) { | |
return resolvedUrl; | |
} | |
return new Promise(function (resolve) { | |
request.head(url, function (err, response) { | |
if (!err && response.statusCode === 200) { | |
resolve(url); | |
} else { | |
resolve(null); | |
} | |
}); | |
}); | |
}, null); | |
}).then(function (url) { | |
if (!url) { | |
throw new Error('File not found'); | |
} | |
var headers = generateCacheHeaders(); | |
for (var key in headers) { | |
if (headers.hasOwnProperty(key)) { | |
res.setHeader(key, headers[key]); | |
} | |
} | |
res.redirect(url); | |
redisClient.set(cacheKey, url); | |
redisClient.expire(cacheKey, 60 * 60 * 24 * 30); | |
}).catch(function (err) { | |
sendError(res, 404, err); | |
}); | |
}); | |
app.get('/crossdomain.xml', function (req, res) { | |
req.setEncoding('utf8'); | |
res.writeHead(200, { 'Content-Type': 'text/xml' }); | |
res.end('<?xml version="1.0" ?><cross-domain-policy><allow-access-from domain="*" /></cross-domain-policy>'); | |
}); | |
redisClient.on('ready', function () { | |
app.listen(app.set('port')); | |
}); | |
redisClient.on('error', function () { | |
throw new Error('Could not connect to Redis'); | |
}); | |
module.exports = app; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Heya,
Silly question - Where do i add the url for the soundcloud link?
Also is it possible for the output to be the a string which is the url of the artwork image.
example url:
url: https://soundcloud.com/jens-records/jens012-a1-funkig/s-ueATsI77OHU?in=jens-records/sets/jens112-the-ristorante-ep//s-9lt1WDfSCtf
url for artwork:
https://i1.sndcdn.com/artworks-1TKywvsYSljt2vXR-KSOtfQ-t500x500.jpg