Search code examples
google-chromegoogle-chrome-extensionbrowser-extension

Updating Location header does not affect redirect


I'm trying to update the Location header. I can see the new value for the header in the Console, however the browser is not redirecting to the new URL.

Here's my manifest.json:

{
    "manifest_version": 3,
    "name": "Hello Extensions",
    "description": "Base Level Extension",
    "version": "1.0",
    "action": {
    "default_popup": "hello.html",
    "default_icon": "hello_extensions.png"
    },  
    "background": {
        "service_worker": "scripts/background.js"
      },
    "host_permissions": [
        "<all_urls>"
    ],
    "permissions": [    
    "webRequest"
    ]
}

background.js:

var callback = function(details) {
    if (details.statusCode === 302) {
        
        var locationHeader = details.responseHeaders.find(x => x.name === 'Location')
        if (locationHeader) {       
            locationHeader.value = "https://www.google.com";
            console.log(details);
        }
    }
    
    return { responseHeaders: details.responseHeaders };
}

var filter = { urls: ["*://*/*"] };

chrome.webRequest.onHeadersReceived.addListener(callback, filter, ["responseHeaders"]);

Here you can see the new value for Location:

enter image description here

I also had a look in the tab's own Console and can see the Location value has not persisted.

How can I make the browser redirect to the new Location header value?


Solution

  • You need to use webRequestBlocking permission for that (and the accompanying 'blocking' mode in addListener), but it's allowed only in a policy-installed ManifestV3 extension (or in a patched/recompiled Chrome binary), otherwise webRequest API is purely observational, i.e. it can't make changes.

    There's no solution for normal ManifestV3 extensions until crbug.com/1141166 is fixed, then you'll be able to use declarativeNetRequest API to change the header on responses that already have it.

    The current workaround is to use declarativeNetRequest unconditionally for the domains that you confirmed to serve this header. To list the domains in one rule you can use requestDomains array or just omit condition altogether in case the list is the same as host_permissions in manifest.json.