Ist es möglich, einer iframe src-Anfrage Anforderungsheader hinzuzufügen?

80

Ich verstehe, dass Sie HTTP-Anforderungsheader sehr einfach festlegen können, wenn Sie AJAX-Aufrufe in JavaScript ausführen.

Ist es jedoch auch möglich, benutzerdefinierte HTTP-Anforderungsheader festzulegen, wenn ein Iframe per Skript in eine Seite eingefügt wird?

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

Antworten:

30

Nein, das kannst du nicht. Sie können die iframeQuelle jedoch auf eine Art Preload-Skript einstellen , das AJAX verwendet, um die eigentliche Seite mit allen gewünschten Headern abzurufen.

Niet the Dark Absol
quelle
4
Hallo Niet, können Sie bitte Beispiel Implementierungscode in JSFiddle
Naveen Reddy
Ich glaube, Niet bedeutet so etwas wie stackoverflow.com/a/17695034/1524918
Ryan Kara
5
Würde die Anforderung in einem solchen Preload-Skript nicht an eine andere Domain gesendet und damit gegen die Same Origin-Richtlinie verstoßen?
Mart1n
Welche Header werden standardmäßig gesendet? Gibt es einen Standard dafür?
Fund Monica Klage
70

Sie können die Anfrage in Javascript stellen und beliebige Header festlegen. Dann können Sie URL.createObjectURL()etwas Passendes für srcden Iframe bekommen.

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 :(');
    }
  }
}

Der MIME-Typ der Antwort bleibt erhalten. Wenn Sie also eine HTML-Antwort erhalten, wird das HTML im Iframe angezeigt. Wenn Sie ein PDF angefordert haben, wird der PDF-Viewer des Browsers für den Iframe aktiviert.

Wenn dies Teil einer langlebigen clientseitigen App ist, möchten Sie diese möglicherweise verwenden URL.revokeObjectURL() Speicherlecks vermeiden.

Die Objekt-URLs sind auch ziemlich interessant. Sie sind von der Form blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. Sie können sie tatsächlich in einem neuen Tab öffnen und die Antwort anzeigen. Sie werden verworfen, wenn der Kontext, in dem sie erstellt wurden, geschlossen wird.

Hier ist ein vollständiges Beispiel: https://github.com/courajs/pdf-poc

FellowMD
quelle
Perfekt. Hat einwandfrei funktioniert. Vielen Dank.
Mike123
du der Mann! Ich arbeite an einer Angular 5-Komponente, die von diesem Code inspiriert ist, um PDF-Vorschauen in Angularjs anzuzeigen. Das hat mir sehr geholfen
FireDragon
Vielen Dank! du hast mein Leben gerettet!
Renato Souza de Oliveira
1
@BSSchwarzkopf sieht so aus, als hättest du recht. Blob-URLs werden in Edge unterstützt, funktionieren jedoch nicht im src-Attribut eines Iframes. Ich halte es für einen Verstoß gegen die Spezifikation: "Dieses Schema sollte mit Web-APIs verwendet werden können ... und mit Elementen, die für die Verwendung mit HTTP-URLs ausgelegt sind ... Im Allgemeinen sollte dieses Schema so ausgelegt sein überall dort verwendet werden, wo URLs im Web verwendet werden können. " Problem auf dem Edge-Tracker: developer.microsoft.com/en-us/microsoft-edge/platform/issues/… Spec: w3.org/TR/FileAPI/#use-cases-scheme
FellowMD
Ich erhalte die Meldung "'createObjectURL' für 'URL' konnte nicht ausgeführt werden: Es wurde keine Funktion gefunden, die mit der angegebenen Signatur übereinstimmt." auf Chrome 84.0.4147.105.
Poiuytrez
2

Es stellt sich heraus , dass URL.createObjectURL () in Chrome ist veraltet 71
(siehe https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems )
Aufbauend auf @Niet die dunkle Absol und In den hervorragenden Antworten von @ FellowMD erfahren Sie, wie Sie eine Datei in einen Iframe laden, wenn Sie Authentifizierungsheader übergeben müssen. (Sie können das src-Attribut nicht einfach auf die URL setzen):

$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>');
            }
        }
    }
}

und rufen Sie Courajs an: https://github.com/courajs/pdf-poc/blob/master/script.js

TomEberhard
quelle
1
Über den Google-Link: "Die URL.createObjectURL () -Methode wurde aus der MediaStream-Oberfläche entfernt." Ist diese Ablehnung, die sich auf die MediaStream-Oberfläche auswirkt, für die andere Antwort relevant? (Ich würde nicht denken.)
Jared Thirsk
Nicht veraltet. Nur aus MediaStream
TheMaster
1
@TheMaster, das steht in der Tat in der Dokumentation, aber ich habe ein paar Stunden damit verbracht, es zum Laufen zu bringen, und war nicht erfolgreich. Es kann nicht darüber spekulieren, warum. Der oben gezeigte Code hat zu dem Zeitpunkt funktioniert, als ich ihn codiert habe. Ich habe nicht die Bandbreite, um ihn erneut zu versuchen.
TomEberhard
Sie können diese Methode mit Blob-Objekten verwenden. In Ihrem Fall wäre das wieURL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
u.unver34
createObjectURLwird nur für MediaStream-Argumente veraltet. Das Übergeben eines Blobs ist nicht veraltet und wird in der Tat ziemlich häufig und zunehmend genutzt . Ich schätze die Mühe, die Dinge auf dem neuesten Stand zu halten :)
FellowMD
1

Da die @ FellMD-Antwort in modernen Browsern aufgrund der Abwertung von createObjectURL nicht funktioniert, habe ich denselben Ansatz verwendet, jedoch das Attribut iframe srcDoc verwendet.

  1. Rufen Sie den im iframe anzuzeigenden Inhalt mit XMLHttpRequest oder einer anderen Methode ab
  2. Legen Sie den Parameter srcdoc des Iframes fest

Nachfolgend finden Sie ein Reaktionsbeispiel (ich weiß, dass es übertrieben ist):

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 wird jetzt in den meisten Browsern unterstützt. Es scheint, dass Edge etwas spät dran war, es zu implementieren: https://caniuse.com/#feat=iframe-srcdoc

poiuytrez
quelle
createObjectURLwird nur für MediaStream-Argumente veraltet. Das Übergeben eines Blobs ist nicht veraltet und wird in der Tat ziemlich häufig und zunehmend genutzt . Ich schätze die Bemühungen, die Dinge auf dem neuesten Stand zu halten :)
FellowMD