Ngx_http_send_special_response

Hi

I am appreciate any help I can get on the following issues.

I am writing my own module.

  1. I can see in function ngx_http_send_special_response
    that it calculates the content length of the error page even if the
    request signed as header only (r->header_only = 1)
    and set the content length header with value, after sending the header
    it does not send the body ( because r->header_only = 1)
    so the response arrive with content length different than 0 but without
    body

Is it a BUG?

2.In the module I am trying to redirect the request with status code 302
(NGX_HTTP_MOVED_TEMPORARILY)
Trying to user->headers_out.location for the Alternate URL failed, I
looked in the code and saw the Location must start with “/” - why?

In the end I add it to r->headers_out.headers
using header = ngx_list_push(&r->headers_out.headers);
Is it the write way to do it?

  1. Can you explain please the different between
    a. r->headers_out.content_length_n
    b. r->headers_out.content_length

  2. Can you explain the usage of the hash field in ngx_table_elt_t

Thanks
Hagai A.

Hello!

On Mon, Apr 16, 2012 at 01:53:39AM -0700, hagai avrahami wrote:

and set the content length header with value, after sending the header it does
not send the body ( because r->header_only = 1)
so the response arrive with content length different than 0 but without body

Is it a BUG?

No. The r->header_only flag should is set when body isn’t
expected per protocol (HEAD requests, 304 responses). Having
Content-Length present in such responses is ok.

2.In the module I am trying to redirect the request with status code 302
(NGX_HTTP_MOVED_TEMPORARILY)
Trying to user->headers_out.location for the Alternate URL failed, I looked in
the code and saw the Location must start with “/” - why?

You have to set it correctly, i.e. add to r->headers_out.headers
and link to r->headers_out.location. If it starts with “/” it
works even if set incorrectly due to adding of a server_name,
that’s probably what confused you.

In the end I add it to r->headers_out.headers
using header = ngx_list_push(&r->headers_out.headers);
Is it the write way to do it?

  1. Can you explain please the different between
    a. r->headers_out.content_length_n
    b. r->headers_out.content_length

The content_length_n is a numeric length, this what you normaly
should set when generating response in nginx. The content_length
is a pointer to a headers array element, it might be present if
there is string representation of a Content-Length header
available for some reason (e.g. from a backend).

  1. Can you explain the usage of the hash field in ngx_table_elt_t

Normally the hash field is used for fast lookups in hash
structures. In case of r->headers_out it’s usually just set to 1
indicate the header is valid (or reset to 0 to indicate the
header should not be sent as it was superseeded by some other
header).

Maxim D.

WOW thanks for the quick and elaborate response

So what is the right way to send response with status code 302 on GET
request but
with content length 0 and no body (I want to redirect the request to
other Server)

Thanks

Hagai

Hello!

On Mon, Apr 16, 2012 at 04:29:18AM -0700, hagai avrahami wrote:

WOW thanks for the quick and elaborate response

So what is the right way to send response with status code 302 on GET request
but
with content length 0 and no body (I want to redirect the request to other
Server)

Easiest solution is to just write

return 302 $where;

in config. :slight_smile:

From the code point of view (assuming content handler context),
something like this should work:

ngx_table_elt_t  *h;

ngx_http_clear_location(r);

h = ngx_list_push(&r->headers_out.headers);
if (h == NULL) {
    return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

h->hash = 1;
ngx_str_set(&h->key, "Location");

h->value.data = ...
h->value.len = ...

r->headers_out.location = h;

return NGX_HTTP_MOVED_TEMPORARILY;

Maxim D.

To: [email protected]

that’s probably what confused you.
should set when generating response in nginx. The content_length
header).

Maxim D.


nginx mailing list
[email protected]
nginx Info Page

Hi
Thanks

The redirect response is from content handler context.

Using the code you added

cause Nginx to send back the Error Page (302) with Content-Length and
Content-Type (“test/html”) (And I am trying avoid that) without Body

That’s why I assumed using r->header_only = 1 will solve my problem but
as you explained it is used for other cases.
please see that in ngx_http_send_special_response when this flag set to
1 the Header is set with this fields but no body in response (I think
this is not a good result)

if adding in the beginning of the function
(ngx_http_send_special_response) the following code it solves the
problem:

if (r->header_only == 1)
{
ngx_http_clear_accept_ranges®;
ngx_http_clear_last_modified®;

rc = ngx_http_send_header®;

return rc;
}

Is there any other way I can avoid content length and content-type in
302 response
Thanks
Hagai

Hello!

On Mon, Apr 16, 2012 at 08:14:25AM -0700, hagai avrahami wrote:

Hi
Thanks

The redirect response is from content handler context.

Using the code you added

cause Nginx to send back the Error Page (302) with
Content-Length and Content-Type (“test/html”) (And I am trying
avoid that) without Body

Ah, sorry, I missed you want to send 302 with an empty body, not
just 302. Then instead of

return NGX_HTTP_MOVED_TEMPORARY;

you have to send actual response youself, like this:

r->headers_out.status = NGX_HTTP_MOVED_TEMPORARY;
r->headers_out.content_length_n = 0;

rc = ngx_http_send_header(r);

if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
    return rc;
}

return ngx_http_send_special(r, NGX_HTTP_LAST);

Maxim D.

Thanks!