¿Es posible agregar encabezados de solicitud a una solicitud iframe src?

83

Entiendo que puede configurar los encabezados de solicitud HTTP muy fácilmente al realizar llamadas AJAX en JavaScript.

Sin embargo, ¿también es posible configurar encabezados de solicitud HTTP personalizados al insertar un iframe en una página a través de un script?

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

Respuestas:

31

No, no puedes. Sin embargo, puede configurar la iframefuente para algún tipo de script de precarga, que usa AJAX para recuperar la página real con todos los encabezados que desee.

Niet the Dark Absol
fuente
4
Hola Niet, ¿Puede proporcionar un código de implementación de muestra en JSFiddle
Naveen Reddy
Creo que Niet quiere decir algo como esto stackoverflow.com/a/17695034/1524918
Ryan Kara
5
¿No se enviaría la solicitud en un script de precarga de este tipo a un dominio diferente y, por lo tanto, violaría la Política del mismo origen?
martes
¿Qué encabezados se envían por defecto? ¿Existe algún estándar al respecto?
Financia la demanda de Monica el
74

Puede realizar la solicitud en javascript, configurando los encabezados que desee. Entonces puede URL.createObjectURL(), para obtener algo adecuado para srcel iframe.

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

Se conserva el tipo MIME de la respuesta. Entonces, si obtiene una respuesta html, el html se mostrará en el iframe. Si solicitó un pdf, el visor de pdf del navegador se activará para el iframe.

Si esto es parte de una aplicación del lado del cliente de larga duración, es posible que desee utilizarla URL.revokeObjectURL()para evitar pérdidas de memoria.

Las URL de los objetos también son bastante interesantes. Son de la forma blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. De hecho, puede abrirlos en una nueva pestaña y ver la respuesta, y se descartan cuando se cierra el contexto que los creó.

Aquí hay un ejemplo completo: https://github.com/courajs/pdf-poc

FellowMD
fuente
Perfecto. Funcionó a la perfección. Gracias.
mike123
eres el hombre! Estoy trabajando en un componente Angular 5 inspirado en este código para mostrar vistas previas en PDF en Angularjs. esto me ha ayudado mucho
FireDragon
¡Gracias! ¡me salvaste la vida!
Renato Souza de Oliveira
1
@BSSchwarzkopf parece que tienes razón. Las URL de blob son compatibles con Edge, pero no funcionarán en el atributo src de un iframe. Considero que es una violación de la especificación: "Este esquema debería poder usarse con API web ... y con elementos que están diseñados para usarse con URL HTTP ... En general, este esquema debe diseñarse para utilizarse dondequiera que se puedan utilizar URL en la web ". Problema en el rastreador de Edge: developer.microsoft.com/en-us/microsoft-edge/platform/issues/… Spec: w3.org/TR/FileAPI/#use-cases-scheme
FellowMD
Aparece "No se pudo ejecutar 'createObjectURL' en 'URL': No se encontró ninguna función que coincidiera con la firma proporcionada". en Chrome 84.0.4147.105.
poiuytrez
3

Resulta que URL.createObjectURL () está obsoleto en Chrome 71
(consulte https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems )
Construyendo sobre @Niet the dark Absol y Las excelentes respuestas de @ FellowMD, aquí le mostramos cómo cargar un archivo en un iframe, si necesita pasar encabezados de autenticación. (No puede simplemente establecer el atributo src en la 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>');
            }
        }
    }
}

y un saludo a courajs: https://github.com/courajs/pdf-poc/blob/master/script.js

TomEberhard
fuente
1
Desde el enlace de Google: "El método URL.createObjectURL () se ha eliminado de la interfaz de MediaStream". ¿Esta desaprobación que afecta a la interfaz de MediaStream es relevante para la otra respuesta? (Creo que no.)
Jared Thirsk
No desaprobado. Solo eliminado de MediaStream
TheMaster
1
@TheMaster eso es lo que dice la documentación, pero pasé algunas horas tratando de que funcionara y no tuve éxito. No se puede especular sobre por qué. El código que se muestra arriba es lo que terminó funcionando en el momento en que lo codifiqué, no tengo el ancho de banda para volver a intentarlo.
TomEberhard
Puede usar ese método con objetos Blob. En su caso, sería comoURL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
u.unver34
createObjectURLsolo está en desuso para los argumentos de MediaStream. Pasar un Blob no está en desuso y, de hecho, se ve un uso bastante amplio y creciente . Sin embargo, aprecio el esfuerzo por mantener las cosas actualizadas :)
FellowMD
2

Como la respuesta de @FellowMD no funciona en los navegadores modernos debido a la depreciación de createObjectURL, utilicé el mismo enfoque pero usando el atributo iframe srcDoc.

  1. Recupere el contenido para mostrar en el iframe usando XMLHttpRequest o cualquier otro método
  2. Establecer el parámetro srcdoc del iframe

A continuación, encontrará un ejemplo de React (sé que es excesivo):

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 ahora es compatible con la mayoría de los navegadores. Parece que Edge llegó un poco tarde para implementarlo: https://caniuse.com/#feat=iframe-srcdoc

poiuytrez
fuente
createObjectURLsolo está en desuso para los argumentos de MediaStream. Pasar un Blob no está en desuso y, de hecho, se ve un uso bastante amplio y creciente . Sin embargo, aprecio el esfuerzo por mantener las cosas actualizadas :)
FellowMD