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 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; |
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 for artwork:
https://i1.sndcdn.com/artworks-1TKywvsYSljt2vXR-KSOtfQ-t500x500.jpg
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gist.github.com/gaearon/717ed6d6c7771f95d50d#file-fixsoundcloudartworkurl-js-L52
It's a widespread convention known as "так исторически сложилось"