Maxim Dounin
February 22, 2011 06:16AM
Hello!

On Tue, Feb 22, 2011 at 01:34:51AM -0800, Antoine BONAVITA wrote:

> Hello,
>
> I'm trying to write my first module, so bear with me if my question feel silly.
> The situation is fairly simple:
> - My module accepts GET, POST and HEAD methods.
> - My module can return big chunks of data for GET and POST.
> - When I'm processing the GET everything is OK.
> - When I'm processing a POST which does not trigger saving the body to a temp
> file, everything is OK.
> - When I'm processing a POST which triggers saving the body to a temp file, my
> client only gets the first 65536 bytes (confirmed by both a wireshark capture
> and the nginx logs).
>
> Now, I understand nginx is happy when handling GET and "small POST" because
> everything happens in the content handler which returns appropriately
> NGX_AGAIN/NGX_OK/NGX_DONE. I would be happy to do the same with the
> post_handler. Unfortunately the signature of the post_handler (as defined by
> ngx_http_read_client_request_body) is:
> typedef void (*ngx_http_client_body_handler_pt)(ngx_http_request_t *r);
> and therefore I cannot return NGX_AGAIN (which would be natural).

When reading request body, your code in handler should look like:

static ngx_int_t
ngx_http_your_module_handler(...)
{
...

rc = ngx_http_read_client_request_body(r, ngx_http_your_body_hander);

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

return NGX_DONE;
}

static void
ngx_http_your_body_handler(...)
{
...

ngx_http_finalize_request(...);
return;
}

Key points are:

1. You always return NGX_DONE from handler.

2. You are responsible to call ngx_http_finalize_request() as
you've retruned NGX_DONE.

> I'll try to get some "bare-bone" code together to reproduce this but high-level
> it looks like:
> ngx_int_t ngx_http_xxx_handler(ngx_http_request_t *r) {
> if (NGX_HTTP_GET == r->method) {
> return ngx_http_xxx_do_get(r);
> } else if (NGX_HTTP_POST == r->method) {
> return ngx_http_xxx_do_post(r);
> }
> }
>
> ngx_int_t ngx_http_xxx_do_post(ngx_http_request_t *r) {
> [...]
> rc = ngx_http_read_client_request_body(r, ngx_http_xxx_body_received);
>
> if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
> return rc;
> }
>
> if (rc == NGX_AGAIN) {
> /* It will not call me again, but call the body_received. */
> return NGX_AGAIN;
> }

No, NGX_AGAIN here means: setup http writer and call it again once
write is possible on client connection. It is designed to be
natural for code like

return ngx_http_output_filter(r, &out);

Returning NGX_AGAIN in case of reading body will result in
problems (exactly as you see). Use the above pattern instead.

Maxim Dounin

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

BIG requests/responses to POST and post_handler return value

Antoine BONAVITA 2191 February 22, 2011 04:36AM

Re: BIG requests/responses to POST and post_handler return value

Maxim Dounin 968 February 22, 2011 06:16AM

Re: BIG requests/responses to POST and post_handler return value

Antoine BONAVITA 1092 February 22, 2011 08:52AM

Re: BIG requests/responses to POST and post_handler return value

agentzh 919 February 22, 2011 10:34PM

Re: BIG requests/responses to POST and post_handler return value

Antoine BONAVITA 869 February 23, 2011 12:04PM

Re: BIG requests/responses to POST and post_handler return value

agentzh 1574 February 27, 2011 11:06PM

Re: BIG requests/responses to POST and post_handler return value

Antoine BONAVITA 1107 February 28, 2011 04:26PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 159
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready