尝试在火狐扩展中获取 HTTP POST 请求

Trying to get HTTP POST request in Firefox extension

本文关键字:获取 HTTP POST 请求 扩展 火狐      更新时间:2023-09-26

我正在构建一个扩展来获取Firefox中的POST请求。我通读了拦截页面加载和 HTTP 观察器的文档,但仍然无法在页面加载上获取特定的 POST 数据(例如:data1=50&sdata2=0&data3=50)。

我查看了TamperData的代码,发现他们使用了stream.available()和stream.read(1)。但是,我无法让这些命令与我的代码一起使用。

目前我的代码如下所示:

var ObserverTest = {
     observe: function(subject, topic, data) {
        if (topic == 'http-on-modify-request') {
            var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
        }
        if (topic == "http-on-examine-response") {
            var newListener = new TracingListener();
            subject.QueryInterface(Ci.nsITraceableChannel);
            newListener.originalListener = subject.setNewListener(newListener);
        }
    },
    register: function() {
        var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
        observerService.addObserver(ObserverTest, "http-on-modify-request", false);
        observerService.addObserver(ObserverTest, "http-on-examine-response", false);
    },
    unregister: function() {
        var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
        observerService.removeObserver(ObserverTest, "http-on-modify-request");
        observerService.removeObserver(ObserverTest,"http-on-examine-response");
    }
}
window.addEventListener("load", ObserverTest.register, false);
window.addEventListener("unload", ObserverTest.unregister, false);

//Helper function for XPCOM instanciation (from Firebug)
function CCIN(cName, ifaceName) {
    return Cc[cName].createInstance(Ci[ifaceName]);
}
// Copy response listener implementation.
function TracingListener() {
    this.originalListener = null;
    this.receivedData = [];   // array for incoming data.
}
TracingListener.prototype = {
    onDataAvailable: function(request, context, inputStream, offset, count) {
        var binaryInputStream = CCIN("@mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
        var storageStream = CCIN("@mozilla.org/storagestream;1", "nsIStorageStream");
        var binaryOutputStream = CCIN("@mozilla.org/binaryoutputstream;1", "nsIBinaryOutputStream");

        var stream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
        stream.init(binaryInputStream);
        binaryInputStream.setInputStream(inputStream);
        storageStream.init(8192, count, null);
        binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
        // Copy received data as they come.
        var data = binaryInputStream.readBytes(count);
        this.receivedData.push(data);
        binaryOutputStream.writeBytes(data, count);
        this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), offset, count);
    },
    onStartRequest: function(request, context) {
        this.originalListener.onStartRequest(request, context);
    },
    onStopRequest: function(request, context, statusCode)
    {
        // Get entire response
        var responseSource = this.receivedData.join();
        this.originalListener.onStopRequest(request, context, statusCode);
    },
    QueryInterface: function (aIID) {
        if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
            return this;
        }
        throw Components.results.NS_NOINTERFACE;
    }
}
 

首先,根本不需要"http-on-examine-response"TracingListener。如果你想对响应做点什么,这些东西是有好处的,但你追求的是请求中的数据,所以topic == 'http-on-modify-request'是这样。

以下函数(未经测试,但从我的一个扩展复制并清理了一些)演示了如何获取帖子数据。假定该函数是从 http-on-modify-request 调用的。

const ScriptableInputStream = Components.Constructor(
  "@mozilla.org/scriptableinputstream;1",
  "nsIScriptableInputStream",
  "init");
function observeRequest(channel, topic, data) {
  let post = null;
  if (!(channel instanceof Ci.nsIHttpChannel) ||
    !(channel instanceof Ci.nsIUploadChannel)) {
    return post;
  }
  if (channel.requestMethod !== 'POST') {
    return post;
  }
  try {
    let us = channel.uploadStream;
    if (!us) {
      return post;
    }
    if (us instanceof Ci.nsIMultiplexInputStream) {
      // Seeking in a nsIMultiplexInputStream effectively breaks the stream.
      return post;
    }
    if (!(us instanceof Ci.nsISeekableStream)) {
      // Cannot seek within the stream :(
      return post;
    }
    let oldpos = us.tell();
    us.seek(0, 0);
    try {
      let is = new ScriptableInputStream(us);
      // we'll read max 64k
      let available = Math.min(is.available(), 1 << 16);
      if (available) {
        post = is.read(available);
      }
    }
    finally {
      // Always restore the stream position!
      us.seek(0, oldpos);
    }
  }
  catch (ex) {
    Cu.reportError(ex);
  }
  return post;
}

根据您的用例,您可能需要检查us instanceof是否例如 nsIMIMEInputStreamnsIStringInputStream用于特殊处理或快速通道...

你可以从观察者那里调用它,如下所示:

  observe: function(subject, topic, data) {
    if (topic == 'http-on-modify-request') {
      observeRequest(subject, topic, data);
    }
  },