Stan
Stan

Reputation: 8768

How to use Chrome's declarativeWebRequest for changing http response headers

I'm trying to write a simple Chrome extension, which replaces the Content-Type header in http response using declarativeWebRequest (currently in beta; I'm using 25.0.1364.0).

The code is based on Catifier example, where I changed the registerRules method:

var RequestMatcher = chrome.declarativeWebRequest.RequestMatcher;
var RemoveResponseHeader = chrome.declarativeWebRequest.RemoveResponseHeader;
var AddResponseHeader = chrome.declarativeWebRequest.AddResponseHeader;

function registerRules() {
  var changeRule = {
    priority: 100,
    conditions: [
      // If any of these conditions is fulfilled, the actions are executed.
      new RequestMatcher({
        contentType: ['audio/mpeg']
      }),
    ],
    actions: [
      new RemoveResponseHeader({name: 'Content-Type'}),
      new AddResponseHeader({name: 'Content-Type', value: 'application/octet-stream'}),
      new AddResponseHeader({name: 'X-ChromeExt-Content-Type', value: 'trap'})
    ]
  };

  var callback = function() {
    if (chrome.extension.lastError) {
      console.error('Error adding rules: ' + chrome.extension.lastError);
    } else {
      console.info('Rules successfully installed');
      chrome.declarativeWebRequest.onRequest.getRules(null,
          function(rules) {
            console.info('Now the following rules are registered: ' +
                         JSON.stringify(rules, null, 2));
          });
    }
  };

  chrome.declarativeWebRequest.onRequest.addRules(
      [changeRule], callback);
}

It works ok in the sense, that the rules are registered, and I got the following feedback from the browser console:

Now the following rules are registered: [
  {
    "actions": [
      {
        "instanceType": "declarativeWebRequest.RemoveResponseHeader",
        "name": "Content-Type"
      },
      {
        "instanceType": "declarativeWebRequest.AddResponseHeader",
        "name": "Content-Type",
        "value": "application/octet-stream"
      },
      {
        "instanceType": "declarativeWebRequest.AddResponseHeader",
        "name": "X-ChromeExt-Content-Type",
        "value": "trap"
      }
    ],
    "conditions": [
      {
        "contentType": [
          "audio/mpeg"
        ],
        "instanceType": "declarativeWebRequest.RequestMatcher"
      }
    ],
    "id": "_0_",
    "priority": 100
  }
]

The problem is that the code does not actually produce any effect, that is http response headers remain unchanged. I'm not sure if this relates to a (still unfixed) bug in Chrome not displaying altered headers. But anyway, I have the following questions:

1) Is the abovementioned RequestMatcher applied to contentType correctly or should I use a matcher for responseHeaders instead (with somehow pointed out Content-Type)?

2) If RequestMatcher should be applied to responseHeaders, what is the syntax for such a rule?

new RequestMatcher({
  responseHeaders: // what to place here to match a value in a specific header line?
  // or possibly responseHeaders['Content-Type']: ...?
})

3) How can one debug a rule execution? I mean I'd like to trace and analyze how conditions are processed, and actions executed. Without this using declarativeWebRequest would be a puzzle, imho.

Thanks in advance.

Upvotes: 2

Views: 2474

Answers (1)

方 觉
方 觉

Reputation: 4152

1) I tried the following code (which is almost the same as yours, except that it modifies the content type from text/html to text/plain)

chrome.declarativeWebRequest.onRequest.addRules([{
    priority: 100,
    conditions: [
      // If any of these conditions is fulfilled, the actions are executed.
      new chrome.declarativeWebRequest.RequestMatcher({
        contentType: ['text/html']
      }),
    ],
    actions: [
      new chrome.declarativeWebRequest.RemoveResponseHeader({name: 'Content-Type'}),
      new chrome.declarativeWebRequest.AddResponseHeader({name: 'Content-Type', value: 'text/plain'}),
      new chrome.declarativeWebRequest.AddResponseHeader({name: 'X-ChromeExt-Content-Type', value: 'trap'})
    ]
  }])

And it worked! The modification is not reflected in DevTools, though.

2) According to https://developer.chrome.com/trunk/extensions/declarativeWebRequest.html#type-HeaderFilter , you should use

new RequestMatcher({
  responseHeaders: [{nameEquals: "Content-Type", valueContains: "audio/mpeg"}]
})

But it didn't work (Did I make a mistake??). Use valueContains instead of valueEquals since Content-Type may contain encoding.

3) It seems impossible to do that unless you debug Chrome itself.

I tested on Chromium 25.0.1363.0 (Build 173419)

Upvotes: 4

Related Questions