jQuery 如果 iframe src 无法加载,则捕获错误。错误:-“拒绝在框架中显示‘http://www.google.co.in/’..”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15273042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 14:42:54  来源:igfitidea点击:

Catch error if iframe src fails to load . Error :-"Refused to display 'http://www.google.co.in/' in a frame.."

jqueryiframeknockout.jssame-origin-policy

提问by Shubh

I am using Knockout.jsto bind iframe srctag(This will be configurable with respect to User).

我正在使用Knockout.js绑定 iframesrc标记(这将可以针对用户进行配置)。

Now, if user has configured http://www.google.com(I know it won't load in iframe, thats why I am using it for -ve scenario) and that has to be shown in IFrame. but it throws error:-

现在,如果用户配置了http://www.google.com(我知道它不会在 iframe 中加载,这就是我将它用于 -ve 场景的原因)并且必须在 IFrame 中显示。但它会引发错误:-

Refused to display 'http://www.google.co.in/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

拒绝在框架中显示“ http://www.google.co.in/”,因为它将“X-Frame-Options”设置为“SAMEORIGIN”。

I have the following code for Iframe:-

我有以下 Iframe 代码:-

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

What I want is, if the URL fails to load. I want to display Custom Message. Screenshot of console when I get errorFIDDLE HERE

我想要的是,如果 URL 无法加载。我想显示自定义消息出现错误时的控制台屏幕截图在这里小提琴

Now, if I use onload and onerror as:-

现在,如果我使用 onload 和 onerror 作为:-

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

It works fine loading w3schools.com but not with google.com.

它可以很好地加载 w3schools.com 但不适用于 google.com。

Secondly:- if I make it as a function and try like I have done in my fiddle, it doesn't works.

其次:-如果我将它作为一个函数并尝试像我在我的小提琴中所做的那样,它不起作用。

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

I don't know how should I make it run and capture the error.

我不知道我应该如何让它运行并捕获错误。

Edited:- I have seen Want to call a function if iframe doesn't load or load'squestion in stackoverflow but it shows error for sites that can be loaded in iframe.

编辑:- 我已经看到想要调用一个函数,如果 iframe 没有加载或加载stackoverflow 中问题,但它显示可以在 iframe 中加载的站点的错误。

Also, I have looked into Stackoverflow iframe on load eventThanks!!

另外,我在加载事件上查看了Stackoverflow iframe谢谢!

采纳答案by Evan Larsen

You wont be able to do this from the client side because of the Same Origin Policyset by the browsers. You wont be able to get much information from the iFrame other than basic properties like its width and height.

由于浏览器设置的同源策略,您将无法从客户端执行此操作。除了宽度和高度等基本属性之外,您将无法从 iFrame 中获得太多信息。

Also, google sets in its response header an 'X-Frame-Options' of SAMEORIGIN.

此外,谷歌在其响应头中设置了 SAMEORIGIN的“ X-Frame-Options”。

Even if you did an ajax call to google you wont be able to inspect the response because the browser enforcing Same Origin Policy.

即使您对 google 进行了 ajax 调用,您也无法检查响应,因为浏览器执行同源策略。

So, the only option is to make the request from your server to see if you can display the site in your IFrame.

因此,唯一的选择是从您的服务器发出请求,以查看您是否可以在 IFrame 中显示该站点。

So, on your server.. your web app would make a request to www.google.com and then inspect the response to see if it has a header argument of X-Frame-Options. If it does exist then you know the IFrame will error.

因此,在您的服务器上.. 您的网络应用程序将向 www.google.com 发出请求,然后检查响应以查看它是否具有 X-Frame-Options 的标头参数。如果它确实存在,那么您知道 IFrame 会出错。

回答by Irvin Dominin

I think that you can bind the loadevent of the iframe, the event fires when the iframe content is fully loaded.

我认为您可以绑定loadiframe 的事件,当 iframe 内容完全加载时会触发该事件。

At the same time you can start a setTimeout, if the iFrame is loaded clear the timeout alternatively let the timeout fire.

同时你可以启动一个setTimeout,如果加载了iFrame,清除超时或者让超时触发。

Code:

代码:

var iframeError;

function change() {
    var url = $("#addr").val();
    $("#browse").attr("src", url);
    iframeError = setTimeout(error, 5000);
}

function load(e) {
    alert(e);
}

function error() {
    alert('error');
}

$(document).ready(function () {
    $('#browse').on('load', (function () {
        load('ok');
        clearTimeout(iframeError);
    }));

});

Demo: http://jsfiddle.net/IrvinDominin/QXc6P/

演示:http: //jsfiddle.net/IrvinDominin/QXc6P/

Second problem

第二个问题

It is because you miss the parens in the inline function call; try change this:

这是因为您错过了内联函数调用中的括号;尝试改变这个:

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

into this:

进入这个:

<iframe id="browse" style="width:100%;height:100%" onload="load('Done func');" onerror="error('failed function');"></iframe>

Demo: http://jsfiddle.net/IrvinDominin/ALBXR/4/

演示:http: //jsfiddle.net/IrvinDominin/ALBXR/4/

回答by H.Eden

The onload will always be trigger, i slove this problem use try catch block.It will throw an exception when you try to get the contentDocument.

onload 将始终被触发,我很喜欢这个问题,使用 try catch 块。当您尝试获取 contentDocument 时,它会抛出异常。

iframe.onload = function(){
   var that = $(this)[0];
   try{
        that.contentDocument;
   }
   catch(err){
        //TODO 
   }
}

回答by user2677034

This is a slight modification to Edens answer - which for me in chrome didn't catch the error. Although you'll still get an error in the console: "Refused to display 'https://www.google.ca/' in a frame because it set 'X-Frame-Options' to 'sameorigin'." At least this will catch the error message and then you can deal with it.

这是对伊登斯答案的轻微修改 - 对我来说,chrome 没有发现错误。尽管您仍会在控制台中收到错误消息:“拒绝在框架中显示‘ https://www.google.ca/’,因为它将‘X-​​Frame-Options’设置为‘sameorigin’。” 至少这将捕获错误消息,然后您可以处理它。

 <iframe id="myframe" src="https://google.ca"></iframe>

 <script>
 myframe.onload = function(){
 var that = document.getElementById('myframe');

 try{
    (that.contentWindow||that.contentDocument).location.href;
 }
 catch(err){
    //err:SecurityError: Blocked a frame with origin "http://*********" from accessing a cross-origin frame.
    console.log('err:'+err);
}
}
</script>

回答by viresh

I faced similar problem. I solved it without using onload handler.I was working on AngularJs project so i used $interval and $ timeout. U can also use setTimeout and setInterval.Here's the code:

我遇到了类似的问题。我在不使用 onload 处理程序的情况下解决了它。我正在处理 AngularJs 项目,所以我使用了 $interval 和 $ timeout。你也可以使用 setTimeout 和 setInterval。代码如下:

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

Every 0.4 Seconds keep checking the head of iFrame Document. I somthing is present.Loading was not stopped by CORS as CORS error shows blank page. If nothing is present after 5 seconds there was some error (Cors policy) etc.. Show suitable message.Thanks. I hope it solves your problem.

每 0.4 秒不断检查 iFrame 文档的头部。我有一些东西。加载没有被 CORS 停止,因为 CORS 错误显示空白页。如果 5 秒后没有任何内容,则出现一些错误(Cors 政策)等。显示合适的消息。谢谢。我希望它能解决你的问题。

回答by Engin Morse

I have the same problem, chrome can't fire onerror when iframe src load error.

我有同样的问题,当 iframe src 加载错误时,chrome 无法触发 onerror。

but in my case, I just need make a cross domain http request, so I use script src/onload/onerror instead of iframe. it's working well.

但就我而言,我只需要发出跨域 http 请求,所以我使用脚本 src/onload/onerror 而不是 iframe。它运行良好。

回答by lwdthe1

As explained in the accepted answer, https://stackoverflow.com/a/18665488/4038790, you need to check via a server.

如已接受的答案https://stackoverflow.com/a/18665488/4038790 中所述,您需要通过服务器进行检查。

Because there's no reliable way to check this in the browser, I suggest you build yourself a quick server endpoint that you can use to check if any url is loadable via iframe. Once your server is up and running, just send a AJAX request to it to check any url by providing the url in the query string as url(or whatever your server desires). Here's the server code in NodeJs:

因为在浏览器中没有可靠的方法来检查这个,我建议你自己建立一个快速的服务器端点,你可以用它来检查是否有任何 url 可以通过 iframe 加载。一旦您的服务器启动并运行,只需向它发送 AJAX 请求以通过在查询字符串中提供 url url(或您的服务器所需的任何内容)来检查任何 url 。这是 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)

回答by Qeemerc

I solved it with window.length. But with this solution you can take current error (X-Frame or 404).

我用window.length. 但是使用此解决方案,您可以获取当前错误(X-Frame 或 404)。

iframe.onload = event => {
   const isLoaded = event.target.contentWindow.window.length // 0 or 1
}

MSDN

MSDN