Чи можна додати заголовки запитів до запиту iframe src?


83

Я розумію, що ви можете дуже легко встановлювати заголовки запитів HTTP під час здійснення викликів AJAX у JavaScript.

Однак чи можливо також встановити власні заголовки запитів HTTP під час вставки iframe на сторінку за допомогою сценарію?

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

Відповіді:


31

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


4
Привіт Ніт, чи можете ви надати зразок коду реалізації в JSFiddle
Naveen Reddy

Я вважаю, що Ніт означає щось на зразок цього stackoverflow.com/a/17695034/1524918
Райан Кара

5
Чи не буде запит у такому сценарії попереднього завантаження надісланий до іншого домену та, таким чином, не порушує Політику того самого походження?
mart1n

Які заголовки надсилаються за замовчуванням? Чи існує якийсь стандарт щодо цього?
Позов Фонду Моніки

74

Ви можете зробити запит у javascript, встановивши будь-які потрібні заголовки. Тоді ви можете URL.createObjectURL(), щоб отримати щось підходяще для 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


Ідеально Працювали бездоганно. Дякую.
mike123

ти людина! Я працюю над компонентом Angular 5, натхненним цим кодом, щоб показати попередній перегляд PDF-файлів у Angularjs. це мені дуже допомогло
FireDragon

Дякую! ти врятував мені життя!
Ренато Соуза де Олівейра

1
@BSSchwarzkopf схоже на те, що ти маєш рацію. URL-адреси BLOB-об'єктів підтримуються в Edge, але вони не працюватимуть в атрибуті src iframe. Я вважаю це порушенням специфікації: "Цю схему слід використовувати з веб-API ... і з елементами, призначеними для використання з HTTP-URL-адресами ... Загалом, ця схема повинна бути розроблена для того, щоб використовувати там, де URL-адреси можна використовувати в Інтернеті ". Випуск на Edge tracker: 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 темний Абсолют та Відмінні відповіді @ 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


createObjectURLне підтримується лише для аргументів MediaStream. Передача BLOB-інформації не є застарілою, і насправді спостерігається досить широке і все більше використання . Я вдячний зусиллям, щоб підтримувати ситуацію в курсі :)
FellowMD
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.