Byte-Range Support

I’m serving audio for a podcast using Active Storage’s proxy feature with AWS’s S3. But the audio on iOS devices aren’t playing because Apple appears to (sometimes?) require byte range support.

Here’s a related issue, but I think the best solution would be to bake the support into Active Storage.

I found an example implementation of supporting it (that might be a bit old) on stack overflow: What is the proper way to serve mp4 files through rails to an Ipad? - Stack Overflow

I’d definitely be willing to create a PR but I wanted to start a discussion here to see if it’d be a welcomed addition. Let me know if I’m missing anything, or if there’s an easier way to add this support to my app.


For reference, here’s the related code: https://github.com/rails/rails/blob/master/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb

And in my case uses this: https://github.com/rails/rails/blob/72d30056a429f243c0454a94167229e4d03c7b3e/activestorage/lib/active_storage/service/s3_service.rb#L133

1 Like

Although I did not get to it yet, we are definitely looking forward to serve audio files using ActiveStorage in a secure and performant manner, also to iOS devices (here is another PR waiting on the topic). As Rails 6.2 development has started not long ago maybe now could be a good time to submit a PR.

1 Like

I went ahead and created a small branch where I think I have it working. I’m going to play around with it in a test application next.

If anyone has any feedback on it, let me know.

https://github.com/rails/rails/compare/master...tomprats:active-storage-byte-range?expand=1

1 Like

If you use pre-signed blob access then your HTTP requests will redirect to the actual storage backend with the Range headers kept in place. Given how stream is implemented in the proxy controller this might be much easier to achieve. Alternatively you can add your own implementation of the Blob serving using this bit of infra we are using: GitHub - WeTransfer/interval_response: Serve partial (Range) HTTP responses from 💎 applications

@julik It didn’t seem to be working for me through redirect or proxy options before. The headers being forwarded makes sense and since S3 supports those headers, it seems like it should have worked, but there was still an issue somewhere along the way. Maybe it’s supported but the Accept-Ranges: bytes header isn’t being passed so Apple isn’t trying it.

Either way, I created a PR to bake the support directly into ActiveStorage. I’m using an earlier version in a production app and updating another app to use the latest soon.

https://github.com/rails/rails/pull/41437

1 Like

@Tom_Prats What audio player do you use in the client side? I’ve not found audio players that sends the byte requests

I believe the issue occurs in Safari using the video tag. But also potentially in the Apple Podcast app. I think it’s been fixed since my PR was merged.