Need help with sub-request handling

Rajalakshmi Iyer rajalakshmi.iyer at blis.com
Mon Jul 11 23:35:39 UTC 2016


Hello,

I am trying to write an Nginx module that tries to do the following in the
content phase handler -

   - Read the POST body
   - Call a sub-request to another location module within the same server
   - Return a 204 response after the sub-request is completed (for test
   purposes only)

Here is the pseudo code for the handler (Apologies for the longish
description, I have tried to keep the code to a minimum required to
describe the issue I am facing) -

ngx_int_t ngx_http_test_handler(ngx_http_request_t* r)
{
   ngx_http_test_ctx_t* ctx = ngx_http_get_module_ctx(r,
ngx_http_test_module);

   // Initialize request context
   if (ctx == NULL)
   {
      ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_test_ctx_t));
      ctx->waiting_more_body = false;
      ctx->read_body_done = false;
      ctx->sub_request = NULL;
      ngx_http_set_ctx(r, ctx, ngx_http_test_module);
   }

   // If sub-request is in progress
   if (ctx->sub_request && !ctx->sub_request->done)
   {
      return NGX_DONE;
   }

   // If awaiting more POST body
   if (ctx->waiting_more_body)
   {
      return NGX_DONE;
   }

   // If POST body not yet read
   if (!ctx->read_body_done)
   {
      rc = ngx_http_read_client_request_body(r,
ngx_http_test_content_phase_post_read);

      if (rc == NGX_AGAIN)
      {
         ctx->waiting_more_body = true;
         return NGX_DONE;
      }
   }

   // If body read
   if (ctx->read_body_done)
   {
      // Initiate sub-request if not yet done
      if (!ctx->sub_request)
      {
         ngx_http_test_subrequest(r);
         return NGX_DONE;
      }

      // If sub-request completed
      if (ctx->sub_request->done)
      {
         // Return test response
         r->headers_out.status = NGX_HTTP_NO_CONTENT;
         ngx_http_send_header(r);
         ngx_http_finalize_request(r, NGX_HTTP_NO_CONTENT);
      }

      // Sub-request is in progress
      return NGX_DONE;
   }

   return NGX_OK;
}


This is the post read callback hander -

static void ngx_http_ssp_content_phase_post_read(ngx_http_request_t *r)
{
   ngx_http_test_ctx_t* ctx = ngx_http_get_module_ctx(r,
ngx_http_test_module);
   ctx->read_body_done = true;
   if (ctx->waiting_more_body)
   {
      ctx->waiting_more_body = false;
      ngx_http_finalize_request(r, ngx_http_test_request_handler(r));
   }
   else
   {
      r->main->count--;
   }
}


And here is the pseudo code for the function that initiates the sub-request
-

ngx_int_t ngx_http_ssp_auction_subrequest(ngx_http_request_t* r)
{
   ngx_http_test_ctx_t* ctx = ngx_http_get_module_ctx(r,
ngx_http_test_module);

   // Setup post sub-request handler
   ngx_http_post_subrequest_t* psr = ngx_pcalloc(r->pool,
sizeof(ngx_http_post_subrequest_t));
   psr->handler = ngx_http_test_post_subrequest;
   return ngx_http_subrequest(r, &location, url_args, &ctx->sub_request,
psr, 0);
}

And finally the post sub-request handler -

ngx_int_t ngx_http_test_auction_post_subrequest(ngx_http_request_t *r, void*
data, ngx_int_t rc)
{
   // Mark the sub-request as done
   r->done = true;
   return NGX_DONE;
}


When I run this, here are the observations -

   - The ngx_http_test_auction_post_subrequest is being called twice -
      - First via the sub-request location module handler's
      ngx_http_finalize_request
      - Second via the core content phase's call to
      ngx_http_finalize_request

           Is this expected?

   - When I issue a request at the main module's entry point, I can see
   everything working, until the post subrequest handler is called twice.
   Thereafter, I don't see the test response (204) and the request just hangs.
   If I terminate nginx, I can see the 204 response.


Any pointers on what is going wrong and how to correct it is greatly
appreciated.

Thanks in advance,
Raj

-- 
This email and any attachments to it may be confidential and are 
intended solely for the use of the individual to whom it is addressed. Any 
views or opinions expressed are solely those of the author and do not 
necessarily represent those of Blis Ltd, a company registered in England 
and Wales with registered number 06455773. Its registered office is 5th 
Floor, 85 Tottenham Court Road, London, W1T 4TQ, United Kingdom.

If you are not the intended recipient of this email, you must neither take 
any action based upon its contents, nor copy or show it to anyone. Please 
contact the sender if you believe you have received this email in error.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20160712/8a8f1886/attachment.html>


More information about the nginx-devel mailing list