13

I am working on a project where we need to add some custom headers to the HTTP requests for image, video and audio content in the browser. I've been looking around and not really coming up with a good answer, other than possibly creating browser plugins.

Decorating the URL is not an option at this time because the gateway is looking for headers.

I can get the content by AJAX requests and adding the header to AJAX requests, then reassembling the content, base64 encoding it, then feeding that to the image, video or audio element, using a data: URI for the src. but that is horribly inefficient, especially for videos, where we think the content may be as much as 120MB. This technique also does not allow the video element to buffer the stream.

So I am looking for ideas on how the native browser behavior can be used, but with injecting the required custom headers. Can I have

<img src="javascript:MyFunction(this)" />

or

<video src="javascript:MyFunction(this)" />

Gary Williams
  • 289
  • 2
  • 5

2 Answers2

-1

You want to use the browser's native capability of downloading and rendering your image, audio, and video requests. Easy solution: Use an <iframe/>, then when you want to download something, set the src to the URL of the image, audio, or video. For instance...

<iframe src="https://wikipedia.com"/>

I went with a simple URL in this code snippet, and not an actual image, video, or audio file, since hotlinking is discouraged online.

By using an iframe, all of the browser's natural downloading and rendering elements will be available, plus, you can put the iframe anywhere in your app, giving you total control along with browser reliability.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
  • 1
    This does nothing to solve the custom request header problem, which is core to the question. – Brad Sep 14 '20 at 22:52
-1

As far s I'm aware the only way to do this is with XMLHttpRequest or fetch, BUT you can tried l retrieve binary data for videos and stream it using native stream APIs.

If the server allows partial requests, which allows you to get a certain amount of bytes only

You can append the different bytes to a mediasource https://developer.mozilla.org/en-US/docs/Web/API/MediaSource

I almost got it working

<div id="u"></div>
<Script>
vd("ok.mp4")
function vd(src) {
    
    var v=document. createElement("video")
    document.body.appendChild(v)
//  v.autoplay=true
    v. controls=true
//  v.src=src 
    v.play()
    
    var mime=
        'video/mp4; '+
        'codecs="avc1.42E01E, mp4a.40.2"'
    var ms= new MediaSource()
    v.src=URL.createObjectURL(ms)
    
    ms.addEventListener(
        "sourceopen", 
        function (){
            if(
                !MediaSource.
                isTypeSupported(
                    mime
                )
            ){
                u.innerHTML="eh"
                return
            }
            var sb= ms.addSourceBuffer(mime)
            fatch(src, function (d,hd){
                u.innerText=770+hd
                u.innerText+="7+("+d.length
                sb.appendBuffer(d)
                
                
                sb.addEventListener(
                    "updateend",
                    function (){
                        u.innerText+="&&77++"
                        ms.endOfStream()
                        v.play()
                    }
                )
                sb.addEventListener(
                    "error",
                    function (e){
                        u.innerText+=Object.entries(e)
                    }
                )
                sb.addEventListener(
                    "abort",
                    function (e){
                        u.innerText+=Object.entries(e)
                    }
                )
                sb.addEventListener(
                    "update",
                    function (e){
                        u.innerText+=Object.entries(e)
                    }
                )
                sb.addEventListener(
                    "updatestart",
                    function (e){
                        u.innerText+="ok man"
                    //  +objecktify(e)
                    }
                )
                
                
                
            })
        }
    )
    
}

function objecktify(obj) {
    var d=[]
    for(var k in obj){
        d.push([k,JSON.stringify(obj[k])])
    }
    return JSON.stringify(d,4,4,4)
}
function fatch(url, obj1) {
    var obj=obj1
    if(!typeof(obj)=="object")obj={}
    if(typeof(url) == "string") obj.url= url
    if (typeof(url)=="object") obj=url
    if(typeof(obj1)=="function") obj.cb=obj1
    
    var x= new XMLHttpRequest ()
    x.onload= function (){
        if(typeof (obj.cb)=="function"){
            obj.cb(
                x.response,
                x.getAllResponseHeaders()
            )
        }
    }
    if(typeof(
        obj.headers
    )=="object") {
        Object.entries(
            obj.headers
        ).forEach(function (z){
            x.setHeader(
                z[0],
                z[1]
            )
        
        })
    }
    
    x.responseType="arraybuffer"
    x.open("get",obj.url)
    x.send()
}
</Script>

Although the problem is that mediasource can only deal with fragmented mp4s https://github.com/w3c/media-source/issues/216 https://stackoverflow.com/a/18745164/2016831

But with some more research it should be possible to manually/automatically fragment the sections of the mp4 video with JavaScript after they're feutched, possibly using ffmpeg.js