Можно ли добавить заголовки запроса в запрос iframe src?

83

Я понимаю, что вы можете очень легко установить заголовки HTTP-запросов при выполнении вызовов AJAX в JavaScript.

Однако можно ли также установить собственные заголовки HTTP-запроса при вставке iframe на страницу с помощью скрипта?

<iframe src="someURL"> <!-- is there any place to set headers in this? -->
onlywei
источник

Ответы:

31

Нет, не можешь. Однако вы можете установить в качестве iframeисточника какой-либо сценарий предварительной загрузки, который использует AJAX для получения фактической страницы со всеми нужными заголовками.

Ниет Темный Абсол
источник
4
Привет, Ниет! Не могли бы вы предоставить образец кода реализации в JSFiddle?
Навин Редди
Я считаю, что Niet означает что-то вроде этого stackoverflow.com/a/17695034/1524918
Райан Кара
5
Разве запрос в таком сценарии предварительной загрузки не будет отправлен в другой домен и, таким образом, не нарушит ту же политику происхождения?
mart1n 01
Какие заголовки отправляются по умолчанию? Есть ли на это какой-нибудь стандарт?
Иск Фонда Моники
74

Вы можете сделать запрос в javascript, установив любые заголовки, какие захотите. Тогда вы сможете URL.createObjectURL()получить что-то подходящее для srciframe.

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, он отобразится в iframe. Если вы запросили PDF-файл, программа просмотра PDF-файлов в браузере запустит iframe.

Если это часть долгоживущего клиентского приложения, вы можете использовать его, URL.revokeObjectURL()чтобы избежать утечек памяти.

URL-адреса объектов тоже довольно интересны. Они имеют форму blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. Фактически вы можете открыть их на новой вкладке и увидеть ответ, и они отбрасываются, когда контекст, в котором они созданы, закрывается.

Вот полный пример: https://github.com/courajs/pdf-poc

Научный сотрудник
источник
Отлично. Сработало безупречно. Спасибо.
mike123
ты мужчина! Я работаю над компонентом Angular 5, вдохновленным этим кодом, чтобы показывать превью в формате PDF в Angularjs. это мне очень помогло
FireDragon
Спасибо! Вы спасли мою жизнь!
Ренато Соуза де Оливейра
1
@BSSchwarzkopf похоже, что вы правы. URL-адреса BLOB-объектов поддерживаются в Edge, но они не работают в атрибуте src iframe. Я считаю это нарушением спецификации: «Эта схема должна быть в состоянии использоваться с веб-API ... и с элементами, которые предназначены для использования с URL-адресами HTTP ... В общем, эта схема должна быть разработана для использоваться везде, где можно использовать URL-адреса в Интернете ". Проблема с трекером Edge: developer.microsoft.com/en-us/microsoft-edge/platform/issues/… Spec: w3.org/TR/FileAPI/#use-cases-scheme
FellowMD
Я получаю сообщение «Не удалось выполнить createObjectURL на« URL »: не найдено ни одной функции, соответствующей предоставленной подписи». в Chrome 84.0.4147.105.
poiuytrez
3

Оказывается, 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

ТомЭберхард
источник
1
По ссылке Google: «Метод URL.createObjectURL () был удален из интерфейса MediaStream». Относится ли это устаревание, влияющее на интерфейс MediaStream, к другому ответу? (Я думаю, что нет.)
Джаред Тирск
Не устарело. Удалено только из MediaStream
TheMaster
1
@TheMaster - это действительно то, что написано в документации, но я потратил несколько часов, пытаясь заставить его работать, и безуспешно. Невозможно предположить, почему. Код, показанный выше, - это то, что закончилось работать в то время, когда я его закодировал, у меня нет пропускной способности, чтобы попробовать его снова.
TomEberhard
Вы можете использовать этот метод с объектами Blob. В вашем случае это будет примерно такURL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
u.unver34
createObjectURLне рекомендуется использовать только для аргументов MediaStream. Передача Blob-объекта не является устаревшей и фактически имеет довольно широкое и растущее использование . Я ценю усилия, чтобы держать вещи в курсе :)
FellowMD
2

Поскольку ответ @FellowMD не работает в современных браузерах из-за обесценивания createObjectURL, я использовал тот же подход, но с использованием атрибута iframe srcDoc.

  1. Получите контент для отображения в iframe с помощью XMLHttpRequest или любого другого метода
  2. Установите параметр srcdoc для iframe

Пожалуйста, найдите ниже пример 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"
              width="300"
              height="200"
              srcDoc={content}>
      </iframe>


    </div>
  );
}

export default App;

Srcdoc теперь поддерживается большинством браузеров. Похоже, Edge немного запоздал с его реализацией: https://caniuse.com/#feat=iframe-srcdoc

Poiuytrez
источник
createObjectURLне рекомендуется использовать только для аргументов MediaStream. Передача Blob-объекта не является устаревшей и фактически имеет довольно широкое и растущее использование . Я ценю усилия по обновлению информации :)
FellowMD