Hatena::Groupdann

Nginxのモジュール作成

Nginxのモジュール作成

モジュールの種類

Handler

Upstream Handler (proxy handler)

headerの送信
  • headers_outというstructにヘッダ情報が
    • r->headers_out
  • headerの送信
    • ngx_http_send_header(r);
Responseの送信
  • レスポンス生成
  • メモリのallocate
  • レスポンスを特別なbufferに割当
  • chain linkにbuffer割当
  • send body functionをcall
    • return ngx_http_output_filter(r, &out);

chain link

What are the chain links for? Nginx lets handler modules generate (and filter modules process) responses one buffer at a time; each chain link keeps a pointer to the next link in the chain, or NULL if it's the last one. We'll keep it simple and assume there is just one buffer.

  • nginexはhandlerのresponseを生成させる。一度に一つのbufferを。
  • chain linkはchain中の次のリンクへのポインタを持つ(またはNULL - これは最後の)
  • うーむ、まだわからん

upstream handlerのcallback (hook)

  • create_request
    • crafts a request buffer (or chain of them) to be sent to the upstream
  • reinit_request
    • is called if the connection to the back-end is reset (just before create_request is called for the second time)
  • process_header
    • processes the first bit of the upstream's response, and usually saves a pointer to the upstream's "payload"
  • abort_request
    • is called if the client aborts the request
  • finalize_request
    • is called when Nginx is finished reading from the upstream
  • input_filter
    • is a body filter that can be called on the response body (e.g., to remove a trailer)

callbackの登録の仕方

static ngx_int_t
ngx_http_proxy_handler(ngx_http_request_t *r)
{
    ngx_int_t                   rc;
    ngx_http_upstream_t        *u;
    ngx_http_proxy_loc_conf_t  *plcf;

    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);

/* set up our upstream struct */
    u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
    if (u == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u->peer.log = r->connection->log;
    u->peer.log_error = NGX_ERROR_ERR;

    u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;

    u->conf = &plcf->upstream;

/* attach the callback functions */
    u->create_request = ngx_http_proxy_create_request;
    u->reinit_request = ngx_http_proxy_reinit_request;
    u->process_header = ngx_http_proxy_process_status_line;
    u->abort_request = ngx_http_proxy_abort_request;
    u->finalize_request = ngx_http_proxy_finalize_request;

Handlerのインストール

ngx_command_tの3番目にhandler(callback)を

    { ngx_string("circle_gif"),
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
      ngx_http_circle_gif,
      0,
      0,
      NULL }

clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

でcore structを取得して、core structのhandlerにhandlerを代入.

以下が例

static char *
ngx_http_circle_gif(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_circle_gif_handler;

    return NGX_CONF_OK;
}

filter

Filterはhandlerが生成したレスポンスの操作

  • header filterは HTTP headerをfilter
  • body filterはresponse contentをfilter

filterのインストール

fiterはpostconfiguration phaseでインストール

static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_http_chunked_filter_init,          /* postconfiguration */
  ...
};

Here's what happens in ngx_http_chunked_filter_init:

static ngx_int_t
ngx_http_chunked_filter_init(ngx_conf_t *cf)
{
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_chunked_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_chunked_body_filter;

    return NGX_OK;
}

Load balancer

とりあえず必要ないので、後回し