はじめに
初投稿です。
先日chrome拡張機能を作成したのですがCORS周りがめんどくさかったので記録を残します。
拡張機能の内容としてはマウスで英単語を選択した際に選択位置の右下にCambridge DictionaryへのリンクとWeblio英和辞典から日本語訳を表示させるものです。私は英単語を学習するとき日本語訳をチラ見してから英英辞典を見るという手順をとっているので手間を省くために作成したって感じです。
で、選択した文字列に対応するページが存在することを確認する際と日本語訳を拾ってくる際にfetchを使用したんですがこれがCORS制約で弾かれました。調べていくとmanifest.json周りをいじってやれば解決できそうなのでやってみました。
やり方
URLの存在確認用コードはこんな感じです。fetchのresponseを基に判断しますがCambridge Dictionaryは存在しないページへのリクエストは自動的にトップページにリダイレクトされていしまうのでresponse.url === urlで返答元が指定したurlかを確かめています。
function isUrlValid(url,callback){
fetch(url,{
method:"HEAD"
})
.then((response) => {
if(response.status === 200 && response.url === url){
callback(true);
}else{
callback(false);
}
})
.catch(error => {
callback(false);
});
}
ただしこのコードだけではCORSエラーが出ますのでchromeのdeclarativeNetRequest APIを用いて対応します。これは特定のルールに基づいてネットワークリクエストをブロックしたり変更したりできるようにするものらしいです(公式リファレンス)。今回は変更で使います。
書き方は下のようにしておけば少なくとも動くとは思います。
"permissions": [
"declarativeNetRequest"
],
"host_permissions": [
"<all_urls>"
],
"declarative_net_request": {
"rule_resources": [
{
"id": "1",
"enabled": true,
"path": "rules/rule1.json"
},
{
"id": "2",
"enabled": true,
"path": "rules/rule2.json"
}
]
}
permissionsはAPIのアクセス許可です。今回はdeclarative_net_requestしか使いません。
host_permissionsにはdeclarative_net_requestを許可するurlを書きます。一部chromeAPIではpermissionのほかにこいつが必要になるらしいです。今回は全てのurlからのリクエストが対象となるので<all_urls>と書きます。
declarative_net_requestのrule_resourcesに使用するjson形式のルールファイルへのpathを書きます。複数指定できます。
[
{
"id": 1,
"priority": 1,
"action": {
"type": "modifyHeaders",
"responseHeaders": [
{
"header": "Access-Control-Allow-Origin",
"operation": "set",
"value": "*"
}
]
},
"condition": {
"urlFilter": "https://dictionary.cambridge.org/dictionary/english/*",
"resourceTypes": ["xmlhttprequest"]
}
}
]
actionにネットワークリクエストに対し何をするかを書きます。今回はレスポンスヘッダの書き換えです。全てのurlからのリクエストに対するレスポンスですのでvalueを*にしています。
conditionにそれを行う条件を書きます。urlFilterが書き換えの対象となるurlです。resourceTypesはxmlhttprequestを指定すればfetchもできます。
補足
ちなみに後で分かったことですがfetchをServiceWorker(要するにbackground.js)で行う場合host_permissionsの記述は必要ありませんでした。多分そっちが正しいやり方。
