nginxのHttpPerlModuleを試してみた

nginxで、「HttpPerlModule」を試してみました。

1.HttpPerlModuleの概要

HttpPerlModuleは、nginxにPerlを組み込んで、nginxをPerlで拡張できるようにするモジュールです。
Apacheのmod_perlに似ています。
以下のようなことができます。

  • 特定のディレクトリにアクセスがあった時に、Perlのプログラムを実行して、その結果を出力する
  • nginxの設定ファイル(nginx.conf)で使う変数を、Perlのプログラムで設定する
  • SSIとしてPerlのプログラムを実行する

2.HttpPerlModuleのインストール

HttpPerlModuleは、デフォルトではオプションとなっています。
nginxをコンパイルする際に、configureのオプションとして「-with-http_perl_module」を付加してからコンパイルします。

3.nginx.confの設定

HttpPerlModuleを使うには、nginx.confに以下のような行を追加します。

3-1.perl_modules

実行するPerlのモジュールのファイルがあるディレクトリを記述します。
nginx.confのhttpのコンテキストに入れます。
例えば、「/mylib/perl」ディレクトリのPerlのファイルを実行できるようにするには、以下のように書きます。

http {
  ...
  perl_module /mylib/perl
  ...
}

なお、複数のディレクトリを指定したい場合は、個々のディレクトリごとに、perl_moduleの行を書きます。

3-2.perl_require

読み込むPerlのファイル名を記述します。
nginx.confのhttpのコンテキストに入れます。
また、ファイルは、前述のperl_moduleで指定したディレクトリに入れます。
例えば、「/mylib/perl/MyModule.pm」というファイルを実行できるようにするには、以下のように書きます。

http {
  ...
  perl_module /mylib/perl
  perl_require MyModule.pm
  ...
}

なお、複数のファイルを読み込みたい場合は、個々のファイルごとに、perl_requireの行を書きます。

3-3.perl_set

nginx.confで使う変数を設定します。
nginx.confのhttpのコンテキストに入れます。
書き方は以下のいずれかで、サブルーチンの戻り値が変数にセットされます。

  • perl_set $変数名 モジュール名::サブルーチン名;
  • perl_set $変数名 'sub { ... }';

3-4.perl

ページへのアクセスがあった時に、指定したサブルーチンを実行します。
nginx.confのlocationかlimit_exceptのコンテキストに入れます。

例えば、「http://○○○.com/perl/」ディレクトリにアクセスがあった時に、「/mylib/perl/MyModule.pm」の「handler」というサブルーチンを実行する場合だと、nginx.confに以下のように書きます。

http {
  ...
  perl_module /mylib/perl
  perl_require MyModule.pm
  ...
  server {
    location /perl/ {
      perl MyModule::handler;
      ...
    }
    ...
  }
  ...
}

4.ハンドラの記述例

perlディレクティブで指定したサブルーチンには、「$r」というオブジェクトが渡されます。
このオブジェクトはリクエストを表すもので、リクエストやレスポンスを処理するためのメソッドがあります。

例えば、以下のような処理を行いたいとします。

  • URLに対応するファイルがある場合は、そのファイルの内容を出力し、その後に「<!-- This page was served by nginx. -->」のコメントを出力する
  • URLに対応するファイルがない場合は、404エラーにし、「Not Found」と出力する

このような処理を行うモジュールを作ると、以下のようになります。

package MyModule;
use strict;
use nginx;

sub handler {
    my $r = shift;
    my $fname = $r->filename;
    if (!-e $fname) {
        $r->status(404);
        $r->send_http_header("text/html");
        $r->print('Not Found');
    }
    else {
        $r->send_http_header("text/html");
        $r->sendfile($fname);
        $r->print('<!-- This page was served by nginx. -->');
    }
    return OK;
}

1;

なお、$rで使えるメソッドの詳細は、こちらのページにあります。