谷歌插件v3关于跨域拨号修改文件头那点事

443 阅读3分钟

我手上负责的谷歌插件v3版本对v2的替代进程已经基本完成了。对于大部分非屏蔽广告功能的插件来说,其实主要难点就在于跨域拨号方式的修改。v3拨号废弃了ajax,采用了fetch。关于fetch的使用我建议去查询fetch的使用方法。本文要说的重点在于对头文件的修改。

v3要实现头文件修改需要依靠重定向规则,而重定向规则可以用两种形式实现。

一种是静态规则,该种方法的弊端在于定性之后,对当个接口修改规则或添加接口时。都需要替换底层文件,对于上传到应用市场的插件这不是太大问题。但对于需要客户手动离线安装的插件来说,会麻烦很多,增加不必要的用户操作。

另一种是采用动态规则修改,相对第一种来说就灵活了很多。用点比较狗的方法,基本可以达到v2版所能实现的那种头文件修改直接跟接口放到一起的效果。我自己选择的也是第二种。

静态规则

manifest.json

{
"name": "My extension",
...
"declarative_net_request" : {
    "rule_resources" : [
        {
        "id": "rule",
        "enabled": true,
        "path": "rule.json"
        }]
    },
"permissions": [
    "declarativeNetRequest",
    "declarativeNetRequestFeedback",
    ...
    ],
...
}

然后在目录下新建文件rule.json。 rule.json

[{
    "id": 1,
    "priority": 1,
    "condition": {
        "regexFilter": "https://XXX.XXX.XXX/api/*",
        "resourceTypes": ["xmlhttprequest"]
        },
    "action": {
        "type": "modifyHeaders",
        "requestHeaders": [
            {
            "header": "h1",
            "operation": "set",
            "value": "v4"
            },
            {
            "header": "foo",
            "operation": "remove"
            }]
        }
}]

动态规则

动态规则无需在manifest.json中做declarative_net_request的配置。而是需要在服务工作中使用chrome.declarativeNetRequest.updateDynamicRules。 service_worker.js(即v3中代替background.js的那个东西)

let rule={
    removeRuleIds: [1],//删除原有的规则一
    addRules: [{
            "id": 1,
            "priority": 1,
            "condition": {
                "urlFilter": "https://XXX.XXX.XXX/api/*",
                "resourceTypes": ["xmlhttprequest"],
            },
            "action": {
                "type": "modifyHeaders",
                "requestHeaders": [
                {
                    "header": "h1",
                    "operation": "set",
                    "value": "v4"
                },
                {
                    "header": "foo",
                    "operation": "remove"
                }]
            }
        }]
};
//注意这一句,不是画蛇添足,往下看说明
rule.addRules.forEach((item)=>{
    item.condition.domains=[chrome.runtime.id]
})
//写入规则
chrome.declarativeNetRequest.updateDynamicRules(rule,function(){
//这是为了查看规则是否写入成功,正式使用时可以删除
    chrome.declarativeNetRequest.getDynamicRules(rules=>console.log(rules)) 
})

这一段其实是被我强行拿出来凑一起举例了,实际使用中rule参数应该是进行跨域拨号前将其传到service_worker中,然后再在service_worker中写入插件id限制修改头文件的范围最后updateDynamicRules;

这个方法好处在于无限接近于v2版的修改规则头,最大程度避免了同一插件使用相近url时产生的影响。坏处在于使用多个跨域拨号时需要采用异步操作,否则会有修改头文件失误的可能性。

避免这些问题,还可以有个折中的方法。将插件一个页面所需的跨域规则全部统计出来,在加载时就将其写入规则。在所需跨域接口不多,且不会稳定不需要经常改动的情况下,这不失为最佳的方案。

请重点注意

1、rule中你要影响到的网址需要在manifest.json的host_permissions中有。其实想想也是你主机权限都不给你让插件怎么去改这个api的拨号头呢。

2、为了避免对正常网页影响,规则集中一定要使用domains!!!!

3、关于rule参数我介绍我记得有专门的文档,写文的时候我没搜到。基本常用的就是举例上的这些参数;requestHeaders拨号头,responseHeaders响应头;参数的修改set,删除remove。具体感兴趣的可以自己去找文档详细了解。