ふふーん

一緒にやりたくなったのよ!あなたと、調合を!

nginxモジュールを作ってみるやつ(その3)

uni.firis.me

前回のつづき。 変数の展開をやってみた。

confのところでscript_compileしておいてハンドラーでscript_runすればいいらしい。

static char *ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
    ngx_http_core_loc_conf_t *clcf =
            ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    ngx_http_echo_loc_conf_t *elcf = conf;
    ngx_uint_t n;

    clcf->handler = ngx_http_echo_handler;
    elcf->text = ((ngx_str_t *)cf->args->elts)[1];

    n = ngx_http_script_variables_count(&elcf->text);
    if (n > 0) {
        ngx_int_t rc;
        ngx_http_script_compile_t sc = { 0 };

        sc.cf = cf;
        sc.source = &elcf->text;
        sc.lengths = &elcf->lengths;
        sc.values = &elcf->values;
        sc.variables = n;
        sc.complete_lengths = 1;
        sc.complete_values = 1;

        rc = ngx_http_script_compile(&sc);
        if (rc != NGX_OK)
            return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}

static ngx_int_t ngx_http_echo_handler(ngx_http_request_t *r) {
    ngx_http_echo_loc_conf_t *elcf =
            ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
    ngx_int_t rc;
    ngx_chain_t *cl, *newline_cl;
    ngx_buf_t *buf, *newline_buf;
    ngx_str_t text, newline_str = ngx_string("\n");

    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD)
        return NGX_HTTP_NOT_ALLOWED;

    if (elcf->lengths == NULL) {
        text = elcf->text;
    } else {
        u_char *compiled = ngx_http_script_run(r, &text, elcf->lengths->elts,
                                               0, elcf->values->elts);
        if (compiled == NULL)
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    buf = ngx_calloc_buf(r->pool);
    if (buf == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    buf->pos = text.data;
    buf->last = text.data + text.len;
    buf->memory = 1;

    newline_buf = ngx_calloc_buf(r->pool);
    if (newline_buf == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    newline_buf->pos = newline_str.data;
    newline_buf->last = newline_str.data + newline_str.len;
    newline_buf->memory = 1;
    newline_buf->last_buf = 1;

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    cl->buf = buf;

    newline_cl = ngx_alloc_chain_link(r->pool);
    if (newline_cl == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    newline_cl->buf = newline_buf;
    cl->next = newline_cl;

    ngx_str_set(&r->headers_out.content_type, "text/plain");
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = text.len + newline_str.len;

    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
        return rc;

    return ngx_http_output_filter(r, cl);
}

おわり。