如何在更改iframe src时设置自定义http标头?

时间:2021-03-06 15:12:44

Is there a way to add a custom http header into the request done by an <iframe> when changing the source (src) using javascript?

有没有办法在使用javascript更改源(src)时为

4 个解决方案

#1


26  

You can have the results of an ajax request that has custom headers be set as the content of an iframe like so:

您可以将包含自定义标头的ajax请求的结果设置为iframe的内容,如下所示:

$.ajax({
    type: "GET", 
    url: "https://app.icontact.com/icp/a/",
    contentType: "application/json",
    beforeSend: function(xhr, settings){
            xhr.setRequestHeader("some_custom_header", "foo");},
    success: function(data){
        $("#output_iframe_id").attr('src',"data:text/html;charset=utf-8," + escape(data))
    }
});

This is assuming the iframe is pointing at a cross domain src. It is simpler if everything is on the same domain.

这是假设iframe指向跨域src。如果所有内容都在同一个域中,则更简单。

Edit: Maybe try this variation.

编辑:也许尝试这种变化。

$.ajax({
    type: "GET", 
    url: "https://app.icontact.com/icp/a/",
    contentType: "application/json",
    beforeSend: function(xhr, settings){
            xhr.setRequestHeader("some_custom_header", "foo");},
    success: function(data){
        $("#output_iframe_id").attr('src',"/")
        $("#output_iframe_id").contents().find('html').html(data); 
    }
});

#2


7  

Rather than using a data URI, or setting the contents to a string, you can use URL.createObjectURL(), and set it as the src of the iframe.

您可以使用URL.createObjectURL(),并将其设置为iframe的src,而不是使用数据URI或将内容设置为字符串。

var xhr = new XMLHttpRequest();

xhr.open('GET', 'some.pdf');
xhr.onreadystatechange = handler;
xhr.responseType = 'blob';
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.send();

function handler() {
  if (this.readyState === this.DONE) {
    if (this.status === 200) {
      // this.response is a Blob, because we set responseType above
      var data_url = URL.createObjectURL(this.response);
      document.querySelector('#output-frame-id').src = data_url;
    } else {
      console.error('no pdf :(');
    }
  }
}

The object URLs are pretty interesting. They're of the form blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. You can actually open them in a new tab and see the response, and they're discarded when the context that created them is closed.

对象URL非常有趣。它们的形式为blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170。实际上,您可以在新选项卡中打开它们并查看响应,并在创建它们的上下文关闭时将它们丢弃。

Here's a full example: https://github.com/courajs/pdf-poc

这是一个完整的例子:https://github.com/courajs/pdf-poc

#3


5  

I ended up going with the approach proposed by the other answers here, that use ajax to get the html string and then directly set the contents of the iFrame.

我最后采用了其他答案提出的方法,使用ajax获取html字符串,然后直接设置iFrame的内容。

However, I used the approach posted in this answer to actually set the contents of the iFrame, as I found it worked well cross platform with almost all devices I could dig up.

但是,我使用了这个答案中发布的方法来实际设置iFrame的内容,因为我发现它在几乎所有我可以挖掘的设备上都能很好地跨平台工作。

Tested - successful:

经过测试 - 成功:

  • Chrome 54 (desktop) ^
  • Chrome 54(桌面)^

  • Firefox 49 (desktop) ^
  • Firefox 49(桌面)^

  • IE 11 (desktop) ^
  • IE 11(桌面)^

  • IE 10 (desktop) in emulation mode ^
  • IE 10(桌面)处于仿真模式^

  • Safari/Chrome on iOS 8 (ipad)
  • iOS 8上的Safari / Chrome(ipad)

  • Chrome on Android 6 (nexus phone)
  • Android 6上的Chrome(nexus手机)

  • Edge on Lumia 950 (Win 10 Phone)
  • Edge on Lumia 950(赢10手机)

^ confirmed that linked css and js in the content run correctly (others not tested)

^确认内容中链接的css和js正确运行(其他未测试)

Tested - unsuccessful:

经过测试 - 不成功:

  • IE 9 (desktop) in emulation mode
  • IE 9(桌面)处于仿真模式

  • Safari/Chrome on iOS 7 (iPhone)
  • iOS 7(iPhone)上的Safari / Chrome

So putting them together gives something like this (Note: I havn't actually run this exact code):

所以将它们放在一起会产生这样的结果(注意:我实际上并没有运行这个确切的代码):

$.ajax({
    type: "GET", 
    url: "https://yourdomain.com/gethtml",
    beforeSend: function(xhr) {
        xhr.setRequestHeader("yourheader", "value");
    },
    success: function(data) {
        var iframeDoc = document.querySelector('#myiframe').contentWindow.document;
        iframeDoc.open('text/html', 'replace');
        iframeDoc.write(data);
        iframeDoc.close();
    }
});

Here's an example of setting the iFrame contents in this JS Bin

这是在此JS Bin中设置iFrame内容的示例

Edit: Here's the html part

编辑:这是html部分

<iframe id="myiframe" src="about:blank"></iframe>

Edit 2:

The solution above appears to no longer be working in Firefox (50.1.0) for some unknown reason. Using the solution in this answer I've now changed to code to the example below, which also seems to be more robust:

由于某些未知原因,上述解决方案似乎不再适用于Firefox(50.1.0)。在这个答案中使用解决方案我现在已经改为代码到下面的例子,它似乎也更强大:

$.ajax({
    type: "GET", 
    url: "https://yourdomain.com/gethtml",
    beforeSend: function(xhr) {
        xhr.setRequestHeader("yourheader", "value");
    },
    success: function(data) {
        var iframe = document.getElementById('myiframe');
        iframe.contentWindow.contents = data;
        iframe.src = 'javascript:window["contents"]';
    }
});

#4


4  

The following code works. It is a modification of the code provided by Matthew Graves, modified to use the srcdoc attribute to solve the problem of CSS and JavaScript references not been ran. Unfortunately, it is only working in Chrome.

以下代码有效。它是对Matthew Graves提供的代码的修改,修改为使用srcdoc属性来解决CSS和JavaScript引用未运行的问题。不幸的是,它只适用于Chrome。

 $.ajax({
        type: "GET", 
        url: "https://app.icontact.com/icp/a/",
        contentType: "application/json",
        beforeSend: function(xhr, settings){
                xhr.setRequestHeader("some_custom_header", "foo");},
        success: function(data){
            $("#output_iframe_id").attr('srcdoc',data)
        }
    });

Edit: Finally, I have resolved the issue of the scripts blocks cross-browser, by reassigning them to the iframe on document.ready function:

编辑:最后,我已经解决了跨浏览器的脚本块问题,通过将它们重新分配给document.ready函数上的iframe:

$(document).ready(function () {
    var doc = $(document);
    if (frames.length > 0) {
        doc = frames[0].document;
        $(doc).find('script').each(function () {
            var script = document.createElement("script");
            if ($(this).attr("type") != null) script.type = $(this).attr("type");
            if ($(this).attr("src") != null) script.src = $(this).attr("src");
            script.text = $(this).html();
            $(doc).find('head')[0].appendChild(script);
            $(this).remove();
        });
    }
});

#1


26  

You can have the results of an ajax request that has custom headers be set as the content of an iframe like so:

您可以将包含自定义标头的ajax请求的结果设置为iframe的内容,如下所示:

$.ajax({
    type: "GET", 
    url: "https://app.icontact.com/icp/a/",
    contentType: "application/json",
    beforeSend: function(xhr, settings){
            xhr.setRequestHeader("some_custom_header", "foo");},
    success: function(data){
        $("#output_iframe_id").attr('src',"data:text/html;charset=utf-8," + escape(data))
    }
});

This is assuming the iframe is pointing at a cross domain src. It is simpler if everything is on the same domain.

这是假设iframe指向跨域src。如果所有内容都在同一个域中,则更简单。

Edit: Maybe try this variation.

编辑:也许尝试这种变化。

$.ajax({
    type: "GET", 
    url: "https://app.icontact.com/icp/a/",
    contentType: "application/json",
    beforeSend: function(xhr, settings){
            xhr.setRequestHeader("some_custom_header", "foo");},
    success: function(data){
        $("#output_iframe_id").attr('src',"/")
        $("#output_iframe_id").contents().find('html').html(data); 
    }
});

#2


7  

Rather than using a data URI, or setting the contents to a string, you can use URL.createObjectURL(), and set it as the src of the iframe.

您可以使用URL.createObjectURL(),并将其设置为iframe的src,而不是使用数据URI或将内容设置为字符串。

var xhr = new XMLHttpRequest();

xhr.open('GET', 'some.pdf');
xhr.onreadystatechange = handler;
xhr.responseType = 'blob';
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.send();

function handler() {
  if (this.readyState === this.DONE) {
    if (this.status === 200) {
      // this.response is a Blob, because we set responseType above
      var data_url = URL.createObjectURL(this.response);
      document.querySelector('#output-frame-id').src = data_url;
    } else {
      console.error('no pdf :(');
    }
  }
}

The object URLs are pretty interesting. They're of the form blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. You can actually open them in a new tab and see the response, and they're discarded when the context that created them is closed.

对象URL非常有趣。它们的形式为blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170。实际上,您可以在新选项卡中打开它们并查看响应,并在创建它们的上下文关闭时将它们丢弃。

Here's a full example: https://github.com/courajs/pdf-poc

这是一个完整的例子:https://github.com/courajs/pdf-poc

#3


5  

I ended up going with the approach proposed by the other answers here, that use ajax to get the html string and then directly set the contents of the iFrame.

我最后采用了其他答案提出的方法,使用ajax获取html字符串,然后直接设置iFrame的内容。

However, I used the approach posted in this answer to actually set the contents of the iFrame, as I found it worked well cross platform with almost all devices I could dig up.

但是,我使用了这个答案中发布的方法来实际设置iFrame的内容,因为我发现它在几乎所有我可以挖掘的设备上都能很好地跨平台工作。

Tested - successful:

经过测试 - 成功:

  • Chrome 54 (desktop) ^
  • Chrome 54(桌面)^

  • Firefox 49 (desktop) ^
  • Firefox 49(桌面)^

  • IE 11 (desktop) ^
  • IE 11(桌面)^

  • IE 10 (desktop) in emulation mode ^
  • IE 10(桌面)处于仿真模式^

  • Safari/Chrome on iOS 8 (ipad)
  • iOS 8上的Safari / Chrome(ipad)

  • Chrome on Android 6 (nexus phone)
  • Android 6上的Chrome(nexus手机)

  • Edge on Lumia 950 (Win 10 Phone)
  • Edge on Lumia 950(赢10手机)

^ confirmed that linked css and js in the content run correctly (others not tested)

^确认内容中链接的css和js正确运行(其他未测试)

Tested - unsuccessful:

经过测试 - 不成功:

  • IE 9 (desktop) in emulation mode
  • IE 9(桌面)处于仿真模式

  • Safari/Chrome on iOS 7 (iPhone)
  • iOS 7(iPhone)上的Safari / Chrome

So putting them together gives something like this (Note: I havn't actually run this exact code):

所以将它们放在一起会产生这样的结果(注意:我实际上并没有运行这个确切的代码):

$.ajax({
    type: "GET", 
    url: "https://yourdomain.com/gethtml",
    beforeSend: function(xhr) {
        xhr.setRequestHeader("yourheader", "value");
    },
    success: function(data) {
        var iframeDoc = document.querySelector('#myiframe').contentWindow.document;
        iframeDoc.open('text/html', 'replace');
        iframeDoc.write(data);
        iframeDoc.close();
    }
});

Here's an example of setting the iFrame contents in this JS Bin

这是在此JS Bin中设置iFrame内容的示例

Edit: Here's the html part

编辑:这是html部分

<iframe id="myiframe" src="about:blank"></iframe>

Edit 2:

The solution above appears to no longer be working in Firefox (50.1.0) for some unknown reason. Using the solution in this answer I've now changed to code to the example below, which also seems to be more robust:

由于某些未知原因,上述解决方案似乎不再适用于Firefox(50.1.0)。在这个答案中使用解决方案我现在已经改为代码到下面的例子,它似乎也更强大:

$.ajax({
    type: "GET", 
    url: "https://yourdomain.com/gethtml",
    beforeSend: function(xhr) {
        xhr.setRequestHeader("yourheader", "value");
    },
    success: function(data) {
        var iframe = document.getElementById('myiframe');
        iframe.contentWindow.contents = data;
        iframe.src = 'javascript:window["contents"]';
    }
});

#4


4  

The following code works. It is a modification of the code provided by Matthew Graves, modified to use the srcdoc attribute to solve the problem of CSS and JavaScript references not been ran. Unfortunately, it is only working in Chrome.

以下代码有效。它是对Matthew Graves提供的代码的修改,修改为使用srcdoc属性来解决CSS和JavaScript引用未运行的问题。不幸的是,它只适用于Chrome。

 $.ajax({
        type: "GET", 
        url: "https://app.icontact.com/icp/a/",
        contentType: "application/json",
        beforeSend: function(xhr, settings){
                xhr.setRequestHeader("some_custom_header", "foo");},
        success: function(data){
            $("#output_iframe_id").attr('srcdoc',data)
        }
    });

Edit: Finally, I have resolved the issue of the scripts blocks cross-browser, by reassigning them to the iframe on document.ready function:

编辑:最后,我已经解决了跨浏览器的脚本块问题,通过将它们重新分配给document.ready函数上的iframe:

$(document).ready(function () {
    var doc = $(document);
    if (frames.length > 0) {
        doc = frames[0].document;
        $(doc).find('script').each(function () {
            var script = document.createElement("script");
            if ($(this).attr("type") != null) script.type = $(this).attr("type");
            if ($(this).attr("src") != null) script.src = $(this).attr("src");
            script.text = $(this).html();
            $(doc).find('head')[0].appendChild(script);
            $(this).remove();
        });
    }
});