当响应位置的域发生变化时使用 nginx 的 proxy_redirect

当响应位置的域发生变化时使用 nginx 的 proxy_redirect

我正在使用 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/;
}

阅读文档始终是一个好主意。

相关内容