<div dir="ltr">Hello, <div><br></div><div>I am trying to write an Nginx module that tries to do the following in the content phase handler - </div><div><ul><li>Read the POST body</li><li>Call a sub-request to another location module within the same server</li><li>Return a 204 response after the sub-request is completed (for test purposes only)</li></ul></div><div>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) -</div><div><br></div><div><font face="monospace, monospace">ngx_int_t ngx_http_test_handler(ngx_http_request_t* r)</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> ngx_http_test_ctx_t* ctx = ngx_http_get_module_ctx(r, ngx_http_test_module);</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> // Initialize request context</font></div><div><font face="monospace, monospace"> if (ctx == NULL)</font></div><div><font face="monospace, monospace"> {</font></div><div><font face="monospace, monospace"> ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_test_ctx_t));</font></div><div><font face="monospace, monospace"> ctx->waiting_more_body = false;</font></div><div><font face="monospace, monospace"> ctx->read_body_done = false;</font></div><div><font face="monospace, monospace"> ctx->sub_request = NULL;</font></div><div><font face="monospace, monospace"> ngx_http_set_ctx(r, ctx, ngx_http_test_module);</font></div><div><font face="monospace, monospace"> }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> // If sub-request is in progress</font></div><div><font face="monospace, monospace"> if (ctx->sub_request && !ctx->sub_request->done)</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"> // If awaiting more POST body</font></div><div><font face="monospace, monospace"> if (ctx->waiting_more_body)</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"> // If POST body not yet read</font></div><div><font face="monospace, monospace"> if (!ctx->read_body_done)</font></div><div><font face="monospace, monospace"> {</font></div><div><font face="monospace, monospace"> rc = ngx_http_read_client_request_body(r, ngx_http_test_content_phase_post_read);</font></div><div><font face="monospace, monospace"> </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"> ctx->waiting_more_body = true;</font></div><div><font face="monospace, monospace"> return NGX_DONE;</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"> // If body read</font></div><div><font face="monospace, monospace"> if (ctx->read_body_done)</font></div><div><font face="monospace, monospace"> {</font></div><div><font face="monospace, monospace"> // Initiate sub-request if not yet done</font></div><div><font face="monospace, monospace"> if (!ctx->sub_request)</font></div><div><font face="monospace, monospace"> {</font></div><div><font face="monospace, monospace"> ngx_http_test_subrequest(r);</font></div><div><font face="monospace, monospace"> return NGX_DONE;</font></div><div><font face="monospace, monospace"> }</font></div><div><font face="monospace, monospace"> </font></div><div><font face="monospace, monospace"> // If sub-request completed</font></div><div><font face="monospace, monospace"> if (ctx->sub_request->done)</font></div><div><font face="monospace, monospace"> </font><span style="font-family:monospace,monospace">{</span></div><div><span style="font-family:monospace,monospace"> // Return test response </span></div><div><span style="font-family:monospace,monospace"> r->headers_out.status = NGX_HTTP_NO_CONTENT;</span></div><div><span style="font-family:monospace,monospace"> ngx_http_send_header(r);</span></div><div><span style="font-family:monospace,monospace"> ngx_http_finalize_request(r, NGX_HTTP_NO_CONTENT);</span><br></div><div><span style="font-family:monospace,monospace"> }</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace"> // Sub-request is in progress</span></div><div><span style="font-family:monospace,monospace"> return NGX_DONE;</span></div><div><span style="font-family:monospace,monospace"> }</span></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> return NGX_OK;</font></div><div><font face="monospace, monospace">}</font></div><div><div><br></div><div><br></div><div>This is the post read callback hander - </div><div><br></div><div><span class="" style="font-family:monospace,monospace">static</span><span class="" style="font-family:monospace,monospace"> </span><span class="" style="font-family:monospace,monospace">void </span><span style="font-family:monospace,monospace">ngx_http_ssp_content_phase_post_read(ngx_http_request_t *r)</span><br></div><div><span style="font-family:monospace,monospace">{</span></div><div><span style="font-family:monospace,monospace"> ngx_http_test_ctx_t* ctx = ngx_http_get_module_ctx(r, ngx_http_test_module);</span></div><div><span style="font-family:monospace,monospace"> ctx->read_body_done = true;</span></div><div><span style="font-family:monospace,monospace"> if (ctx->waiting_more_body)</span></div><div><span style="font-family:monospace,monospace"> {</span></div><div><span style="font-family:monospace,monospace"> ctx->waiting_more_body = false;</span></div><div><span style="font-family:monospace,monospace"> ngx_http_finalize_request(r, ngx_http_test_request_handler(r));</span></div><div><span style="font-family:monospace,monospace"> }</span></div><div><span style="font-family:monospace,monospace"> else </span></div><div><span style="font-family:monospace,monospace"> {</span></div><div><span style="font-family:monospace,monospace"> r->main->count--;</span></div><div><span style="font-family:monospace,monospace"> }</span></div><div><span style="font-family:monospace,monospace">}</span></div><div><br></div><div><br></div><div>And here is the pseudo code for the function that initiates the sub-request -</div><div><br></div><div><font face="monospace, monospace">ngx_int_t ngx_http_ssp_auction_subrequest(ngx_http_request_t* r)</font></div><div><span style="font-family:monospace,monospace">{</span><br></div><div><span style="font-family:monospace,monospace"> ngx_http_</span><span style="font-family:monospace,monospace">test_ctx_t* ctx = ngx_http_get_module_ctx(r, ngx_http_test_module);</span></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> // Setup post sub-request handler</font></div><div><font face="monospace, monospace"> ngx_http_post_subrequest_t* psr = ngx_pcalloc(r->pool, sizeof(ngx_http_post_subrequest_t));</font></div><div><font face="monospace, monospace"> psr->handler = ngx_http_test_post_subrequest;</font></div><div><font face="monospace, monospace"> return ngx_http_subrequest(r, &location, url_args, &ctx->sub_request, psr, 0);</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">And finally the post sub-request handler -</font></div><div><font face="monospace, monospace"><br></font></div>
<div><font face="monospace, monospace">ngx_int_t <span class="">ngx_http_test_auction_post_subrequest(ngx_http_request_t *r, </span><span class="">void</span><span class="">* data, ngx_int_t rc)</span></font></div><div><span class=""><font face="monospace, monospace">{</font></span></div><div><span class=""><font face="monospace, monospace"> // Mark the sub-request as done</font></span></div><div><span class=""><font face="monospace, monospace"> r->done = true;</font></span></div><div><span class=""><font face="monospace, monospace"> return NGX_DONE;</font></span></div><div><span class=""><font face="monospace, monospace">}</font></span></div>
<div><br></div><div><br></div><div>When I run this, here are the observations -</div><div><ul><li><font face="arial, helvetica, sans-serif">The ngx_http_test_auction_post_subrequest is being called twice - </font></li><ul><li><font face="arial, helvetica, sans-serif">First via the sub-request location module handler's ngx_http_finalize_request</font></li><li><font face="arial, helvetica, sans-serif">Second via the core content phase's call to ngx_http_finalize_request</font></li></ul></ul><font face="arial, helvetica, sans-serif"> Is this expected?<br></font><ul><li><font face="arial, helvetica, sans-serif">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. </font></li></ul></div><div><br></div><div>Any pointers on what is going wrong and how to correct it is greatly appreciated.</div><div><br></div><div>Thanks in advance,</div><div>Raj</div><br><div data-smartmail="gmail_signature"><table border="0" cellpadding="0" cellspacing="0"><tbody align="left" valign="top"><tr><td style="vertical-align:top;text-align:left;white-space:nowrap"><br></td><td style="vertical-align:top;text-align:left;white-space:nowrap"><table border="0" cellpadding="0" cellspacing="0"><tbody align="left" valign="top">
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div>
</div></div>
<br>
<div style="color:rgb(0,0,0);font-family:Arial,Helvetica,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><font color="#808080" size="1">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.</font></div><div style="color:rgb(0,0,0);font-family:Arial,Helvetica,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><font color="#808080" size="1"><br></font></div><div style="color:rgb(0,0,0);font-family:Arial,Helvetica,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><font color="#808080" size="1">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.</font></div>