是否可以将请求标头添加到 iframe src 请求?

Posted

技术标签:

【中文标题】是否可以将请求标头添加到 iframe src 请求?【英文标题】:Is it possible to add Request Headers to an iframe src request? 【发布时间】:2012-11-06 03:16:35 【问题描述】:

我了解到,在 javascript 中进行 AJAX 调用时,您可以非常轻松地设置 HTTP 请求标头。

但是,在通过脚本将 iframe 插入页面时,是否也可以设置自定义 HTTP 请求标头?

<iframe src="someURL"> <!-- is there any place to set headers in this? -->

【问题讨论】:

【参考方案1】:

您可以在 javascript 中发出请求,设置您喜欢的任何标头。然后你可以URL.createObjectURL(),得到适合iframe的src的东西。

var xhr = new XMLHttpRequest();

xhr.open('GET', 'page.html');
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 :(');
    
  

保留响应的 MIME 类型。因此,如果您收到 html 响应,则 html 将显示在 iframe 中。如果您请求 pdf,浏览器 pdf 查看器将启动 iframe。

如果这是长期存在的客户端应用程序的一部分,您可能需要使用URL.revokeObjectURL() 以避免内存泄漏。

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

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

【讨论】:

完美。完美地工作。谢谢。 你这个人!我正在开发一个受此代码启发的 Angular 5 组件,以在 Angularjs 中显示 pdf 预览。这对我帮助很大 @BSSchwarzkopf 看起来你是对的。 Edge 支持 Blob URL,但它们在 iframe 的 src 属性中不起作用。我认为它违反了规范:“这个方案应该能够与 Web API 一起使用......以及设计用于 HTTP URL 的元素......一般来说,这个方案应该被设计为可以在 Web 上使用 URL 的任何地方使用。”边缘跟踪器问题:developer.microsoft.com/en-us/microsoft-edge/platform/issues/… 规范:w3.org/TR/FileAPI/#use-cases-scheme 我得到“无法在 'URL' 上执行 'createObjectURL':找不到与提供的签名匹配的函数。”在 Chrome 84.0.4147.105 上。 @poiuytrez 这意味着您传递了错误的参数。它需要文件、Blob 或 MediaSource。也许你传递的是 null、undefined、promise 或 Request 对象?【参考方案2】:

不,你不能。但是,您可以将 iframe 源设置为某种预加载脚本,该脚本使用 AJAX 来获取包含您想要的所有标题的实际页面。

【讨论】:

Hi Niet,能否提供 JSFiddle 中的示例实现代码 我相信 Niet 的意思是这样的 ***.com/a/17695034/1524918 这样的预加载脚本中的请求会不会被发送到不同的域,从而违反同源策略? 默认发送哪些标头?这有什么标准吗?【参考方案3】:

由于 createObjectURL 的贬值,@FellowMD 的答案不适用于现代浏览器,因此我使用了相同的方法,但使用了 iframe srcDoc 属性。

    使用 XMLHttpRequest 或任何其他方法检索要在 iframe 中显示的内容 设置iframe的srcdoc参数

请在下面找到一个 React 示例(我知道这是矫枉过正):

import React, useEffect, useState from 'react';

function App() 
  const [content, setContent] = useState('');


  useEffect(() => 
    // Fetch the content using the method of your choice
    const fetchedContent = '<h1>Some HTML</h1>';
    setContent(fetchedContent);
  , []);


  return (
    <div className="App">
      <iframe sandbox id="inlineFrameExample"
              title="Inline Frame Example"
              
              
              srcDoc=content>
      </iframe>


    </div>
  );


export default App;

现在大多数浏览器都支持 Srcdoc。看来Edge实现有点晚了:https://caniuse.com/#feat=iframe-srcdoc

【讨论】:

createObjectURL 仅在 MediaStream 参数中被弃用。不推荐传递 Blob,实际上是 sees pretty wide and increasing usage。不过,我很感激为保持最新状态所做的努力:) @poiuytrez 当我想获取带有自定义标头的内容时,我收到this question 中询问的错误,请您看一下 这个解决方案没有展示如何在请求中设置headers来获取内容【参考方案4】:

事实证明 URL.createObjectURL() 在 Chrome 71 中已被弃用 (见https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems) 在 @Niet the dark Absol 和 @FellowMD 的出色答案的基础上,如果您需要传入身份验证标头,这里是如何将文件加载到 iframe 中。 (您不能只将 src 属性设置为 URL):

$scope.load() 
    var iframe = #angular.element("#reportViewer");
    var url = "http://your.url.com/path/etc";
    var token = "your-long-auth-token";
    var headers = [['Authorization', 'Bearer ' + token]];
    $scope.populateIframe(iframe, url, headers);


$scope.populateIframe = function (iframe, url, headers) 
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.onreadystatechange = handler;
    xhr.responseType = 'document';
    headers.forEach(function (header) 
        xhr.setRequestHeader(header[0], header[1]);
    );
    xhr.send();

    function handler() 
        if (this.readyState === this.DONE) 
            if (this.status === 200) 
                var content = iframe[0].contentWindow ||
                    iframe[0].contentDocument.document || 
                    iframe[0].contentDocument;
                content.document.open();
                content.document.write(this.response.documentElement.innerHTML);
                content.document.close();
             else 
                iframe.attr('srcdoc', '<html><head></head><body>Error loading page.</body></html>');
            
        
    

向 courajs 大喊:https://github.com/courajs/pdf-poc/blob/master/script.js

【讨论】:

来自 Google 链接:“URL.createObjectURL() 方法已从 MediaStream 接口中删除。”这种影响 MediaStream 接口的弃用是否与其他答案相关? (我认为不会。) 不推荐使用。仅从 MediaStream 中删除 @TheMaster 这确实是文档所说的,但我花了几个小时试图让它工作但没有成功。它无法推测原因。上面显示的代码是我编写代码时最终运行的代码,我没有足够的带宽再试一次。 您可以将该方法用于 Blob 对象。在你的情况下,就像URL.createObjectURL(new Blob([this.response.documentElement.innerHTML])) createObjectURL 仅在 MediaStream 参数中被弃用。不推荐传递 Blob,实际上是 sees pretty wide and increasing usage。不过,我很感激为保持最新状态所做的努力:)

以上是关于是否可以将请求标头添加到 iframe src 请求?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以向 CORS 预检请求添加请求标头?

HFS在iFrame src中

将单个 HTTP 标头的多个值添加到请求或响应的标准

将单个 HTTP 标头的多个值添加到请求或响应的标准

Web 浏览器何时请求动态创建的 iframe 的 src 内容?

是否可以直接从 html img 标签 src 向服务器请求文件并使用 jwt 身份验证标头加载它?