86 votes

Attrape l'erreur si la src de l'iframe ne se charge pas . Erreur :-"Refus d'afficher 'http://www.google.co.in/' dans un cadre.."

J'utilise Knockout.js pour lier l'iframe src tag (configurable en fonction de l'utilisateur).

Maintenant, si l'utilisateur a configuré http://www.google.com (Je sais qu'il ne se chargera pas dans une iframe, c'est pourquoi je l'utilise pour le scénario -ve) et cela doit être affiché dans une IFrame. mais il y a une erreur :-)

Refus d'affichage ' http://www.google.co.in/ dans un cadre parce qu'il a défini 'X-Frame-Options' à 'SAMEORIGIN'.

J'ai le code suivant pour l'Iframe :-)

<iframe class="iframe" id="iframe" data-bind="attr: {src: externalAppUrl, height: iframeheight}">
    <p>Hi, This website does not supports IFrame</p>
</iframe>

Ce que je veux, c'est que si l'URL ne se charge pas. Je veux afficher Message personnalisé . Screenshot of console when I get errorFIDDLE ICI

Maintenant, si j'utilise onload et onerror comme:-

<iframe id="browse" style="width:100%;height:100%" onload="alert('Done')" onerror="alert('Failed')"></iframe>

Le chargement de w3schools.com fonctionne bien, mais pas celui de google.com.

Deuxièmement, si j'en fais une fonction et que j'essaie comme je l'ai fait dans mon fiddle, cela ne fonctionne pas.

<iframe id="browse" style="width:100%;height:100%" onload="load" onerror="error"></iframe>

Je ne sais pas comment le faire fonctionner et capturer l'erreur.

Édité:- J'ai vu Vous voulez appeler une fonction si l'iframe ne se charge pas ou se charge question dans stackoverflow mais il montre une erreur pour les sites qui peuvent être chargés dans iframe.

J'ai également examiné Iframe de Stackoverflow sur l'événement de chargement Merci !

3voto

Palash Bansal Points 97

Mise à jour : contentWindow.name génère désormais toujours une erreur sur les cadres inter-origines. Il semble que la seule solution soit de faire cela côté serveur (pour l'instant). J'ai écrit un petit worker cloudflare pour capturer les en-têtes pour les apis distantes et il peut être utilisé ici pour vérifier les X-Frame-Options.

Exemple de code à vérifier avant le rendu dans une iframe : (jsfiddle : https://jsfiddle.net/2gud39aw/2/ )

function checkUrlFrameOptions(apiurl){
  return fetch("https://header-inspector.repalash.workers.dev/?" + new URLSearchParams({
    'apiurl': apiurl,
    'headers': 'x-frame-options'
  }), {
    method: 'GET'
  }).then(r => r.json()).then(json => {
    let xFrameOp = (json.headers['x-frame-options'] || '').toLowerCase();
    // deny all requests
    if(xFrameOp==='deny') return false;
    // deny if different origin
    if(xFrameOp==='sameorigin' && json.origin !== location.origin) return false;
    return true;
  })
}

checkUrlFrameOptions("https://google.com").then((res)=>console.log("google.com can be loaded in iframe: ", res))
checkUrlFrameOptions("https://example.com").then((res)=>console.log("example.com can be loaded in iframe: ", res))

Le point de terminaison de cloudflare worker ( https://header-inspector.repalash.workers.dev ) est juste pour les tests, ne l'utilisez pas en production. Le code est disponible à l'adresse suivante : https://gist.github.com/repalash/b1e778dbe3ac2e7149831c530a6535f9 et peut être déployé directement en tant que travailleur cloudflare

Réponse OLD

Voici une solution simple, testée sur Chrome et Safari.

    const iframe = document.createElement('iframe')
    iframe.onload = function() {
        try {
            iframe.contentWindow.name
        } catch (e) {
            if (e.message.includes('cross-origin')) console.warn(e.message);
            else console.error(e.message);
        }
    }

    iframe.src = "https://google.com";

Démonstration de jsFiddle : https://jsfiddle.net/k5e1mg3t/5/

2voto

viresh Points 51

J'ai rencontré le même problème. J'ai résolu le problème sans utiliser le gestionnaire onload. Je travaillais sur un projet AngularJs et j'ai donc utilisé $interval et $timeout. Vous pouvez également utiliser setTimeout et setInterval.Voici le code :

 var stopPolling;
 var doIframePolling;
 $scope.showIframe = true;
 doIframePolling = $interval(function () {
    if(document.getElementById('UrlIframe') && document.getElementById('UrlIframe').contentDocument.head && document.getElementById('UrlIframe').contentDocument.head.innerHTML != ''){
        $interval.cancel(doIframePolling);
        doIframePolling = undefined;
        $timeout.cancel(stopPolling);
        stopPolling = undefined;
        $scope.showIframe = true;
    }
},400);

stopPolling = $timeout(function () {
        $interval.cancel(doIframePolling);
        doIframePolling = undefined;
        $timeout.cancel(stopPolling);
        stopPolling = undefined;
        $scope.showIframe = false;     
},5000);

 $scope.$on("$destroy",function() {
        $timeout.cancel(stopPolling);
        $interval.cancel(doIframePolling);
 });

Toutes les 0,4 secondes, il vérifie l'en-tête du document iFrame. Si quelque chose est présent, le chargement n'a pas été stoppé par CORS car l'erreur CORS affiche une page blanche. Si rien n'est présent après 5 secondes, c'est qu'il y a eu une erreur (politique CORS), etc. Affichez le message approprié. J'espère que cela résoudra votre problème.

0voto

Engin Morse Points 31

J'ai le même problème, chrome ne peut pas déclencher onerror quand l'iframe src load error.

mais dans mon cas, j'ai juste besoin de faire une requête http inter-domaine, j'utilise donc script src/onload/onerror au lieu d'iframe. Cela fonctionne bien.

0voto

lwdthe1 Points 396

Comme expliqué dans la réponse acceptée, https://stackoverflow.com/a/18665488/4038790 vous devez vérifier par l'intermédiaire d'un serveur.

Comme il n'y a pas de moyen fiable de vérifier cela dans le navigateur, je vous suggère de créer un point de terminaison serveur rapide que vous pouvez utiliser pour vérifier si une url est chargeable via une iframe. Une fois que votre serveur est opérationnel, envoyez-lui une requête AJAX pour vérifier n'importe quelle url en fournissant l'url dans la chaîne de requête sous la forme de url (ou tout ce que votre serveur désire). Voici le code du serveur en NodeJs :

const express = require('express')
const app = express()

app.get('/checkCanLoadIframeUrl', (req, res) => {
  const request = require('request')
  const Q = require('q')

  return Q.Promise((resolve) => {
    const url = decodeURIComponent(req.query.url)

    const deafultTimeout = setTimeout(() => {
      // Default to false if no response after 10 seconds
      resolve(false)
    }, 10000)

    request({
        url,
        jar: true /** Maintain cookies through redirects */
      })
      .on('response', (remoteRes) => {
        const opts = (remoteRes.headers['x-frame-options'] || '').toLowerCase()
        resolve(!opts || (opts !== 'deny' && opts !== 'sameorigin'))
        clearTimeout(deafultTimeout)
      })
      .on('error', function() {
        resolve(false)
        clearTimeout(deafultTimeout)
      })
  }).then((result) => {
    return res.status(200).json(!!result)
  })
})

app.listen(process.env.PORT || 3100)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X