おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

[Apache] レスポンスヘッダーの内容をログに出力して、なおかつヘッダーから削除する方法

フロントにApacheを立てて、裏でRailsなどを動かしている場合、Rails上の情報をApacheのログに残したいときがあります。

たとえば、処理をしたRailsが稼動しているサーバ名を記録したいとしましょう(障害対応の助けになりますよね?)。
Rails側で以下のようなコードを書いて、after_filterなどで処理させるようにします(本当はrack上とかで処理したほうがいいけど)。

response.headers["X-Server-Name"] = Server.hostname #=> サーバ名を返す架空のライブラリ  

こうすれぱレスポンスヘッダー X-Server-Name の内容をApacheのログに出力するだけでよくなります。

LogFormat "....\t%{X-Server-Name}o\t...."  

しかしこのままだと、この情報はそのままクライアントに返ってしまいます。サーバ名を返しちゃうのはあまりよくありません。
そこで、Apacheのconfを設定してレスポンスヘッダから消してしまいます。

Header        unset X-Server-Name  
Header always unset X-Server-Name  

これでクライアントには返りません。めでたしめでたし、と思っていたら、サーバ名の情報がログにも出力されなくなりました。

Apacheの処理のサイクルでは、ログ出力が一番最後の処理になります。ヘッダから削除した後にログ出力をするので、ログには何も書かれないというわけなのです。
The Apache Modules Book

 「 The Apache Modules Book」に詳しく書いてあります。

となると、Apache module を書くしかないのかと思っていたら、すでに作っている方がいらっしゃいました。

mod_copy_header

と思っていたら、Apacheのmod_headersにすでにこれを実現できる機能が存在していました。

mod_headers#Header

以下のようにするとレスポンスヘッダーの内容をノートにコピーできます(Apache2.4.7以降)

Header note X-Server-Name Server-Name  

Header        unset X-Server-Name  
Header always unset X-Server-Name  

ノートにコピーしたあとは、ヘッダから消しちゃって構いません。
あとはログに出力するだけです。ノートの情報は、%{Foobar}n で出力できます。

LogFormat "....\t%{Server-Name}n\t...."  

簡単です…。なにを悩んでいたのか。
落とし穴だったのは、Apacheの日本語ドキュメントにはこのことが書いてないということなのでした。
英語のドキュメントをまず読むようにしないといけないですね。