ring-clojure/ring

Range header not respected when serving files

Closed this issue · 4 comments

edit: I ended up making a package for this:


I came across an issue where the ring server was serving mp4 files, but Safari likes to stream the video in small parts using the Range header. Header looks something like Range: bytes=0-1

It doesn't seem that ring supports this. Should this function be modified?

(defn file-response
"Returns a Ring response to serve a static file, or nil if an appropriate
file does not exist.
Options:
:root - take the filepath relative to this root path
:index-files? - look for index.* files in directories (defaults to true)
:allow-symlinks? - allow symlinks that lead to paths outside the root path
(defaults to false)"
([filepath]
(file-response filepath {}))
([filepath options]
(if-let [file (find-file filepath options)]
(let [data (file-data file)]
(-> (response (:content data))
(content-length (:content-length data))
(last-modified (:last-modified data)))))))

I'd welcome a patch to add support for Range, though as middleware, rather than a modification of file-response, as Range can be useful for any 200 OK response. My guess is that this is going to be reasonably complex, as it needs to deal with a number of different scenaros.

However, it's worth noting that Range is an optional header, and may be safely ignored by the server, though obviously that may mean the server is sending more data than necessary.

sova commented

Humorous, I just ran into this problem myself =)
Yes, apparently WebKit (iOS mobile) requires these three (3) headers for HTML5 audio to have a seek bar rather than say "Live Broadcast":

Accept-Ranges:bytes
Content-Length:7437847
Content-Range:bytes 0-7437846/7437847

Using java.io as io you can have something such as
file-size-in-bytes (.length (io/file -filename-))
and the header can be something like
"Content-Range" (str "bytes 0-" (dec file-size-in-bytes) "/" file-size-in-bytes)

I'm testing this now, hopefully it will work as expected.

It would be nice if WebKit respected the "optional" part of Content-Range, especially because it's clearly discernible when one knows the Content-Length, but I can't argue with them over BugZilla all day.

sova commented

@patosai please use absolute file name instead of relative file name in the audio element source
https://stackoverflow.com/a/43133607/440887
Hopefully that fixes the issue for you (don't ask me why :D)

I eventually hosted the file on Cloudfront and because that implements the Range header, it ended up working. I'm working on a pull request for this.