2011年10月2日

Nginx でレスポンスヘッダーを追加する

Nginx の HttpHeadersMoreModule を使うと、HTTP レスポンスにヘッダーを付け足せるようなので導入してみます。 特定の条件の場合にヘッダーを追加できるとクロスドメイン通信を実現できますので、 JSON か XML でレスポンスを返せるサーバーソフトウェアのクライアントサイドを実装する敷居が下がるはずです。 要するに、JavaScript で Solr のカスタムクライアントを実装できるかもしれませんね、という話です。

HttpHeadersMoreModule は追加モジュールであるため、ソースコードを取得して、 Nginx のビルドオプションで明示する必要があります。 自前でソースコードをコンパイルするところから始めますので、すんなりいかない場合もあるかもしれません。 実行環境には Amazon の EC2 を使います。

この辺の続きです。

Nginx のコンパイル

nginx-1.0.8 を使います。 headers-more-nginx-module のバージョン 0.15 は 1.0.5 で動作確認しているようですが、 たぶん 1.0.8 でも大丈夫でしょう。

Nginx 自体をコンパイルするためには PCRE (Perl Compatible Regular Expressions) も必要になりますので、 合計で次の3つのソースアーカイブを用意します。

  • nginx-1.0.8
  • headers-more-nginx-module-0.15
  • pcre-8.13
$ [ -d src ] || mkdir src
$ cd src
$ wget http://nginx.org/download/nginx-1.0.8.tar.gz
$ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.13.tar.gz
$ wget -O headers-more-nginx-module-0.15.tar.gz https://github.com/agentzh/headers-more-nginx-module/tarball/v0.15
$ for f in `ls -1 *.tar.gz`; do tar -xzvf $f; done

コンパイラなどをインストールしておきます。

$ sudo yum -y install gcc zlib-devel

configure スクリプトにいくつかのオプションを渡してビルドします。

$ cd nginx-1.0.8
$ ./configure \
        --prefix=/usr/local/nginx/nginx-1.0.8 \
        --with-pcre=../pcre-8.13 \
        --add-module=../agentzh-headers-more-nginx-module-137855d
$ make

コンパイルが通ったらインストールします。 バージョンの違いで嵌まるとイヤなのでバージョン番号も残しておきます。

$ sudo make install
$ cd /usr/local/nginx
$ sudo ln -s nginx-1.0.8 latest

インストールできたら起動してみます。

$ cd /usr/local/nginx/latest
$ sudo ./sbin/nginx

wget などでアクセスして、Server が nginx であることを確認します。

$ wget -Sq "http://localhost"
  HTTP/1.1 200 OK
  Server: nginx/1.0.8
  Date: Sun, 02 Oct 2011 11:56:12 GMT
  Content-Type: text/html
  Content-Length: 151
  Last-Modified: Sun, 02 Oct 2011 11:52:43 GMT
  Connection: keep-alive
  Accept-Ranges: bytes

アクセスログも確認しておきます。

$ tail logs/access.log

Nginx の設定

more_set_headers を使ってみます。 /usr/local/nginx/latest/conf/nginx.conf に次の記述を追加します。

location /search {
    more_set_headers 'X-MyHeader: blah' 'X-MyHeader2: foo';
}

Nginx を再起動します。

$ sudo pkill nginx
$ sudo ./sbin/nginx

/search にアクセスするとヘッダーが追加されていますね。

$ wget -Sq "http://localhost/search"
  HTTP/1.1 404 Not Found
  Server: nginx/1.0.8
  Date: Sun, 02 Oct 2011 12:01:47 GMT
  Content-Type: text/html
  Content-Length: 168
  Connection: keep-alive
  X-MyHeader: blah
  X-MyHeader2: foo

クロスドメインの設定

サーバー側で Solr を動かして Nginx でプロキシさせるために、 stackoverflow の回答を参考に設定します。

nginx.conf はこんな感じ。

location /solr {
    if ($request_method = 'OPTIONS') {
        more_set_headers 'Access-Control-Allow-Origin: *';
        more_set_headers 'Access-Control-Allow-Methods: GET, OPTIONS';
        more_set_headers 'Access-Control-Max-Age: 1728000';
        more_set_headers 'Content-Type: text/plain; charset=UTF-8';

        return 200;
    }

    more_set_headers 'Access-Control-Allow-Origin: *';
    proxy_pass       http://127.0.0.1:8983/solr;
}

HTTP の OPTIONS を処理する必要性はこの辺で。

JavaScript で Solr のレスポンスを表示

ローカルマシンで適当な HTML と JavaScript (solr-search.html, solr-search.js) を用意します。 jQuery と jQuery Template、それから Twitter Bootstrap を読み込んでおきます。

HTML のあるディレクトリで HTTP サーバーを立ち上げます。

$ python -m SimpleHTTPServer

ブラウザーで http://localhost:8000/solr-search.html にアクセスし、 検索キーワードを入力して実行すると、検索結果が表示されます。(冒頭のスクリーンショット)

Firebug などでレスポンスヘッダーを確認すると、 Access-Control-Allow-Origin が設定されています。

あとは好みに応じて実装すればカスタムクライアントを実装できます。 特定のフィールドだけを一覧形式で表示したい場合には便利かもしれません。

終わりに

Nginx でレスポンスヘッダーを追加してみました。 追加モジュールを使う場合は、ソースアーカイブを取得してコンパイルオプションを調整する必要があります。 独自環境を使っている場合にはコンパイルが大変かもしれませんが、たいがいのアーキテクチャではサクッと使えると思います。

ヘッダーにも多様な役割のものがありますが、ここではクロスドメイン通信に焦点を当てました。 JavaScript によるクロスドメイン通信には色々と難しい問題がありますが、 サーバーサイドにプロキシを追加して実現する方法はとてもお手軽だと思いました。

なお、Solr の場合は json.wrf パラメータを使うことで JSONP を実現できます。 このため、Solr で JSON だけを使う場合にはこの記事の内容は不要です。 たとえば、次のリンクのようにして実現できます。

Solr の JavaScript クライアントとしては ajax-solr があります。 リクエスト URL とプロキシ URL を設定できるようになっていますので、 きちんとした自前のクライアントページを構築するならこちらを使うべきでしょう。

用途に合わせて様々な組み合わせや制約がありますが、 何かのときに役立つと良いのかな、と。

コメントを投稿