--- title: Setting HTTP request headers slug: Mozilla/Tech/XPCOM/Setting_HTTP_request_headers tags: - Add-ons - Extensions - HTTP - XUL - XULRunner - 要更新 translation_of: Mozilla/Tech/XPCOM/Setting_HTTP_request_headers ---
HTTP は Web の中核を成す技術の一つです。実際のコンテンツに加え、HTTP ヘッダによっていくつかの重要な情報が HTTP リクエストとレスポンスの両方で渡されます。
アプリケーションが作成するどんなリクエストに対しても、独自の HTTP ヘッダを加える事ができます。そのリクエストがあなたのコードで明示的に HTTP チャンネルを開くことによって開始されたリクエストであっても、また XMLHttpRequest の活動や、コンテンツ内の <img>
タグ、さらに例え CSS からのものであったとしても、それは可能です。
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");
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; }