Serving 206 Byte-Range through Nginx, Django
Asked Answered
M

3

4

I have Nginx serving my static Django files which is being run on Gunicorn. I am trying to serve MP3 files and get them to have the head 206 so that they will be accepted by Apple for podcasting. At the moment the audio files are in my static directory and are served straight through Nginx. This is the response i get:

    HTTP/1.1 200 OK
    Server: nginx/1.2.1
    Date: Wed, 30 Jan 2013 07:12:36 GMT
    Content-Type: audio/mpeg
    Content-Length: 22094968
    Connection: keep-alive
    Last-Modified: Wed, 30 Jan 2013 05:43:57 GMT

Can someone help with the correct way to serve mp3 files so that byte-ranges will be accepted.

Update: This is the code in my view that serves the file through Django

    response = HttpResponse(file.read(), mimetype=mimetype)
    response["Content-Disposition"]= "filename=%s" % os.path.split(s)[1]
    response["Accept-Ranges"]="bytes"
    response.status_code = 206
    return response
Myrtia answered 30/1, 2013 at 7:16 Comment(2)
What behavior are you wishing for?Ballesteros
I am having two problems. If I serve the file like this then it doesnt work in an itunes podcast and I cant play the file in the browser. However if I serve it statically it will play in browser but it does now serve it as a 206 Byte-Range and so apple wont accept the podcast. I am trying to find a solution. It would be great if I could serve it through Django and get it to workMyrtia
T
2

If you want to do this only in nginx then in your location directive which is responsible for serving static .mp3 files add those directives:

# here you add response header "Content-Disposition"
# with value of "filename=" + name of file (in variable $request_uri),
# so for url example.com/static/audio/blahblah.mp3 
# it will be /static/audio/blahblah.mp3
# ----
set $sent_http_content_disposition filename=$request_uri;
    # or
add_header content_disposition filename=$request_uri;

# here you add header "Accept-Ranges"
set $sent_http_accept_ranges bytes;
# or
add_header accept_ranges bytes;

# tell nginx that final HTTP Status Code should be 206 not 200
return 206;
Thoma answered 30/1, 2013 at 20:9 Comment(0)
L
1

There is something in your config that prevent nginx from supporting range requests for these static files. When using standard nginx modules, this may be one of the following filters (these filters modify responses, and byte-range handling is disabled if modification may happen during request body handling):

All these modules have directives to control MIME types they work with (gzip_types, gunzip_types, addition_types, ssi_types). By default, they are set to restrictive sets of MIME types, and range requests works fine for most static files even if these modules are enabled. But placing something like

ssi on;
ssi_types *;

into a configuration will disable byte-range support for all static files affected.

Check your nginx configuration and remove offending lines, and/or make sure to switch off modules in question for a location you serve your mp3 files from.

Langsyne answered 27/6, 2014 at 19:18 Comment(1)
Thanks a lot, it really was ssi_types *; Turning it on for specific files will probably help with performance too.Plaything
B
0

You can define your own status code:

response = HttpResponse('this is my response data')
response.status_code = 206
return response

If you are using Django 1.5 you may want to have a look at the new StreamingHttpResponse:

https://docs.djangoproject.com/en/dev/ref/request-response/#streaminghttpresponse-objects

This can be very helpful for big files.

Ballesteros answered 30/1, 2013 at 13:27 Comment(4)
Thank you so much for the answer. Its amazing. Do you know how to get that done if I like straight to the file and serve it through Nginx and not Django. In case Apple wont accept the file being served by an indirect linkMyrtia
Django will serve Nginx, with headers etc. Are you walking about serving the file outside Django?Ballesteros
When I serve it through Django the link looks something like this example.com/audio/audiofile/123/ and it responds with the mp3 file. When I serve it no through Django it looks like this example.com/static/audio/blahblah.mp3Myrtia
I am struggling to get itunes to recognize and play the first linkMyrtia

© 2022 - 2024 — McMap. All rights reserved.