Range headers being stripped out

I have this beautiful Azle Express application that responds to range requests and thus streams audio and video files. It’s dead simple and works great locally.

I just deployed to mainnet (here’s the live canister, you can see in the network tab the failed requests), excited to test it out, and the first thing I see is that the range header seems to be undefined in the canister. Is the boundary node stripping the Range header out?

I ran into this issue a couple years back when trying to host my podcast from the IC. I had hoped that this was resolved, but now trying to make use of the feature on mainnet it seems it is again broken.

I would love to see the Range header passed along to the canister, and the Content-Range and any other required headers returned from the canister.

In general, please allow canisters to accept and return any headers that they possibly can so that we can build decentralized server applications.

Prior art:

14 Likes

+1 to simple video streaming solutions on ICP. If range requests can be implemented within a simple Azle canister we would start using it for video NFTs on ICP and video ordinals on Bioniq. We’ve never really had an easy way to implement simple video streaming for video NFTs (we’ve always had to wait to download the entire video before it could be played), and we’d love to have this kind of functionality.

I know there may be other initiatives in the works to enable video streaming on ICP, and if so, would love an update on those as well as they would be relevant to what @lastmjs is working on here.

7 Likes

Great work, was going the webRTC route for audio streaming. Does this mean we can start streaming data through canisters once successful? This reminds me of AWS Kinesis, one use case could be an IoT platform to process streams of data. People like real-time.

3 Likes

@rbirkner, @bjoern, @mraszyk, @dsarlis: do you see any issues with passing Content-Range headers ?

I don’t see any issues, but I am not an expert in HTTP gateway protocol.

5 Likes

Thank you Jordan for experimenting this. I am also in need for this to write full-stack websites. Right now I am using youtube for videos but this is not optimal. Would really love to utilize the full (400Gb) potential of canisters and consequently own the content across media types. Video is crucial. :pray:

4 Likes

Indeed the problem is on the boundary nodes. Adding the cache for static assets on the boundary nodes broke range requests. We will fix it and let you know once it is rolled out.

What happened: When nginx receives a range request and default caching is enabled, nginx actually tries to fetch the full file from the upstream and then serve only the bytes requested by the client.

And since your canister doesn’t support “non-range” requests, nginx fails to fetch and cache it:

$ curl 'https://f2j4a-eiaaa-aaaam-ab7nq-cai.raw.icp0.io/media/video.ogv'
Only range requests are supported%

Sorry about that!

6 Likes

Amazing! I’m extremely excited that the problem is known and a fix seems relatively simple!

Super super excited to be able to test this out once fixed, I appreciate it.

1 Like

Hopefully this won’t hold up a fix on mainnet, but one improvement I can foresee is making the local replica environment closer to the mainnet environment.

It’s always surprising and disturbing when all of your tests and functionality work locally and then mainnet is just materially different.

2 Likes

One consideration I’ve had is if the boundary nodes could pass through the headers if they are certified with v2 certification(cc @NathanosDev). This has the unfortunate reality that you’ll need to hard code what ranges your return, but as far as I can tell, ios and Safari don’t care if they request bytes 1-10 and you give them 1-2048000. So you could certify in 2MB chunks and always return the chunk that contains the start byte. The browser will see what the last bytes are and make a request for the next chunk.

so if they request 10-20 you return 0-(2048000-1( and then they’ll ask for 2048000 and they’ll get 2048000- (4096000-1). You may end up serving the same chunk a couple of times depending on their streaming strategy.

This also (may) help caching because the responses will always have the same hash…wait…actually maybe not because I’m guessing the cache is based on the request. hmm…

You could also break it into smaller than 2MB chunks to help with bandwidth.

I think the solution already suggested will work fine, the header just needs to be passed on to the canister, certification is not required or a factor here for what I’m looking for at least.

@rbirkner status code 206 and Content-Range in the response will also be required, will this work?

1 Like

Unless the boundary node is blocking anything not certified. In the past we had to use raw subdomain to get things through. I think this is different now but you do have to tag it with some extra header.

1 Like

We’re just assuming the raw subdomain for everything

1 Like

Awesome! I hope this Issue will be resolved soon so I can start working with videos. This functionality could make ICP more attractive, especially for products that rely heavily on video or streaming.

3 Likes

I believe video streaming is something that can being lots of adoption to ICP. And many ICP apps have abandoned live-steaming features in the past.

It would definetly be good to see improvements in this area.

3 Likes

This is great. Video streaming would unleash a new wave of innovation possible on ICP. This further extends what can be done on-chain. Social media, metaverse, education and more, all of these use video.

When could we hope this thing to be resolved? :pray:

1 Like

Yes, it will work. We will probably roll it out in this week’s release.

Last week, we had a bigger release and we didn’t want to cram that change into it as well.

You can already test it semi-locally by using icx-proxy and pointing it to the boundary nodes. In that setup, you get around the static asset cache:

cd rs/boundary_node/icx_proxy
cargo run -- -v --address 127.0.0.1:4704 --replica https://ic0.app/ --danger-accept-invalid-ssl

and then you can access your site in the browser using http://f2j4a-eiaaa-aaaam-ab7nq-cai.raw.localhost:4704/

1 Like

Audio streaming for Nuance is something we would love to do (based on user feedback). Video streaming has also been raised by Nuance users but have also stated that they prefer to embed YouTube videos as to not fragment their audience.

1 Like

How are things looking for a release this week?

Hey @lastmjs

we are just about to merge the change and might deploy a canary later today or tomorrow. However, we don’t like to deploy a release on the weekend. So for the full rollout, you will have to wait until early next week. I will ping you once it is done.

1 Like

Hey @lastmjs

I have just deployed the latest release to a canary node. You can try it by setting the following in your /etc/hosts file:

212.133.1.43 f2j4a-eiaaa-aaaam-ab7nq-cai.raw.icp0.io
2001:4c08:2003:b09:5000:fdff:fe6b:3430 f2j4a-eiaaa-aaaam-ab7nq-cai.raw.icp0.io
1 Like