Mercurial > hg > nginx
annotate src/http/modules/ngx_http_empty_gif_module.c @ 4247:b79dbadb3d5e stable-1.0
Merging r4147, r4148, r4149, r4150, r4207:
Fixes of combination of error_page and return directives:
*) Fix for incorrect 201 replies from dav module.
Replies with 201 code contain body, and we should clearly indicate it's
empty if it's empty. Before 0.8.32 chunked was explicitly disabled for
201 replies and as a result empty body was indicated by connection close
(not perfect, but worked). Since 0.8.32 chunked is enabled, and this
causes incorrect responses from dav module when HTTP/1.1 is used: with
"Transfer-Encoding: chunked" but no chunks at all.
Fix is to actually return empty body in special response handler instead
of abusing r->header_only flag.
See here for initial report:
http://mailman.nginx.org/pipermail/nginx-ru/2010-October/037535.html
*) Fix for double content when return is used in error_page handler.
Test case:
location / {
error_page 405 /nope;
return 405;
}
location /nope {
return 200;
}
This is expected to return 405 with empty body, but in 0.8.42+ will return
builtin 405 error page as well (though not counted in Content-Length, thus
breaking protocol).
Fix is to use status provided by rewrite script execution in case
it's less than NGX_HTTP_BAD_REQUEST even if r->error_status set. This
check is in line with one in ngx_http_script_return_code().
Note that this patch also changes behaviour for "return 302 ..." and
"rewrite ... redirect" used as error handler. E.g.
location / {
error_page 405 /redirect;
return 405;
}
location /redirect {
rewrite ^ http://example.com/;
}
will actually return redirect to "http://example.com/" instead of builtin
405 error page with meaningless Location header. This looks like correct
change and it's in line with what happens on e.g. directory redirects
in error handlers.
*) Fix for "return 202" not discarding body.
Big POST (not fully preread) to a
location / {
return 202;
}
resulted in incorrect behaviour due to "return" code path not calling
ngx_http_discard_request_body(). The same applies to all "return" used
with 2xx/3xx codes except 201 and 204, and to all "return ... text" uses.
Fix is to add ngx_http_discard_request_body() call to
ngx_http_send_response() function where it looks appropriate.
Discard body call from emtpy gif module removed as it's now redundant.
Reported by Pyry Hakulinen, see
http://mailman.nginx.org/pipermail/nginx/2011-August/028503.html
*) Incorrect special case for "return 204" removed.
The special case in question leads to replies without body in
configuration like
location / { error_page 404 /zero; return 404; }
location /zero { return 204; }
while replies with empty body are expected per protocol specs.
Correct one will look like
if (status == NGX_HTTP_NO_CONTENT) {
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || r->header_only) {
return rc;
}
return ngx_http_send_special(r, NGX_HTTP_LAST);
}
though it looks like it's better to drop this special case at all.
*) Clear old Location header (if any) while adding a new one.
This prevents incorrect behaviour when another redirect is issued within
error_page 302 handler.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 01 Nov 2011 13:45:33 +0000 |
parents | c0113b6648de |
children | d620f497c50f |
rev | line source |
---|---|
577 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 #include <ngx_config.h> | |
7 #include <ngx_core.h> | |
8 #include <ngx_http.h> | |
9 | |
10 | |
11 static char *ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t *cmd, | |
12 void *conf); | |
13 | |
14 static ngx_command_t ngx_http_empty_gif_commands[] = { | |
15 | |
16 { ngx_string("empty_gif"), | |
17 NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, | |
18 ngx_http_empty_gif, | |
19 0, | |
20 0, | |
21 NULL }, | |
22 | |
23 ngx_null_command | |
24 }; | |
25 | |
26 | |
27 /* the minimal single pixel transparent GIF, 43 bytes */ | |
28 | |
29 static u_char ngx_empty_gif[] = { | |
30 | |
581 | 31 'G', 'I', 'F', '8', '9', 'a', /* header */ |
577 | 32 |
581 | 33 /* logical screen descriptor */ |
34 0x01, 0x00, /* logical screen width */ | |
35 0x01, 0x00, /* logical screen height */ | |
36 0x80, /* global 1-bit color table */ | |
37 0x01, /* background color #1 */ | |
38 0x00, /* no aspect ratio */ | |
577 | 39 |
581 | 40 /* global color table */ |
41 0x00, 0x00, 0x00, /* #0: black */ | |
42 0xff, 0xff, 0xff, /* #1: white */ | |
577 | 43 |
581 | 44 /* graphic control extension */ |
45 0x21, /* extension introducer */ | |
46 0xf9, /* graphic control label */ | |
47 0x04, /* block size */ | |
48 0x01, /* transparent color is given, */ | |
49 /* no disposal specified, */ | |
50 /* user input is not expected */ | |
51 0x00, 0x00, /* delay time */ | |
52 0x01, /* transparent color #1 */ | |
53 0x00, /* block terminator */ | |
577 | 54 |
581 | 55 /* image descriptor */ |
56 0x2c, /* image separator */ | |
57 0x00, 0x00, /* image left position */ | |
58 0x00, 0x00, /* image top position */ | |
59 0x01, 0x00, /* image width */ | |
60 0x01, 0x00, /* image height */ | |
61 0x00, /* no local color table, no interlaced */ | |
577 | 62 |
581 | 63 /* table based image data */ |
64 0x02, /* LZW minimum code size, */ | |
65 /* must be at least 2-bit */ | |
66 0x02, /* block size */ | |
577 | 67 0x4c, 0x01, /* compressed bytes 01_001_100, 0000000_1 */ |
581 | 68 /* 100: clear code */ |
69 /* 001: 1 */ | |
70 /* 101: end of information code */ | |
71 0x00, /* block terminator */ | |
577 | 72 |
581 | 73 0x3B /* trailer */ |
577 | 74 }; |
75 | |
76 | |
667 | 77 static ngx_http_module_t ngx_http_empty_gif_module_ctx = { |
577 | 78 NULL, /* preconfiguration */ |
79 NULL, /* postconfiguration */ | |
80 | |
81 NULL, /* create main configuration */ | |
82 NULL, /* init main configuration */ | |
83 | |
84 NULL, /* create server configuration */ | |
85 NULL, /* merge server configuration */ | |
86 | |
87 NULL, /* create location configuration */ | |
88 NULL /* merge location configuration */ | |
89 }; | |
90 | |
91 | |
92 ngx_module_t ngx_http_empty_gif_module = { | |
93 NGX_MODULE_V1, | |
94 &ngx_http_empty_gif_module_ctx, /* module context */ | |
95 ngx_http_empty_gif_commands, /* module directives */ | |
96 NGX_HTTP_MODULE, /* module type */ | |
97 NULL, /* init master */ | |
98 NULL, /* init module */ | |
99 NULL, /* init process */ | |
100 NULL, /* init thread */ | |
101 NULL, /* exit thread */ | |
102 NULL, /* exit process */ | |
103 NULL, /* exit master */ | |
104 NGX_MODULE_V1_PADDING | |
105 }; | |
106 | |
107 | |
3635
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
108 static ngx_str_t ngx_http_gif_type = ngx_string("image/gif"); |
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
109 |
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
110 |
577 | 111 static ngx_int_t |
112 ngx_http_empty_gif_handler(ngx_http_request_t *r) | |
113 { | |
3635
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
114 ngx_http_complex_value_t cv; |
577 | 115 |
645 | 116 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { |
577 | 117 return NGX_HTTP_NOT_ALLOWED; |
118 } | |
119 | |
3635
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
120 ngx_memzero(&cv, sizeof(ngx_http_complex_value_t)); |
577 | 121 |
3635
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
122 cv.value.len = sizeof(ngx_empty_gif); |
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
123 cv.value.data = ngx_empty_gif; |
577 | 124 r->headers_out.last_modified_time = 23349600; |
125 | |
3635
c0113b6648de
use ngx_http_send_response() in empty_gif
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
126 return ngx_http_send_response(r, NGX_HTTP_OK, &ngx_http_gif_type, &cv); |
577 | 127 } |
128 | |
129 | |
130 static char * | |
131 ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
132 { | |
133 ngx_http_core_loc_conf_t *clcf; | |
134 | |
135 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
136 clcf->handler = ngx_http_empty_gif_handler; | |
137 | |
138 return NGX_CONF_OK; | |
139 } |