Symfoware

Symfowareについての考察blog

nginx 拡張モジュールの作り方

nginxの拡張モジュールを作ってみます。

NginxでのModuleの作り方
こちらを参考に・・・というか、そのまま試してみました。


nginxビルド



Apacheのような別途モジュールをロードする方式ではなく、
ビルド時にモジュールを埋め込む感じなので、ソースからのビルドが必要になります。

ビルドするための準備は、こちらが参考になると思います。
Debian 7 + nginx 1.6.2 + lua-nginx-moduleの環境構築




最低限必要なファイル



最低限必要になるのは

config
本体ソース.c

の2つだけです。

519_01.png



「Hello Sample!」と表示するだけのsampleモジュールを作ってみます。


configにはモジュールの名前やソースのファイル名を記載。

・config


ngx_addon_name=ngx_http_sample_module
HTTP_MODULES="$HTTP_MODULES ngx_http_sample_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_sample_module.c"





本体ソースは参考サイトのままです。

・ngx_http_sample_module.c


  1. #include <ngx_config.h>
  2. #include <ngx_core.h>
  3. #include <ngx_http.h>
  4. typedef struct {
  5.     ngx_flag_t         enable;
  6. } ngx_http_sample_loc_conf_t;
  7. static char* ngx_http_sample(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  8. static void* ngx_http_sample_create_loc_conf(ngx_conf_t *cf);
  9. static ngx_command_t ngx_http_sample_commands[] = {
  10.     { ngx_string("sample"),
  11.      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
  12.      ngx_http_sample,
  13.      NGX_HTTP_LOC_CONF_OFFSET,
  14.      0,
  15.      NULL },
  16.      ngx_null_command
  17. };
  18. static ngx_http_module_t ngx_http_sample_module_ctx = {
  19.     NULL, /* preconfiguration */
  20.     NULL, /* postconfiguration */
  21.     NULL, /* create main configuration */
  22.     NULL, /* init main configuration */
  23.     NULL, /* create server configuration */
  24.     NULL, /* merge server configuration */
  25.     ngx_http_sample_create_loc_conf, /* create location configuration */
  26.     NULL
  27. };
  28. ngx_module_t ngx_http_sample_module = {
  29.     NGX_MODULE_V1,
  30.     &ngx_http_sample_module_ctx, /* module context */
  31.     ngx_http_sample_commands, /* module directives */
  32.     NGX_HTTP_MODULE,             /* module type */
  33.     NULL,                         /* init master */
  34.     NULL,                         /* init module */
  35.     NULL,                         /* init process */
  36.     NULL,                         /* init thread */
  37.     NULL,                         /* exit thread */
  38.     NULL,                         /* exit process */
  39.     NULL,                         /* exit master */
  40.     NGX_MODULE_V1_PADDING
  41. };
  42. static void *
  43. ngx_http_sample_create_loc_conf(ngx_conf_t *cf)
  44. {
  45.     ngx_http_sample_loc_conf_t *conf;
  46.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sample_loc_conf_t));
  47.     if (conf == NULL) {
  48.         return NGX_CONF_ERROR;
  49.     }
  50.     return conf;
  51. }
  52. static ngx_int_t
  53. ngx_http_sample_handler(ngx_http_request_t *r)
  54. {
  55.     ngx_int_t     rc;
  56.     ngx_buf_t    *b;
  57.     ngx_chain_t out;
  58.     unsigned char *buff;
  59.     char hello[124] = "Hello Sample!";
  60.     int l = strlen(hello);
  61.     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "***Call Handler***");
  62.     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
  63.         return NGX_HTTP_NOT_ALLOWED;
  64.     }
  65.     rc = ngx_http_discard_request_body(r);
  66.     if (rc != NGX_OK && rc != NGX_AGAIN) {
  67.         return rc;
  68.     }
  69.     if (r->headers_in.if_modified_since) {
  70.         return NGX_HTTP_NOT_MODIFIED;
  71.     }
  72.     // header設定
  73.     r->headers_out.content_type.len = sizeof("text/html") - 1;
  74.     r->headers_out.content_type.data = (u_char *) "text/html";
  75.     r->headers_out.status = NGX_HTTP_OK;
  76.     r->headers_out.content_length_n = l;
  77.     if (r->method == NGX_HTTP_HEAD) {
  78.         rc = ngx_http_send_header(r);
  79.         if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
  80.             return rc;
  81.         }
  82.     }
  83.     b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
  84.     if (b == NULL) {
  85.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  86.     }
  87.     out.buf = b;
  88.     out.next = NULL;
  89.     buff = ngx_palloc(r->pool, l);
  90.     if (buff == NULL) {
  91.      ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate memory.");
  92.      return NGX_HTTP_INTERNAL_SERVER_ERROR;
  93.     }
  94.     ngx_memcpy(buff, hello, l);
  95.     b->pos = buff;
  96.     b->last = buff + l;
  97.     b->memory = 1;
  98.     b->last_buf = 1;
  99.     rc = ngx_http_send_header(r);
  100.     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
  101.         return rc;
  102.     }
  103.     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "Success! sample");
  104.     return ngx_http_output_filter(r, &out);
  105. }
  106. static char *
  107. ngx_http_sample(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  108. {
  109.     ngx_http_core_loc_conf_t *clcf;
  110.     // location設定を取得しHandler設定
  111.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
  112.     clcf->handler = ngx_http_sample_handler;
  113.     return NGX_CONF_OK;
  114. }






ビルドと設定



configure時、--add-moduleで2つのファイルを保存したディレクトリを指定します。


# ./configure --prefix=/opt/nginx \
> --add-module=/usr/local/src/sample-module
(略)
checking for openat(), fstatat() ... found
checking for getaddrinfo() ... found
configuring additional modules
adding module in /usr/local/src/sample-module
+ ngx_http_sample_module was configured
checking for PCRE library ... found
checking for PCRE JIT support ... found
checking for md5 in system md library ... not found
checking for md5 in system md5 library ... not found
(略)




「ngx_http_sample_module was configured」と出力されています。
ちゃんと組み込まれたようです。

ビルドを実行。


# make && make install




これで自家製モジュールを組み込んだnginxが出力出来ました。
nginx.confで作ったsampleモジュールを呼び出すようにしてみます。


worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include     mime.types;
    default_type application/octet-stream;
    
    sendfile        on;

    keepalive_timeout 65;
    client_max_body_size 20M;

    server {
        listen     80;
        server_name localhost;

        location / {
            # 作ったモジュールを呼び出す
            sample;
        }
    }
}




ブラウザでアクセスしてみると、Hello Sample!って表示されました。

519_02.png




ソースの修正



Hello Symfo!と表示するよう、ソースの一部を修正しました。


char hello[124] = "Hello Symfo!";




既にsampleモジュールを組み込む形でconfigureが終了しています。
修正を反映させるにはmake && make installを実行すればOK。

519_03.png




デバッグログ



デバッグログを出力するには、nginx.confを修正します。


worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include     mime.types;
    default_type application/octet-stream;
    error_log /opt/nginx/logs/error.log debug;
    sendfile        on;

    keepalive_timeout 65;
    client_max_body_size 20M;

    server {
        listen     80;
        server_name localhost;

        location / {
            # 作ったモジュールを呼び出す
            sample;
        }
    }
}



error_logでファイル名を指定した後に「debug」をつけてやります。
これでlogs/error.logにデバッグログが出力されるようになります。


# tail /opt/nginx/logs/error.log
2014/12/10 23:36:05 [debug] 8680#0: *3 ***Call Handler***
2014/12/10 23:36:05 [debug] 8680#0: *3 Success! sample







【参考URL】

NginxでのModuleの作り方

Nginx Sticky Module

Rails アプリを nginx の拡張モジュールで置き換えて高速化する方法

Emiller's Guide To Nginx Module Development

デバッギングログ
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/12/10(水) 23:55:31|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<nginx モジュール作成 メソッド、URL、クエリパラメーターの取得方法 | ホーム | nginx 1.6.2 + lua-nginx-moduleでapache2 mod_access_tokenを実装>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1564-1e18c387
この記事にトラックバックする(FC2ブログユーザー)