iframe src가로드에 실패하면 오류를 포착합니다. 오류 :-“프레임에 'http://www.google.co.in/'표시를 거부했습니다 ..”


79

Knockout.jsiframe src태그 를 바인딩 하는 데 사용 하고 있습니다 (사용자와 관련하여 구성 할 수 있음).

이제 사용자가 http://www.google.com 을 구성한 경우 (iframe에서로드되지 않는다는 것을 알고 있으므로 -ve 시나리오에 사용하고 있습니다) IFrame에 표시되어야합니다. 하지만 오류가 발생합니다.

'X-Frame-Options'를 'SAMEORIGIN'으로 설정했기 때문에 프레임에 ' http://www.google.co.in/ ' 을 표시하는 것을 거부했습니다 .

Iframe에 대한 다음 코드가 있습니다.

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

내가 원하는 것은 URL이로드되지 않는 경우입니다. 사용자 지정 메시지 를 표시하고 싶습니다 . 오류 발생시 콘솔 스크린 샷 여기에 FIDDLE

이제 onload 및 onerror를 다음과 같이 사용하면

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

w3schools.com로드는 잘 작동하지만 google.com에서는 작동하지 않습니다.

둘째 :-내가 그것을 함수로 만들고 바이올린에서했던 것처럼 시도하면 작동하지 않습니다.

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

어떻게 실행하고 오류를 캡처해야하는지 모르겠습니다.

편집 됨 : -iframe이 stackoverflow 에서 질문을 로드하거나로드하지 않는 경우 함수를 호출하고 싶지만 iframe에로드 할 수있는 사이트에 대한 오류 가 표시되는 것을 보았습니다 .

또한 로드 이벤트시 Stackoverflow iframe을 살펴 보았습니다. 감사합니다 !!

답변:


44

브라우저에서 설정 한 동일한 원본 정책으로 인해 클라이언트 측에서이 작업을 수행 할 수 없습니다 . 너비 및 높이와 같은 기본 속성 외에는 iFrame에서 많은 정보를 얻을 수 없습니다.

또한 Google은 응답 헤더 에 SAMEORIGIN 의 ' X-Frame-Options '를 설정합니다.

Google에 ajax 호출을하더라도 브라우저가 동일한 출처 정책을 시행하기 때문에 응답을 검사 할 수 없습니다.

따라서 유일한 옵션은 IFrame에 사이트를 표시 할 수 있는지 확인하기 위해 서버에서 요청하는 것입니다.

따라서 서버에서 웹 앱은 www.google.com에 요청한 다음 응답을 검사하여 X-Frame-Options의 헤더 인수가 있는지 확인합니다. 존재하는 경우 IFrame에서 오류가 발생한다는 것을 알 수 있습니다.


Roblox는 사용자 지정 URI 처리기 iframe를 감지하여 게임이 설치되었는지 감지 하는 트릭을 사용 <iframe src="roblox-player:foo">합니다. 이 iframe오류를 감지 하면 "다운로드"버튼이 표시됩니다. 그러면 그들은 어떻게합니까?
tresf

1
@QZ 지원 당신이 무슨 말을하는지 모르겠습니다.
에반 라슨

1
@EvanLarsen 저는이 <iframe>기술을 성공적으로 사용 하여 OS에 등록 된 URI 핸들러를 실행하는 (그리고 감지하길 바랬던) 매우 인기있는 비디오 게임을 언급하고 있습니다. 무료 게임이므로 설치하여 직접 확인할 수 있습니다. 브라우저를 통해 게임에 참여하면 iframe 해킹을 사용하여 게임을 시작합니다. 실패하면 "다운로드"버튼이 표시됩니다. 어떻게 든 그들은 URI가 제대로 처리되었는지 여부를 알고 있습니다. 내 초기 추측은 iframe오류를 포착 했지만 답변 (내 테스트뿐만 아니라)은 불가능하다는 것을 암시하는 것 같습니다. iframe이 실패하면 어떻게 알 수 있습니까?
tresf

이것은 추측 일 뿐이지 만 웹 사이트는 로컬 컴퓨터에서 자체 호스팅 웹 앱을 호출하는 것입니다. 호출이 실패하면 다운로드 버튼이 표시됩니다. 컴퓨터에 게임을 다운로드하고 설치하면 웹 사이트에서 로컬 자체 호스팅 웹 앱을 호출 할 수 있습니다. 자체 호스팅 웹 앱으로 .. 나는 그것에 대해 알고있는 모든 웹 사이트에서 호출 할 수있는 http 엔드 포인트가있는 앱을 의미합니다. (예. 로컬 호스트 : 7845 / opengame / 방 / 2534 )
에반 라슨

이것은 localhost:7845상당히 가정입니다. 첫째, 혼합 콘텐츠 경고 / 오류 (roblox.com은 HTTPS 사용)가 발생하고 다음으로 충돌시 장애 조치 포트가 필요합니다. 소프트웨어를 시작하는 데 사용되는 기술은 iframe. 이것은 페이지 소스를 조사하여 관찰 할 수 있습니다. 어떻게 든 이것이 소프트웨어를 시작하지 못하면 그것을 감지 할 수 있습니다. 이것은 브라우저 추적기 ID를 사용하여 "phone home"+ 시간 제한 방법을 통해 수행 할 수 있습니다. 이 iframe실패 감지는 관련 앱을 시작하는 데 유용하지만 실패를 감지 할 수있는 경우에만 이를 언급합니다 .
tresf

15

loadiframe 의 이벤트를 바인딩 할 수 있다고 생각합니다 . iframe 콘텐츠가 완전히로드되면 이벤트가 발생합니다.

동시에 setTimeout을 시작할 수 있습니다. iFrame이로드되면 시간 제한을 지우거나 시간 제한이 실행되도록합니다.

암호:

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

});

데모 : http://jsfiddle.net/IrvinDominin/QXc6P/

두 번째 문제

인라인 함수 호출에서 괄호를 놓치기 때문입니다. 이것을 변경하십시오 :

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

이것으로 :

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

데모 : http://jsfiddle.net/IrvinDominin/ALBXR/4/


51
이봐, 그냥 바이올린을 봤어-절대로 오류를 던지지 않아.
vvohra87 2013 년

12
나는 Ubuntu와 Chrome을 사용하고 있습니다. 텍스트 상자에 어떤 URL을 넣어도 "done"및 "done func"라고 표시됩니다. :(
vvohra87

3
@IrvinDomininakaEdward : 두 바이올린 링크가 작동하지 않습니다 ... 열리지 않습니다 ... 바이올린을 삭제 했습니까?
Hitesh 2014 년

10
마이너스 1 왜냐하면 위의 주석 상태 : iframe이로드되지 않을 때 바이올린이 예상 된 오류 메시지를 던지지 않기 때문입니다. 콘텐츠를로드하지 않아도 iframe의로드 이벤트가 발생하기 때문입니다.
CodeToad

3
이것은 선택된 답변이 아니어야합니다. 아래의 Evan이 올바입니다. 브라우저 보안이이를 감지하지 못하도록합니다.
스콧 스미스

9

onload는 항상 트리거되며,이 문제는 try catch 블록을 사용하여 해결합니다. contentDocument를 가져 오려고 할 때 예외가 발생합니다.

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

1
이것은 내가 지금까지 본 가장 간단한 방법이며 실제로 작동합니다!
Simon Jackson

15
이것은 또한 크로스 도메인에 대해 작동하지 않습니다 - 그것은 오류 어느 쪽이든 던질거야
Luoruize

이것은 내 도메인의 iframe에서 나를 위해 일했습니다. X-프레임 - 옵션 : SAMEORIGIN
라이언

나에게는 iframe이 콘텐츠를로드하더라도 동일한 예외가 발생합니다. 콘텐츠가로드되지 않았는지 어떻게 알 수 있습니까?
leeCoder 2014

나는 이런 방식으로 그 오류를 잡을 수 있다고 대답하려고했다! 하지만 당신은 이미했습니다! 나는 이런 방식으로 똑같은 정확한 문제를 처리하고 있습니다 (또한 사용자가 내 도메인의 특정 페이지로 리디렉션되었는지 확인하기 위해)! "iframe에서 오류 처리"를 검색하는이 질문을 발견했지만 이제 iframe 내부에서 503 오류가 발생했습니다!
Sampgun

8

이것은 Edens 답변에 대한 약간의 수정입니다-크롬에서 나를 위해 오류를 포착하지 못했습니다. 콘솔에 여전히 오류가 표시되지만 " 'X-Frame-Options'를 'sameorigin'으로 설정했기 때문에 프레임에 ' https://www.google.ca/ ' 를 표시하는 것을 거부했습니다 ." 적어도 이것은 오류 메시지를 포착하고 처리 할 수 ​​있습니다.

 <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>

이로 인해 "null의 '위치'속성을 읽을 수 없음"오류가 발생 that.contentDocument하고 많은 작업 사이트 that.contentWindow에서로드 프로세스 중에 오류가 계속 발생 합니다.
Abandoned Cart

1

비슷한 문제에 직면했습니다. 나는 onload 핸들러를 사용하지 않고 해결했고 AngularJs 프로젝트에서 일하고 있었기 때문에 $ interval과 $ timeout을 사용했습니다. U는 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);
 });

0.4 초마다 iFrame 문서의 헤드를 계속 확인합니다. I somthing is present. CORS 오류가 빈 페이지를 표시하므로 CORS에 의해로드가 중지되지 않았습니다. 5 초 후에도 아무것도 없으면 오류 (Cors 정책) 등이 있습니다. 적절한 메시지를 표시합니다. 감사합니다. 문제가 해결되기를 바랍니다.


2
Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "..." from accessing a cross-origin frame.-교차 도메인에서 작동하고 있습니까?
Mars Robertson

0

나는 같은 문제가 있는데, iframe src로드 오류가 발생하면 크롬이 onerror를 실행할 수 없습니다.

하지만 제 경우에는 도메인 간 http 요청 만하면되므로 iframe 대신 src / onload / onerror 스크립트를 사용합니다. 잘 작동하고 있습니다.


0

나는 그것을 window.length. 그러나이 솔루션을 사용하면 현재 오류 (X-Frame 또는 404)를 사용할 수 있습니다.

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

MSDN


0

수락 된 답변에서 설명했듯이 https://stackoverflow.com/a/18665488/4038790 서버를 통해 확인해야합니다.

브라우저에서이를 확인할 수있는 신뢰할 수있는 방법이 없기 때문에 iframe을 통해 URL을로드 할 수 있는지 확인하는 데 사용할 수있는 빠른 서버 엔드 포인트를 직접 구축하는 것이 좋습니다. 서버가 가동되고 실행되면 AJAX 요청을 보내어 쿼리 문자열에 URL을 제공하여 URL을 확인하십시오 url(또는 서버가 원하는대로). 다음은 NodeJ의 서버 코드입니다.

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)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.