header already sent
Dk Jack
dnj0496 at gmail.com
Mon Jul 9 23:43:04 UTC 2018
@Hung Nguyen,
Sorry did not see your response. Looks like my email settings were
incorrect and I was not receiving the emails.
I am looking for a way to send custom response without having to change the
config.
Dk.
On Fri, Jul 6, 2018 at 2:33 PM 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.
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20180709/11abecb5/attachment-0001.html>
More information about the nginx-devel
mailing list