An express app that redirects to largest SoundCloud artwork URL that doesn't 404.
'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; |
This comment has been minimized.
This comment has been minimized.
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
This comment has been minimized.
https://gist.github.com/gaearon/717ed6d6c7771f95d50d#file-fixsoundcloudartworkurl-js-L52
It's a widespread convention known as "так исторически сложилось"