Chrome拡張機能でリクエストヘッダrefererの書き換え
Chrome拡張機能で content script や background スクリプト内でのajaxリクエスト時にリクエストヘッダ(今回はリファラreferer
)を書き換える方法をメモしておきます。
目次
前提
- Chrome 75.0.3770.100(Official Build) (64 ビット)
manifest.jsonの設定
manifest.json
{
"permissions": [
"<all_urls>",
"webRequest",
"webRequestBlocking",
...
],
...
"background": {
"scripts": [
"jquery.js",
"background.js",
...
],
"persistent": true
},
...
}
manifest設定箇所:
permissions
- ヘッダ書き換え処理を発動させたいURLを追加。上記例では
<all_urls>
を指定して全てのURLをインターセプト。 "webRequest"
を追加。"webRequestBlocking"
を追加。
- ヘッダ書き換え処理を発動させたいURLを追加。上記例では
background
"persistent": true
を指定。
background.scripts
で"jquery.js"
をロードしています。これは後ほどbackground.js内で$.ajax()
するためです。webRequestの設定自体には関係ありません。
サンプルコード
以下コードを実行すると、ajaxリクエストが投げられる直前のタイミングでリクエストヘッダreferer
の値が"http://example.com/"
に書き換えられます。
background.js
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
// 2) $.ajax()が実行され、リクエストが投げられる直前にここに来る。ここでリクエストヘッダを書き換え可能。
// refererを "http://example.com/" に書き換え:
putReqHeader(details, "referer", "http://example.com/");
return {
requestHeaders: details.requestHeaders,
};
}, {
urls: ["<all_urls>"], // 全URLをインターセプト
}, [
"requestHeaders",
"extraHeaders",
"blocking"
]);
// 1) ローカルのWebサーバにajaxリクエストを実行してみる:
$.ajax({ url: "http://127.0.0.1:3000/" }).done((msg) => {
console.log("ajax done!");
});
/** details.requestHeaders内のリクエストヘッダを更新する関数 */
function putReqHeader(details, key, val) {
key = key.toLowerCase();
for (let n in details.requestHeaders) {
const got = details.requestHeaders[n].name.toLowerCase() == key;
if (got) {
details.requestHeaders[n].value = val;
return;
}
}
details.requestHeaders.push({
name: key,
value: val,
});
}
コードレビュー
background.js内でchrome.webRequest.onBeforeSendHeaders.addListener()
を記述することで、リクエストヘッダが送信される直前のリクエストヘッダを弄ることができます。
chrome.webRequest.onBeforeSendHeaders.addListener()
の説明:
- 第一引数には
details.requestHeaders
の書き換え処理 - 第二引数には
urls
にインターセプトしたいURLを指定 - 第三引数には
["requestHeaders", "extraHeaders", "blocking"]
を指定 (※)
※"extraHeaders"
の明示的指定
Chrome 72 からは、以下のリクエストヘッダを書き換えるためには"extraHeaders"
を明示的に指定しなければなりません:
- Accept-Language
- Accept-Encoding
- Referer
- Cookie
NOTE:上記例では background.js 内でajaxリクエストを行っていますが、content script内からのajaxリクエストでも同様にリクエストヘッダが書き換わります。
テスト
リクエストヘッダを表示するだけの簡易Webサーバを作り、先ほどのChrome拡張機能がリクエストヘッダを書き換えられているか確かめてみましょう。簡易WebサーバはNode.jsでサクッと書いてみます。
server.js (簡易Webサーバ)
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
console.log("req.headers:", req.headers); // ここでリクエストヘッダをデバッグ出力
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
簡易Webサーバを起動し、先ほどのChrome拡張機能を実行してみます:
$ node server.js
Server running at http://127.0.0.1:3000/
req.headers: { host: '127.0.0.1:3000',
...
referer: 'http://example.com/' }
ご覧の通り、クライアントからのリクエストヘッダのリファラreferer
にhttp://example.com/
がセットされていることが分かりますね。
以上です。