nginx处理post请求的handler

1. 在主handler中,判断如果是POST请求,转向一个post_handler,因为在不同事件中需要回调用这个post_handler,所以不要在主handler中处理。

2.因为其它事件回调这个post_hander时只能传入request,所以不要传入out,应该把out放在一个自己定义的context中

所以主handler中逻辑应该是

       if (r->method == NGX_HTTP_POST) {
            ctx = ngx_http_get_module_ctx(r, ngx_module_test);
            if (ctx == NULL) {
                ctx = ngx_pcalloc(r->pool, sizeof (ngx_test_request_ctx_t));
                if (ctx == NULL) {
                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate request context.");
                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }
                ctx->post_read_okay = 0;
                ctx->request_out = &out;
                ngx_http_set_ctx(r, ctx, ngx_module_test);
            }
            return ngx_test_post_handler(r);

        }


3.out从外部传入是为了和get等方法统一处理,也可以在这个post_handler要输出的时候再申请一个内存池作

static ngx_int_t ngx_test_post_handler(ngx_http_request_t *r) {

    ngx_int_t rc;
    ngx_test_request_ctx_t *ctx;
    ngx_str_t input;
    ngx_chain_t * out;
    u_char * content;
    content = (u_char *) "This is a post demo handler for nginx.";

    ctx = ngx_http_get_module_ctx(r, ngx_module_test);
    if (ctx == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (!ctx->post_read_okay) {
        rc = ngx_http_read_client_request_body(r, ngx_test_post_read_request_body_handler);
       //ngx_test_post_read_request_body_handler只能有一个参数r,它又需要回调post_handler,

       //所以它也只能传一个参数给post_handler,所以上面的out被放到ctx中。


        if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
            return rc;
        }
        return NGX_DONE;
    }

    // get input request body
    input = ngx_test_post_get_requst_body(r); //这个方法可以放在动态库中处理
    if (input.len == 0) {
        return NGX_DECLINED;
    }
    
    printf("post content:%s\n",(char* )input.data);

    r->headers_out.content_type.len = sizeof ("text/html") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html";
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = ngx_strlen(content);

    out = ctx->request_out;
    out->buf->pos = content;
    out->buf->last = content + (ngx_strlen(content));
    out->buf->memory = 1;
    out->buf->last_buf = 1;

    ngx_http_send_header(r);
    return ngx_http_output_filter(r, out);
}

static void ngx_test_post_read_request_body_handler(ngx_http_request_t *r) {
    ngx_test_request_ctx_t *ctx;
    ctx = ngx_http_get_module_ctx(r, ngx_module_test);

    if (ctx == NULL) {
        return ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
    }
    ctx->post_read_okay = 1;
    ngx_http_finalize_request(r, ngx_test_post_handler(r));
}



static ngx_str_t ngx_test_post_get_requst_body(ngx_http_request_t *r) {
    u_char *p;
    u_char *data;
    size_t len;
    ngx_buf_t *buf, *next;
    ngx_chain_t *cl;
    ngx_str_t body = ngx_null_string;
    if (r->request_body == NULL
            || r->request_body->bufs == NULL) {
        return body;
    }
    if (r->request_body->temp_file) {
        printf("Please read the content from file: %s\n", (char*) r->request_body->temp_file->file.name.data);
        body = r->request_body->temp_file->file.name;
        return body;
    } else {

        cl = r->request_body->bufs;

        buf = cl->buf;

        if (cl->next == NULL) {
            len = (buf->last - buf->pos);
            p = ngx_pnalloc(r->pool, len + 1);
            if (p == NULL) {
                return body;
            }
            data = p;
            ngx_memcpy(p, buf->pos, len);
            data[len] = 0;

        } else {
            next = cl->next->buf;
            len = (buf->last - buf->pos) + (next->last - next->pos);
            p = ngx_pnalloc(r->pool, len + 1);
            data = p;
            if (p == NULL) {
                return body;
            }
            p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
            ngx_memcpy(p, next->pos, next->last - next->pos);
            data[len] = 0;
        }
    }

    body.len = len;
    body.data = data;
    return body;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值