Hi,
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.

Regards,
Dk.


static ngx_int_t mod_setup_body_handler(ngx_http_request_t* r);
static void mod_body_complete_handler(ngx_http_request_t* r);
static ngx_int_t mod_extract_post_body(ngx_http_request_t *r, char *data,
size_t *dsize);

static ngx_int_t
ngx_http_request_handler(ngx_http_request_t *r)
{
  ....
  if ((NGX_HTTP_POST == r->method) || (NGX_HTTP_PUT == r->method)) {
    return mod_setup_body_handler(r);
  }

  ...
}

ngx_int_t
mod_setup_body_handler(ngx_http_request_t* r)
{
  ngx_int_t rc;

  r->request_body_in_single_buf = 1;
  r->request_body_in_persistent_file = 1;
  r->request_body_in_clean_file = 1;

  rc = ngx_http_read_client_request_body(r, mod_body_complete_handler);
  if (rc == NGX_ERROR) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "read req. body
error");
    return rc;
  }

  if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "read req. body
error. special response");
    return rc;
  }

  if (rc == NGX_AGAIN) {
    /*
     * nginx will call the body_received when needed. Returning
     * NGX_DONE will prevent nginx from calling ngx_http_finalize_request
     * (which we will call in body_received)
     */
    return NGX_DONE;
  }

  return NGX_DECLINED;
}


void
mod_body_complete_handler(ngx_http_request_t* r)
{
  ngx_http_request_t* r = mNginxRequest;

  if(r->request_body == NULL) {
    // callback was called but body is empty. Setup handler again.
    mod_setup_body_handler(bh_ptr);
    return;
  } else if (r->request_body->rest) {
    // we don't have the complete body. Complete callback will be called
again.
    return;
  }

  if (NULL == mNginxRequest->request_body->temp_file) {
    size_t dsize = 64*1024;
    char data[dsize]

    if (mod_extract_post_body(r, data, dsize) == NGX_OK) {
      // we have the complete body.
      int rc = mod_allow_request(body, dsize);  // returns NGX_OK or 4XX.

      if (rc != NGX_OK) {
        // allow req. has already sent a custom response if rc != NGX_OK.
        ngx_http_finalize_request(r, NGX_OK);
        return;
      }
    }
  }

  // ???? not having this cause request to hang.
  ngx_http_core_run_phases(r);
}

ngx_int_t
mod_extract_post_body(ngx_http_request_t *r, char *data, size_t *dsize)
{
  size_t buf_size = *dsize;

  if (NULL == r->request_body->temp_file) {
    // we have body in buffer chain.
    ngx_buf_t *buf;
    ngx_chain_t *cl;
    size_t data_start_pos = 0;

    cl = r->request_body->bufs;

    // copy the body into our temporary buffer.
    for (;NULL != cl; cl = cl->next) {
      buf = cl->buf;
      size_t bsize = buf->last - buf->pos;

      if ((data_start_pos+bsize) > buf_size) {
        // data is bigger than the input buffer size, abort
        *dsize = data_start_pos;
        *(data+*dsize) = '\0';
        return NGX_ERROR;
      }

      ngx_memcpy((data+data_start_pos), buf->pos, bsize);
      data_start_pos += bsize;
    }

    *dsize = data_start_pos;
    *(data+*dsize) = '\0';
    return NGX_OK;
  } else {
    // body in file not implemented yet.
  }

  return NGX_ERROR;
}
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to