我正在使用 SoundCloud 的 API 制作一个 Web 应用。请求流式传输 MP3 涉及两个请求。我举个例子。首先:
http://api.soundcloud.com/tracks/59815100/stream
这将返回一个 302 和一个指向实际 MP3(每次都不同)的临时链接,例如:
http://ec-media.soundcloud.com/xYZk0lr2TeQf.128.mp3?ff61182e3c2ecefa438cd02102d0e385713f0c1faf3b0339595667fd0907ea1074840971e6330e82d1d6e15dd660317b237a59b15dd687c7c4215ca64124f80381e8bb3cb5&AWSAccessKeyId=AKIAJ4IAZE5EOI7PA7VQ&Expires=1347621419&Signature=Usd%2BqsuO9wGyn5%2BrFjIQDSrZVRY%3D
我遇到的问题是,我试图通过 JavaScript 的 XMLHTTPRequest 加载 MP3,但出于安全原因,浏览器无法遵循 302,因为 ec-media.soundcloud.com 没有设置标头来表明浏览器通过 XMLHTTPRequest 访问是安全的。
因此,我没有使用 SoundCloud URL,而是在 nginx 中设置了两个位置,这样浏览器就只与托管我的应用程序的服务器交互,并且不会出现任何安全错误:
location /soundcloud/tracks/ {
# rewrite URL to match api.soundcloud.com's URL structure
rewrite \/soundcloud\/tracks\/(\d*) /tracks/$1/stream break;
proxy_set_header Host api.soundcloud.com;
proxy_pass http://api.soundcloud.com;
# the 302 will redirect to /soundcloud/media instead of the original domain
proxy_redirect http://ec-media.soundcloud.com /soundcloud/media;
}
location /soundcloud/media/ {
rewrite \/soundcloud\/media\/(.*) /$1 break;
proxy_set_header Host ec-media.soundcloud.com;
proxy_pass http://ec-media.soundcloud.com;
}
因此 myserver/soundcloud/tracks/59815100 向 /myserver/soundcloud/media/xYZk0lr2TeQf.128.mp3...etc 返回 302,然后将 MP3 转发。
这有效!但是,我遇到了一个问题。有时 302 位置不是 ec-media.soundcloud.com,而是 ak-media.soundcloud.com。可能还有更多的服务器,而且可能随时会出现更多的服务器。有什么方法可以处理任意 302 位置,而不必手动输入每个可能的变体?
或者 nginx 是否可以处理重定向并返回第二步的响应?那么 myserver/soundcloud/tracks/59815100 在后台遵循 302 并返回 MP3?
浏览器会自动遵循重定向,所以我无法对客户端的初始响应执行任何操作。
我对 nginx 还不熟悉,所以如果我遗漏了一些显而易见的内容,或者超出了 nginx 的范围,请原谅。非常感谢您的阅读。
答案1
您可以在 中使用正则表达式proxy_redirect
。请参阅文档。
就像是:
proxy_redirect ~^http://[^/]+(/.+)$ /soundcloud/media$1;
应该可以解决问题。
顺便说一句,你在这里做了一些奇怪的事情:
location /soundcloud/media/ {
rewrite \/soundcloud\/media\/(.*) /$1 break;
proxy_set_header Host ec-media.soundcloud.com;
proxy_pass http://ec-media.soundcloud.com;
}
它等于这个:
location /soundcloud/media/ {
proxy_pass http://ec-media.soundcloud.com/;
}
阅读文档始终是一个好主意。