乐闻世界logo
搜索文章和话题

Iframe 的 src 值是否可以添加请求头?

6 个月前提问
3 个月前修改
浏览次数234

5个答案

1
2
3
4
5

不,iframesrc 属性本身不提供添加请求头的能力。iframe 标签加载资源时,浏览器会使用默认的 GET 请求,而不能直接在 src 属性中指定请求头。

不过,有一些方法可以实现类似的效果,虽然它们不是通过在 iframesrc 中直接添加请求头来实现的。比如:

  1. 通过服务端设置: 你可以在服务端预先设置好请求头,然后当 iframe 请求该资源时,服务端会发送这些预设的请求头。这种方式的限制是它不能动态地根据客户端的需要改变请求头。

  2. 使用JavaScript和CORS: 如果你控制了 iframe 所加载页面的服务器,可以使用 fetchXMLHttpRequest 来发送带有自定义请求头的请求,并且可以在收到响应后将内容动态地插入到一个 iframe 或其他的 DOM 元素中。这需要服务器支持跨源资源共享 (CORS),以允许这种类型的请求。

    例如:

    javascript
    fetch('https://example.com/page', { method: 'GET', headers: { 'Custom-Header': 'value' } }) .then(response => response.text()) .then(html => { const iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.contentWindow.document.open(); iframe.contentWindow.document.write(html); iframe.contentWindow.document.close(); }) .catch(error => console.error(error));
  3. 使用服务端代理: 你可以创建一个服务端代理,该代理会添加所需的请求头,然后 iframe 可以指向这个代理。代理会处理来自 iframe 的请求,添加请求头,然后将请求转发到最终目标。它还会处理响应,将其返回给 iframe

总的来说,虽然不能直接在 iframesrc 属性中添加请求头,但是你可以使用服务端逻辑或客户端脚本以编程的方式来达到相似的效果。这些方法各有优缺点,适用于不同的场景。

2024年6月29日 12:07 回复

您可以在 JavaScript 中发出请求,设置您想要的任何标头。然后你就可以URL.createObjectURL()得到适合srciframe 的东西了。

shell
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

2024年6月29日 12:07 回复

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

2024年6月29日 12:07 回复

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

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

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

shell
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" width="300" height="200" srcDoc={content}> </iframe> </div> ); } export default App;

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

2024年6月29日 12:07 回复

事实证明, URL.createObjectURL() 在 Chrome 71 中已被弃用
(请参阅https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems),
构建于 @Niet 黑暗 Absol 和@FellowMD 的出色答案,如果您需要传递身份验证标头,这里介绍了如何将文件加载到 iframe 中。(您不能只将 src 属性设置为 URL):

shell
$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

2024年6月29日 12:07 回复

你的答案