Подтвердить что ты не робот

Определить ошибку загрузки iframe

Я загружаю выбранную пользователем страницу в iframe, используя свойство src. Если загрузка не удалась, я хотел бы сообщить о проблеме в терминах, которые будут иметь смысл для пользователя. iframe не поддерживает, в общем, поддержку onerror согласно http://www.w3schools.com/jsref/dom_obj_frame.asp.

Страница может появляться из домена пользователя, а не моего, поэтому я не могу просмотреть содержимое iframe.

Я могу установить тайм-аут и отменить его из моего обработчика onload, если загрузка будет успешной, но для предотвращения ложных отчетов об ошибках потребуется длительный тайм-аут, а между тем Safari на моем iPhone отображает предупреждение, которое может смутить пользователь. Даже это не работает для браузера Kindle Fire - он передает событие загрузки моему обработчику независимо от того, была ли загрузка успешной.

Есть ли какое-либо событие, которое я могу использовать для обнаружения сбоя? Есть ли способ подавить поведение Safari по умолчанию? В любом случае, я могу сказать, провалилась ли попытка загрузки? (Если бы я мог это сделать, я мог бы использовать более короткий тайм-аут и опрос до тех пор, пока попытка загрузки не будет разрешена).

Я могу потребовать использования современных браузеров, но хотел бы, чтобы решение было переносимым как можно больше смартфонов и планшетов.

Я тестировал идею AJAX Get, и она, к сожалению, не работает. Междоменный AJAX. Получение произвольного URI приводит к исключению, независимо от того, существует ли цель и может быть загружена в iframe или нет.

4b9b3361

Ответ 1

Вы можете настроить запрос iframe и/или ajax, чтобы всегда вызывать страницу, которую вы контролируете (то есть: loader.php), отправляя loader.php запрашиваемую пользователем страницу через get. Из loader.php используйте завиток или даже просто file_get_contents, чтобы получить внешнюю страницу. Если запрос не возвращается на loader.php, вы можете проверить там ошибку и вернуть все, что хотите, чтобы ваш iframe отображался.

Хотя мой пример ссылается на использование php, curl поддерживается на разных языках сценариев. Вероятнее всего, это сложнее, чем другие решения, которые у вас могут быть, но также даст вам доступ к заголовкам ответов, а также для устранения неполадок, связанных с ошибкой загрузки страницы.

Ответ 2

Как вы уже намекали, вы столкнетесь с ограничениями типа политики типа "один-начало" при попытке запросить что-либо внутри iframe, если оно находится в отдельном домене.

Вы можете сделать запрос AJAX GET на URL-адрес iframe, прежде чем передать его в src фрейма. Если вы не получите ответ HTTP 200 от вызова AJAX, тогда сайт также не сможет загружать внутри фрейма.

Это добавит накладные расходы для всего процесса и будет полезна только если вы проверяете, является ли документ iframe реальным URL-адресом, который работает. Это не поможет, если вам нужно знать, когда документ iframe полностью загружен.

Если вам нужно знать, когда загружался iframe, а во внешнем домене, то я считаю, что у вас нет другого выбора, кроме как попросить добавить какой-либо код на эти внешние сайты, чтобы уведомить родительскую страницу о том, успешно загружен.

Или, если имеет смысл это сделать, попросите конечного пользователя щелкнуть ссылку, чтобы отметить, что содержимое не загружается правильно.

Ответ 3

Поздно к вечеринке, но мне удалось ее взломать:

Сначала я решил сделать вызов AJAX, как и все остальные, за исключением того, что он сначала не работал у меня, поскольку я использовал jQuery. Он отлично работает, если вы выполните XMLHttpRequest:

var url = http://url_to_test.com/
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status != 200) {
        console.log("iframe failed to load");
    }
};
xhttp.open("GET", url, true);
xhttp.send();

Edit:
Таким образом, этот метод работает нормально, за исключением того, что он имеет множество ложных негативов (собирает много вещей, которые будут отображаться в iframe) из-за малярии с перекрестным происхождением. Способ, которым я обходился, состоял в том, чтобы сделать CURL/Web-запрос на сервере, а затем проверить заголовки ответов для a), если сайт существует, и b) если заголовки установили x-frame-options.

Это не проблема, если вы запускаете свой собственный веб-сервер, так как вы можете сделать свой собственный api-вызов для него.

Моя реализация в node.js:

app.get('/iframetest',function(req,res){ //Call using /iframetest?url=url - needs to be stripped of http:// or https://
   var url = req.query.url; 
    var request = require('https').request({host: url}, function(response){ //This does an https request - require('http') if you want to do a http request
        var headers = response.headers;
        if (typeof headers["x-frame-options"] != 'undefined') {
            res.send(false); //Headers don't allow iframe
        } else {
            res.send(true); //Headers don't disallow iframe
        }
    });
    request.on('error',function(e){
       res.send(false); //website unavailable
    });
    request.end();
});