Чи можна додати заголовки запитів до запиту 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.