JavaScript: перехват всех http/https запросов страницы
Прилетела задача перехватить URL всех загрузок тайлов на странице с размещенной Яндекс картой. В принципе если бы был простой случай, то всё решилось бы созданием прототипа для функции XMLHttpRequest , что-то в духе:
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, uri, async, user, pass) {
this.addEventListener("readystatechange", function(event) {
if(this.readyState == 4){
var self = this;
var response = {
method: method,
uri: uri,
responseText: self.responseText
};
console.log(response);
} else {
console.log(this.readyState);
}
}, false);
open.call(this, method, uri, async, user, pass);
};
Но возник один нюанс, карта располагается в iframe, а прототипы «вниз» не распространяются. Единственным способом осталось написать сервис Service Worker, который будет отлавливать все запросы..
На странице добавляем функцию загрузки сервиса:
<script>
console.log("пробуем зарегистрировать Service Worker");
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js',{}).then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
Далее в sw.js добавим слушательсобытия fetch, и реализацию отправки перехваченых url на сервер:
self.addEventListener('install', (event) => {
console.log('Установлен');
});
self.addEventListener('activate', (event) => {
console.log('Активирован');
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
console.log('Запрашиваем URL: '+event.request.url);
postData("woodpecker.php", { "url": event.request.url}).then((data) => {
console.log(data);
});
});
async function postData(url = "", data = {}) {
console.log("-отправляем в "+url);
// Default options are marked with *
const response = await fetch(url, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: "data="+JSON.stringify(data), // body data type must match "Content-Type" header
});
return await response.json(); // parses JSON response into native JavaScript objects
}
Серверная часть woodpecker.php:
<?php
$body= json_decode($_POST["data"]);
if ($body->url!=""){
file_put_contents("urls.txt",$body->url."\n",FILE_APPEND);
}
$answer=new stdClass();
$answer->error=false;
$answer->result="ok";
echo json_encode($answer);
die();
В результате в файл url.txt на сервере пишутся все запрошенные url.
Отладка сервиса в FireFox возможна на вкладке about:debugging#/runtime/this-firefox, ищем там свой сервис, нажимаем «исследовать»
