header already sent

Hung Nguyen hungnv at opensource.com.vn
Sat Jul 7 01:22:18 UTC 2018


Hello, 

I didnt read your code carefully but in case you want to deny request, just return NGX_HTTP_FORBIDDEN, don’t need to send any http header, nginx will take care the rest.

If you want to handle 403 error by a custom 403 page, use error handler in nginx configuration file instead. 

--
Hưng

> On Jul 7, 2018, at 04:33, Dk Jack <dnj0496 at gmail.com> wrote:
> 
> Hi,
> I thought I solved my issue but it looks like I haven't. It just took some time for the log messages to show up.
> I've attached my code below. In my  code, the call HttpModuleProcessRequest returns a non-zero value if
> the requests needs to be blocked. Would appreciate if some one can help. Thanks
> 
> -----------------------------------------------------------------------------------------------------------------------------------------------
> PS: The issue seems to happen for request that my module blocked, so it seems to be related to the send header call.
> 
> SendResponseBuffer(ngx_http_request_t *r, ngx_uint_t http_status, char *reason, ngx_int_t rlen)
> {
>   ngx_int_t rc;
>   ngx_log_t *log = r->connection->log;
>   ngx_buf_t *buf = ngx_create_temp_buf(r->pool, (rlen+16)); // pad.
>   if (NULL == buf) {
>     ngx_log_error(NGX_LOG_ERR, log, 0, "%s: Failed to allocate buffer", __FUNCTION__);
>     return NGX_ERROR;
>   }
> 
>   buf->last = ngx_copy(buf->start, (unsigned char*) data, dlen);
> 
>   rc = ngx_http_discard_request_body(r);
>   if (rc != NGX_OK) {
>     ngx_log_error(NGX_LOG_ERR, log, 0, "%s: Discard req. body failed. rc=%i", __FUNCTION__, rc);
>     return rc;
>   }
> 
>   ngx_chain_t *out_chain = ngx_alloc_chain_link(r->pool);
>   if (NULL == out_chain) {
>     ngx_log_error(NGX_LOG_ERR, log, 0, "%s: Buffer chain alloc failed", __FUNCTION__);
>     return NGX_ERROR;
>   }
> 
>   out_chain->buf = buf;
>   out_chain->next = NULL;
>   buf->last_buf = 1;
>   buf->last_in_chain = 1;
> 
>   r->headers_out.status = http_status;
>   r->headers_out.content_length_n = buf->last - buf->pos;
>   r->headers_out.content_type.len = sizeof("text/plain") - 1;
>   r->headers_out.content_type.data = (u_char *) "text/plain";
>   r->header_only = 1;
>   r->headers_out.content_length_n = 0;
> 
>   rc = ngx_http_send_header(r);
>   if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
>     ngx_log_error(NGX_LOG_ERR, log, 0, "%s: Send header failed. rc=%i", __FUNCTION__, rc);
>     return rc;
>   }
> 
>   return ngx_http_output_filter(r, out_chain);
> }
> 
> typedef struct {
>   unsigned done:1;
> } ngx_http_mod_ctx_t;
> 
> static ngx_int_t
> ngx_http_request_handler(ngx_http_request_t *r)
> {
>   ngx_http_mod_ctx_t  *ctx = ngx_http_get_module_ctx(r, nginx_http_module);
>   if (ctx) {
>     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "duplicate invokation");
>     return NGX_DECLINED;
>   } else {
>     ctx = ngx_palloc(r->connection->pool, sizeof(ngx_http_mod_ctx_t));
>     if (ctx == NULL) {
>       ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
>                     "Out of memory. Cannot allocate context");
>       return NGX_ERROR;
>     }
> 
>     ctx->done = 0;
>     ngx_http_set_ctx(r, ctx, nginx_http_module);
>   }
> 
>   ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
>                 "%s: uri:\"%V\" uuri: \"%V\" call-count:%ud",
>                 __FUNCTION__, &r->uri, &r->unparsed_uri, r->main->count);
> 
>   ngx_int_t rc = 0;
>   if (!ctx->done) {
>     char buf[512];
>     ngx_uint_t len;
>     ngx_uint_t http_status;
> 
>     rc = HttpModuleProcessRequest(r, &http_status, buf, &len);
>     if (!rc) {
>       rc = SendResponseBuffer(r, http_status, buf, len);
>     }
>   }
> 
>   ctx->done = 1;
>   //ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
>   //              "%s: rc = %d, uri:\"%V\"", __FUNCTION__, rc, &r->uri);
> 
>   if ((rc != 0) && (rc != NGX_DECLINED)) {
>     return rc;
>   }
> 
>   // per http://www.nginxguts.com/2011/01/phases/, ACCESS_PHASE handler should return NGX_OK here.
>   // however, returning NGX_OK causes nginx to hang.
>   return NGX_DECLINED;
> }
> 
> static ngx_int_t
> ngx_http_module_init (ngx_conf_t *cf)
> {
>   ngx_http_handler_pt       *hptr;
>   ngx_http_core_main_conf_t *cmcf;
> 
>   cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
>   hptr = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
> 
>   if (hptr == NULL) {
>     ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Cannot retrieve Nginx access phase handler pointer");
>     return NGX_ERROR;
>   }
> 
>   *hptr = ngx_http_request_handler;
>   ngx_log_error(NGX_LOG_INFO, cf->log, 0, "[init] Installed request handler");
> 
>   return NGX_OK;
> }
> 
> 
>> On Thu, Jul 5, 2018 at 5:44 PM Dk Jack <dnj0496 at gmail.com> wrote:
>> Hi,
>> I have an nginx module. The purpose of my module is to inspect every request and make a binary decision (i.e drop or allow). When dropping, I am sending a custom status code and response message. I've setup my module handler to be called in the NGX_HTTP_REWRITE_PHASE. Things seem to be working fine for the most part except for a small issue.
>> 
>> I am seeing 'header already sent' messages in the nginx error.log. In my handler, I create a context for my module and attach it request using the ngx_http_set_ctx call. I am using the context to store some info and also to prevent my module from processing the same request multiple times. My module processes the request only once.
>> 
>> I get the 'header already sent' message only for a fraction of the requests. The messages seem to be generated only for requests that I allowed in my module. In my module handler, I return an NGX_DECLINED return code when I allow a request. The message is not generated for every allowed request but only for some of the allowed requests. When the error is generated it is always for POST request and not all POST requests cause this error message to be logged. 
>> 
>> Could someone explain what could be going on here or where I should look at next to debug this further? Any pointers are appreciated. Thanks.
>> 
>> Dk.
>> 
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20180707/22648279/attachment-0001.html>


More information about the nginx-devel mailing list