Mercurial > hg > nginx-site
changeset 1970:a1d29eda04b6
The HTTP request body section of the development guide.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 19 Apr 2017 18:42:45 +0300 |
parents | 275c928ab386 |
children | 5fb870087b76 |
files | xml/en/docs/dev/development_guide.xml |
diffstat | 1 files changed, 176 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/xml/en/docs/dev/development_guide.xml Wed Apr 19 18:36:37 2017 +0300 +++ b/xml/en/docs/dev/development_guide.xml Wed Apr 19 18:42:45 2017 +0300 @@ -5048,6 +5048,182 @@ </section> +<section name="Request body" id="http_request_body"> + +<para> +For dealing with client request body, nginx provides the following functions: +<literal>ngx_http_read_client_request_body(r, post_handler)</literal> and +<literal>ngx_http_discard_request_body(r)</literal>. +The first function reads the request body and makes it available via the +<literal>request_body</literal> request field. +The second function instructs nginx to discard (read and ignore) the request +body. +One of these functions must be called for every request. +Normally, it is done in the content handler. +</para> + +<para> +Reading or discarding client request body from a subrequest is not allowed. +It should always be done in the main request. +When a subrequest is created, it inherits the parent +<literal>request_body</literal> object which can be used by the subrequest if +the main request has previously read the request body. +</para> + +<para> +The function +<literal>ngx_http_read_client_request_body(r, post_handler)</literal> starts +the process of reading the request body. +When the body is completely read, the <literal>post_handler</literal> callback +is called to continue processing the request. +If request body is missing or already read, the callback is called immediately. +The function +<literal>ngx_http_read_client_request_body(r, post_handler)</literal> +allocates the <literal>request_body</literal> request field of type +<literal>ngx_http_request_body_t</literal>. +The field <literal>bufs</literal> of this object keeps the result as a buffer +chain. +The body can be saved in memory buffers or file buffers, if +<link doc="../http/ngx_http_core_module.xml" id="client_body_buffer_size"/> +is not enough to fit the entire body in memory. +</para> + +<para> +The following example reads client request body and returns its size. +</para> + +<programlisting> +ngx_int_t +ngx_http_foo_content_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + + rc = ngx_http_read_client_request_body(r, ngx_http_foo_init); + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + /* error */ + return rc; + } + + return NGX_DONE; +} + + +void +ngx_http_foo_init(ngx_http_request_t *r) +{ + off_t len; + ngx_buf_t *b; + ngx_int_t rc; + ngx_chain_t *in, out; + + if (r->request_body == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + len = 0; + + for (in = r->request_body->bufs; in; in = in->next) { + len += ngx_buf_size(in->buf); + } + + b = ngx_create_temp_buf(r->pool, NGX_OFF_T_LEN); + if (b == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + b->last = ngx_sprintf(b->pos, "%O", len); + b->last_buf = (r == r->main) ? 1: 0; + b->last_in_chain = 1; + + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = b->last - b->pos; + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + ngx_http_finalize_request(r, rc); + return; + } + + out.buf = b; + out.next = NULL; + + rc = ngx_http_output_filter(r, &out); + + ngx_http_finalize_request(r, rc); +} +</programlisting> + +<para> +The following fields of the request affect the way request body is read: +</para> + +<list type="bullet"> + +<listitem> +<literal>request_body_in_single_buf</literal> - read body to a single memory +buffer +</listitem> + +<listitem> +<literal>request_body_in_file_only</literal> - always read body to a file, +even if fits the memory buffer +</listitem> + +<listitem> +<literal>request_body_in_persistent_file</literal> - do not unlink the file +right after creation. +Such a file can be moved to another directory +</listitem> + +<listitem> +<literal>request_body_in_clean_file</literal> - unlink the file the when the +request is finalized. +This can be useful when a file was supposed to be moved to another directory +but eventually was not moved for some reason +</listitem> + +<listitem> +<literal>request_body_file_group_access</literal> - enable file group access. +By default a file is created with 0600 access mask. +When the flag is set, 0660 access mask is used +</listitem> + +<listitem> +<literal>request_body_file_log_level</literal> - log file errors with this +log level +</listitem> + +<listitem> +<literal>request_body_no_buffering</literal> - read request body without +buffering +</listitem> + +</list> + +<para> +When the <literal>request_body_no_buffering</literal> flag is set, the +unbuffered mode of reading the request body is enabled. +In this mode, after calling +<literal>ngx_http_read_client_request_body()</literal>, the +<literal>bufs</literal> chain may keep only a part of the body. +To read the next part, the +<literal>ngx_http_read_unbuffered_request_body(r)</literal> function should be +called. +The return value of <literal>NGX_AGAIN</literal> and the request flag +<literal>reading_body</literal> indicate that more data is available. +If <literal>bufs</literal> is NULL after calling this function, there is +nothing to read at the moment. +The request callback <literal>read_event_handler</literal> will be called when +the next part of request body is available. +</para> + +</section> + + <section name="Response" id="http_response"> <para>