<div dir="ltr"><div><font face="arial, helvetica, sans-serif">Hi,</font></div><div><font face="arial, helvetica, sans-serif">In my module, I'd like to look into the post body to decide if the request should be allowed to proceed to origin server or not. Based on the examples I could find I've coded this in my module. After some trial and error it seems to be working. I am not sure if my implementation is 100% correct. I would appreciate it if someone can go over my code below and let me know if my implementation is correct. Especially, the body_complete_handler. Thanks.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Regards,</font></div><div><font face="arial, helvetica, sans-serif">Dk.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><div><font face="monospace, monospace">static ngx_int_t mod_setup_body_handler(ngx_http_request_t* r);</font></div><div><font face="monospace, monospace">static void mod_body_complete_handler(ngx_http_request_t* r);</font></div><div><font face="monospace, monospace">static ngx_int_t mod_extract_post_body(ngx_http_request_t *r, char *data, size_t *dsize);</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">static ngx_int_t</font></div><div><font face="monospace, monospace">ngx_http_request_handler(ngx_http_request_t *r)</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace">  ....</font></div><div><font face="monospace, monospace">  if ((NGX_HTTP_POST == r->method) || (NGX_HTTP_PUT == r->method)) {</font></div><div><font face="monospace, monospace">    return mod_setup_body_handler(r);</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  ...</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">ngx_int_t</font></div><div><font face="monospace, monospace">mod_setup_body_handler(ngx_http_request_t* r)</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace">  ngx_int_t rc;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  r->request_body_in_single_buf = 1;</font></div><div><font face="monospace, monospace">  r->request_body_in_persistent_file = 1;</font></div><div><font face="monospace, monospace">  r->request_body_in_clean_file = 1;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  rc = ngx_http_read_client_request_body(r, mod_body_complete_handler);</font></div><div><font face="monospace, monospace">  if (rc == NGX_ERROR) {</font></div><div><font face="monospace, monospace">    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "read req. body error");</font></div><div><font face="monospace, monospace">    return rc;</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {</font></div><div><font face="monospace, monospace">    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "read req. body error. special response");</font></div><div><font face="monospace, monospace">    return rc;</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  if (rc == NGX_AGAIN) {</font></div><div><font face="monospace, monospace">    /*</font></div><div><font face="monospace, monospace">     * nginx will call the body_received when needed. Returning</font></div><div><font face="monospace, monospace">     * NGX_DONE will prevent nginx from calling ngx_http_finalize_request</font></div><div><font face="monospace, monospace">     * (which we will call in body_received)</font></div><div><font face="monospace, monospace">     */</font></div><div><font face="monospace, monospace">    return NGX_DONE;</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  return NGX_DECLINED;</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">void</font></div><div><font face="monospace, monospace">mod_body_complete_handler(ngx_http_request_t* r)</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace">  ngx_http_request_t* r = mNginxRequest;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  if(r->request_body == NULL) {</font></div><div><font face="monospace, monospace">    // callback was called but body is empty. Setup handler again.</font></div><div><font face="monospace, monospace">    mod_setup_body_handler(bh_ptr);</font></div><div><font face="monospace, monospace">    return;</font></div><div><font face="monospace, monospace">  } else if (r->request_body->rest) {</font></div><div><font face="monospace, monospace">    // we don't have the complete body. Complete callback will be called again.</font></div><div><font face="monospace, monospace">    return;</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  if (NULL == mNginxRequest->request_body->temp_file) {</font></div><div><font face="monospace, monospace">    size_t dsize = 64*1024;</font></div><div><font face="monospace, monospace">    char data[dsize]</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    if (mod_extract_post_body(r, data, dsize) == NGX_OK) {</font></div><div><font face="monospace, monospace">      // we have the complete body.</font></div><div><font face="monospace, monospace">      int rc = mod_allow_request(body, dsize);  // returns NGX_OK or 4XX.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">      if (rc != NGX_OK) {</font></div><div><font face="monospace, monospace">        // allow req. has already sent a custom response if rc != NGX_OK.</font></div><div><font face="monospace, monospace">        ngx_http_finalize_request(r, NGX_OK);</font></div><div><font face="monospace, monospace">        return;</font></div><div><font face="monospace, monospace">      }</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  // ???? not having this cause request to hang.</font></div><div><font face="monospace, monospace">  ngx_http_core_run_phases(r);</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">ngx_int_t</font></div><div><font face="monospace, monospace">mod_extract_post_body(ngx_http_request_t *r, char *data, size_t *dsize)</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace">  size_t buf_size = *dsize;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  if (NULL == r->request_body->temp_file) {</font></div><div><font face="monospace, monospace">    // we have body in buffer chain.</font></div><div><font face="monospace, monospace">    ngx_buf_t *buf;</font></div><div><font face="monospace, monospace">    ngx_chain_t *cl;</font></div><div><font face="monospace, monospace">    size_t data_start_pos = 0;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    cl = r->request_body->bufs;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    // copy the body into our temporary buffer.</font></div><div><font face="monospace, monospace">    for (;NULL != cl; cl = cl->next) {</font></div><div><font face="monospace, monospace">      buf = cl->buf;</font></div><div><font face="monospace, monospace">      size_t bsize = buf->last - buf->pos;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">      if ((data_start_pos+bsize) > buf_size) {</font></div><div><font face="monospace, monospace">        // data is bigger than the input buffer size, abort</font></div><div><font face="monospace, monospace">        *dsize = data_start_pos;</font></div><div><font face="monospace, monospace">        *(data+*dsize) = '\0';</font></div><div><font face="monospace, monospace">        return NGX_ERROR;</font></div><div><font face="monospace, monospace">      }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">      ngx_memcpy((data+data_start_pos), buf->pos, bsize);</font></div><div><font face="monospace, monospace">      data_start_pos += bsize;</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    *dsize = data_start_pos;</font></div><div><font face="monospace, monospace">    *(data+*dsize) = '\0';</font></div><div><font face="monospace, monospace">    return NGX_OK;</font></div><div><font face="monospace, monospace">  } else {</font></div><div><font face="monospace, monospace">    // body in file not implemented yet.</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  return NGX_ERROR;</font></div><div><font face="monospace, monospace">}</font></div></div></div>