Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Setting HTTP request headers

HTTP は Web の中核を成す技術の一つです。実際のコンテンツに加え、HTTP ヘッダによっていくつかの重要な情報が HTTP リクエストとレスポンスの両方で渡されます。

アプリケーションが作成するどんなリクエストに対しても、独自の HTTP ヘッダを加える事ができます。そのリクエストがあなたのコードで明示的に HTTP チャンネルを開くことによって開始されたリクエストであっても、また XMLHttpRequest の活動や、コンテンツ内の <img> タグ、さらに例え CSS からのものであったとしても、それは可能です。

HTTP チャンネル

HTTP リクエストとレスポンスを扱う時には、大抵は nsIHttpChannel を扱います。nsIHttpChannel インタフェースにはたくさんのプロパティやメソッドがありますが、ここで重要なメソッドは setRequestHeader です。このメソッドを使って HTTP リクエストヘッダを設定する事ができます。

下は HTTP ヘッダを設定するコードの例です。

// リクエストに "X-Hello: World" ヘッダを加える
httpChannel.setRequestHeader("X-Hello", "World", false);

このコードの httpChannel という変数は、nsIHttpChannel を実装したオブジェクトを示しています。(変数名はどんなものでも結構です。)

setRequestHeader メソッドは 3 つのパラメータを取ります。1 つめは HTTP リクエストヘッダの名前で、2 つめは HTTP リクエストヘッダのです。3 つめのパラメータに関しては今のところ無視して、常に false にしておきます。

このサンプルコードでは X-Hello という名前の HTTP リクエストヘッダが追加され、この HTTP リクエストヘッダのWorld となっています。

: 独自の HTTP ヘッダを作成する場合には、名前の前に X- を付けなければなりません。(上のサンプルコードでもちゃんと名前の前に X- を追加しているため、作成した HTTP ヘッダは Hello ではなく X-Hello となっています。)

通知

ここでおそらく、HTTP リクエストが開始された時にどうやって nsIHttpChannel を取得するのかという疑問が出てくるでしょう。

あなたのコードによってリクエストが開始された場合には、おそらく既に取得できているでしょう。その他のリクエストを捕捉するには、通知 を使います。これは他の言語やフレームワークではイベントシグナル と呼ばれるものと同じようなものです。

具体的に言えば、HTTP リクエストが作られる直前に nsIHttpChannel を取得するには "http-on-modify-request" トピックを監視 (observe) する必要があります。("http-on-modify-request" は文字列です。)

: 通知を受けられるトピックは "http-on-modify-request" の他にもたくさんあります。例えば "http-on-examine-response""xpcom-shutdown" などです。また、独自のトピックを作り出したり、自分で通知を送る事も可能です。

通知のフレームワークや一般的な通知トピックのリストについてのより詳しい情報を得るには Observer Notifications を参照して下さい。

オブザーバ

あるトピック ("http-on-modify-request" など) についての通知を得るには、オブザーバ (observer) を作成しなければなりません。オブザーバは nsIObserver インタフェースを実装したコンポーネントです。あるトピックに対してオブザーバが登録されると、オブザーバは observe メソッドが呼ばれる事によってそのトピックについての通知を受けます。

下のコードは http-on-modify-request の通知によって渡されたチャンネルに "X-Hello" という独自のヘッダを追加するオブザーバの例です。

var httpRequestObserver =
{
  observe: function(subject, topic, data) 
  {
    if (topic == "http-on-modify-request") {
      var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
      httpChannel.setRequestHeader("X-Hello", "World", false);
    }
  }
};

div class="note"> Doesn't seem very suitable for this article; readers should are typically assumed to be familiar with JS. Nickolay '''NOTE''': Often people expect JavaScript to be just like Java. And while superficially, they look very similar, there are some important differences between the two. For example, while Java is an <em>object-oriented programming language</em>, JavaScript is not. JavaScript is <em>prototype-based programming language</em> and as such while it has <em>objects</em> it does not have <em>classes</em>. (Which is why, if you are not well versed with JavaScript, the object creation in the sample code above may look strange.) </div

observe メソッドが取るパラメータの数が重要です。このメソッドは (上のサンプルコードにあるように) 3 つのパラメータを取ります。"http-on-modify-request" トピックに対しては、1 つめのパラメータ (上のコードでは subject) は nsIHttpChannel になります。ただしこれは nsISupports として渡されます。なので nsISupports から nsIHttpChannel変換しなければならず、QueryInterface を呼び出すことによってこれを行っています。

if ブロックの 2 行目のコードは既にご存知でしょう。この記事の最初の方で HTTP リクエストヘッダを追加するのに使ったコードと同じものです。

このオブジェクトの名前 (httpRequestObserver) は重要ではありません。好きな名前を付けて結構です。

登録する

オブザーバを作成したら、それを登録する必要があります。今回の場合は、オブザーバを "http-on-modify-request" トピックに対して登録しようとしています。これは以下のコードによって可能です。

var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                .getService(Components.interfaces.nsIObserverService);
observerService.addObserver(httpRequestObserver, "http-on-modify-request", false);

1 つめの文で、通知を受けたいトピックにオブザーバを登録するためのオブジェクトを取得しています。

2 つめの文では実際に登録を行っています。 "http-on-modify-request" トピック (それぞれの HTTP リクエストの直前に起こる) が発生したときに、httpRequestObserver が (observe メソッドが呼び出されることによって) 通知を受けられるようにしています。

登録を解除する

アプリケーションの終了時にはオブザーバの登録を解除するべきです。これを怠るとメモリリークが引き起こされる可能性があります。オブザーバの登録を解除するには、次のように nsIObserverService.removeObserver を使ってください。

observerService.removeObserver(httpRequestObserver, "http-on-modify-request");

XPCOM コンポーネント

http-on-modify-request オブザーバは、アプリケーションごとに 1 つしか登録する必要はありません (ウィンドウごとに 1 つではありません)。つまり、オブザーバの実装はオーバーレイではなく XPCOM コンポーネントに置くべきです。

まとめ

基本的には大体こんな感じです。しかし、あなたに役立つように、httpRequestObserver オブジェクトの少し違ったバージョンも示しておきます。

前に示したバージョンは学習のためには有効ですが、実際のアプリケーションでは次のようなコードにしたほうがいいでしょう。

var httpRequestObserver =
{
  observe: function(subject, topic, data)
  {
    if (topic == "http-on-modify-request") {
      var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
      httpChannel.setRequestHeader("X-Hello", "World", false);
    }
  },

  get observerService() {
    return Components.classes["@mozilla.org/observer-service;1"]
                     .getService(Components.interfaces.nsIObserverService);
  },

  register: function()
  {
    this.observerService.addObserver(this, "http-on-modify-request", false);
  },

  unregister: function()
  {
    this.observerService.removeObserver(this, "http-on-modify-request");
  }
};

このオブジェクトには register()unregister() という便利なメソッドがあり、下のように呼び出すだけでオブザーバを有効にする事が出来ます。

httpRequestObserver.register();

また、終了時にはオブザーバの登録を解除するのも忘れないでください。

httpRequestObserver.unregister();

以上です。

We need downloadable XPCOM component for this

サンプルコード

var headerName  = "X-hello";
var headerValue = "world";

function LOG(text)
{
    //    var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
    //    consoleService.logStringMessage(text);
}

function myHTTPListener() { }

myHTTPListener.prototype = {
    
  observe: function(subject, topic, data)
  {
      if (topic == "http-on-modify-request") {

          LOG("----------------------------> (" + subject + ") mod request");

          var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
          httpChannel.setRequestHeader(headerName, headerValue, false);
          return;
      }


      if (topic == "app-startup") {

          LOG("----------------------------> app-startup");

          var os = Components.classes["@mozilla.org/observer-service;1"]
                             .getService(Components.interfaces.nsIObserverService);

          os.addObserver(this, "http-on-modify-request", false);
          return;
      }
  },
 
  QueryInterface: function (iid) {
        if (iid.equals(Components.interfaces.nsIObserver) ||
            iid.equals(Components.interfaces.nsISupports))
            return this;
        
        Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
        return null;
    },
};

var myModule = {
    registerSelf: function (compMgr, fileSpec, location, type) {

        var compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(this.myCID,
                                        this.myName,
                                        this.myProgID,
                                        fileSpec,
                                        location,
                                        type);


          LOG("----------------------------> registerSelf");

        var catMgr = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
        catMgr.addCategoryEntry("app-startup", this.myName, this.myProgID, true, true);
    },


    getClassObject: function (compMgr, cid, iid) {

          LOG("----------------------------> getClassObject");

        return this.myFactory;
    },

    myCID: Components.ID("{9cf5f3df-2505-42dd-9094-c1631bd1be1c}"),

    myProgID: "@dougt/myHTTPListener;1",

    myName:   "Simple HTTP Listener",

    myFactory: {
        QueryInterface: function (aIID) {
            if (!aIID.equals(Components.interfaces.nsISupports) &&
                !aIID.equals(Components.interfaces.nsIFactory))
                throw Components.results.NS_ERROR_NO_INTERFACE;
            return this;
        },

        createInstance: function (outer, iid) {

          LOG("----------------------------> createInstance");

          return new myHTTPListener();
        }
    },

    canUnload: function(compMgr) {
        return true;
    }
};

function NSGetModule(compMgr, fileSpec) {
    return myModule;
}

ドキュメントのタグと貢献者

 このページの貢献者: ethertank, fscholz, Shoot
 最終更新者: ethertank,