Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am making an web app using SoundCloud's API. Requesting an MP3 to stream involves two requests. I'll give an example. Firstly:

http://api.soundcloud.com/tracks/59815100/stream

This returns a 302 with a temporary link to the actual MP3 (which varies each time), for example:

http://ec-media.soundcloud.com/xYZk0lr2TeQf.128.mp3?ff61182e3c2ecefa438cd02102d0e385713f0c1faf3b0339595667fd0907ea1074840971e6330e82d1d6e15dd660317b237a59b15dd687c7c4215ca64124f80381e8bb3cb5&AWSAccessKeyId=AKIAJ4IAZE5EOI7PA7VQ&Expires=1347621419&Signature=Usd%2BqsuO9wGyn5%2BrFjIQDSrZVRY%3D

The issue I had was that I am attempting to load the MP3 via JavaScript's XMLHTTPRequest, and for security reasons the browser can't follow the 302, as ec-media.soundcloud.com does not set a header saying it is safe for the browser to access via XMLHTTPRequest.

So instead of using the SoundCloud URL, I set up two locations in nginx, so the browser only interacts with the server my app is hosted on and no security errors come up:

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;
}

So myserver/soundcloud/tracks/59815100 returns a 302 to /myserver/soundcloud/media/xYZk0lr2TeQf.128.mp3...etc, which then forwards the MP3 on.

This works! However, I have hit a snag. Sometimes the 302 location is not ec-media.soundcloud.com, it's ak-media.soundcloud.com. There are possibly even more servers out there and presumably more could appear at any time. Is there any way I can handle an arbitrary 302 location without having to manually enter each possible variation?

Or is it possible for nginx to handle the redirect and return the response of the second step? So myserver/soundcloud/tracks/59815100 follows the 302 behind the scenes and returns the MP3?

The browser automatically follows the redirect, so I can't do anything with the initial response on the client side.

I am new to nginx and in a bit over my head so apologies if I've missed something obvious, or it's beyond the scope of nginx. Thanks a lot for reading.

share|improve this question

1 Answer 1

You can use regular expressions in proxy_redirect. See the docs.

Something like:

proxy_redirect ~^http://[^/]+(/.+)$ /soundcloud/media$1;

should do the trick.

btw, you're doing something strange here:

location /soundcloud/media/ {
    rewrite \/soundcloud\/media\/(.*) /$1 break;
    proxy_set_header Host ec-media.soundcloud.com;
    proxy_pass http://ec-media.soundcloud.com;
}

it's equal to this:

location /soundcloud/media/ {
    proxy_pass http://ec-media.soundcloud.com/;
}

Reading documentation is always a good idea.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.