comparison src/http/ngx_http_header_filter_module.c @ 58:b55cbf18157e NGINX_0_1_29

nginx 0.1.29 *) Feature: the ngx_http_ssi_module supports "include virtual" command. *) Feature: the ngx_http_ssi_module supports the condition command like 'if expr="$NAME"' and "else" and "endif" commands. Only one nested level is supported. *) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and DATE_GMT variables and "config timefmt" command. *) Feature: the "ssi_ignore_recycled_buffers" directive. *) Bugfix: the "echo" command did not show the default value for the empty QUERY_STRING variable. *) Change: the ngx_http_proxy_module was rewritten. *) Feature: the "proxy_redirect", "proxy_pass_request_headers", "proxy_pass_request_body", and "proxy_method" directives. *) Feature: the "proxy_set_header" directive. The "proxy_x_var" was canceled and must be replaced with the proxy_set_header directive. *) Change: the "proxy_preserve_host" is canceled and must be replaced with the "proxy_set_header Host $host" and the "proxy_redirect off" directives, the "proxy_set_header Host $host:$proxy_port" directive and the appropriate proxy_redirect directives. *) Change: the "proxy_set_x_real_ip" is canceled and must be replaced with the "proxy_set_header X-Real-IP $remote_addr" directive. *) Change: the "proxy_add_x_forwarded_for" is canceled and must be replaced with the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for" directive. *) Change: the "proxy_set_x_url" is canceled and must be replaced with the "proxy_set_header X-URL http://$host:$server_port$request_uri" directive. *) Feature: the "fastcgi_param" directive. *) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params" directive are canceled and must be replaced with the fastcgi_param directives. *) Feature: the "index" directive can use the variables. *) Feature: the "index" directive can be used at http and server levels. *) Change: the last index only in the "index" directive can be absolute. *) Feature: the "rewrite" directive can use the variables. *) Feature: the "internal" directive. *) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME, REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables. *) Change: nginx now passes the invalid lines in a client request headers or a backend response header. *) Bugfix: if the backend did not transfer response for a long time and the "send_timeout" was less than "proxy_read_timeout", then nginx returned the 408 response. *) Bugfix: the segmentation fault was occurred if the backend sent an invalid line in response header; bug appeared in 0.1.26. *) Bugfix: the segmentation fault may occurred in FastCGI fault tolerance configuration. *) Bugfix: the "expires" directive did not remove the previous "Expires" and "Cache-Control" headers. *) Bugfix: nginx did not take into account trailing dot in "Host" header line. *) Bugfix: the ngx_http_auth_module did not work under Linux. *) Bugfix: the rewrite directive worked incorrectly, if the arguments were in a request. *) Bugfix: nginx could not be built on MacOS X.
author Igor Sysoev <http://sysoev.ru>
date Thu, 12 May 2005 00:00:00 +0400
parents 72eb30262aac
children df7d3fff122b
comparison
equal deleted inserted replaced
57:5df375c55338 58:b55cbf18157e
13 static ngx_int_t ngx_http_header_filter_init(ngx_cycle_t *cycle); 13 static ngx_int_t ngx_http_header_filter_init(ngx_cycle_t *cycle);
14 static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r); 14 static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
15 15
16 16
17 static ngx_http_module_t ngx_http_header_filter_module_ctx = { 17 static ngx_http_module_t ngx_http_header_filter_module_ctx = {
18 NULL, /* pre conf */ 18 NULL, /* preconfiguration */
19 NULL, /* postconfiguration */
19 20
20 NULL, /* create main configuration */ 21 NULL, /* create main configuration */
21 NULL, /* init main configuration */ 22 NULL, /* init main configuration */
22 23
23 NULL, /* create server configuration */ 24 NULL, /* create server configuration */
27 NULL, /* merge location configuration */ 28 NULL, /* merge location configuration */
28 }; 29 };
29 30
30 31
31 ngx_module_t ngx_http_header_filter_module = { 32 ngx_module_t ngx_http_header_filter_module = {
32 NGX_MODULE, 33 NGX_MODULE_V1,
33 &ngx_http_header_filter_module_ctx, /* module context */ 34 &ngx_http_header_filter_module_ctx, /* module context */
34 NULL, /* module directives */ 35 NULL, /* module directives */
35 NGX_HTTP_MODULE, /* module type */ 36 NGX_HTTP_MODULE, /* module type */
36 ngx_http_header_filter_init, /* init module */ 37 ngx_http_header_filter_init, /* init module */
37 NULL /* init process */ 38 NULL /* init process */
38 }; 39 };
39 40
40 41
41 static char server_string[] = "Server: " NGINX_VER CRLF; 42 static char ngx_http_server_string[] = "Server: " NGINX_VER CRLF;
42 43
43 44
44 static ngx_str_t http_codes[] = { 45 static ngx_str_t ngx_http_status_lines[] = {
45 46
46 ngx_string("200 OK"), 47 ngx_string("200 OK"),
47 ngx_null_string, /* "201 Created" */ 48 ngx_null_string, /* "201 Created" */
48 ngx_null_string, /* "202 Accepted" */ 49 ngx_null_string, /* "202 Accepted" */
49 ngx_null_string, /* "203 Non-Authoritative Information" */ 50 ngx_null_string, /* "203 Non-Authoritative Information" */
113 /* ngx_null_string, */ /* "509 unused" */ 114 /* ngx_null_string, */ /* "509 unused" */
114 /* ngx_null_string, */ /* "510 Not Extended" */ 115 /* ngx_null_string, */ /* "510 Not Extended" */
115 }; 116 };
116 117
117 118
118 ngx_http_header_t ngx_http_headers_out[] = { 119 ngx_http_header0_t ngx_http_headers_out[] = {
119 { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) }, 120 { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
120 { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) }, 121 { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) },
122 #if 0
121 { ngx_string("Content-Type"), 123 { ngx_string("Content-Type"),
122 offsetof(ngx_http_headers_out_t, content_type) }, 124 offsetof(ngx_http_headers_out_t, content_type) },
125 #endif
123 { ngx_string("Content-Length"), 126 { ngx_string("Content-Length"),
124 offsetof(ngx_http_headers_out_t, content_length) }, 127 offsetof(ngx_http_headers_out_t, content_length) },
125 { ngx_string("Content-Encoding"), 128 { ngx_string("Content-Encoding"),
126 offsetof(ngx_http_headers_out_t, content_encoding) }, 129 offsetof(ngx_http_headers_out_t, content_encoding) },
127 { ngx_string("Location"), offsetof(ngx_http_headers_out_t, location) }, 130 { ngx_string("Location"), offsetof(ngx_http_headers_out_t, location) },
148 ngx_chain_t out; 151 ngx_chain_t out;
149 ngx_list_part_t *part; 152 ngx_list_part_t *part;
150 ngx_table_elt_t *header; 153 ngx_table_elt_t *header;
151 ngx_http_core_loc_conf_t *clcf; 154 ngx_http_core_loc_conf_t *clcf;
152 155
156 if (r->main) {
157 return NGX_OK;
158 }
159
153 if (r->http_version < NGX_HTTP_VERSION_10) { 160 if (r->http_version < NGX_HTTP_VERSION_10) {
154 return NGX_OK; 161 return NGX_OK;
155 } 162 }
156 163
157 if (r->method == NGX_HTTP_HEAD) { 164 if (r->method == NGX_HTTP_HEAD) {
207 + NGX_HTTP_LEVEL_200 214 + NGX_HTTP_LEVEL_200
208 + NGX_HTTP_LEVEL_300 215 + NGX_HTTP_LEVEL_300
209 + NGX_HTTP_LEVEL_400; 216 + NGX_HTTP_LEVEL_400;
210 } 217 }
211 218
212 len += http_codes[status].len; 219 len += ngx_http_status_lines[status].len;
213 } 220 }
214 221
215 if (r->headers_out.server && r->headers_out.server->key.len) { 222 if (r->headers_out.server == NULL) {
216 len += r->headers_out.server->key.len 223 len += sizeof(ngx_http_server_string) - 1;
217 + r->headers_out.server->value.len + 2; 224 }
218 } else { 225
219 len += sizeof(server_string) - 1; 226 if (r->headers_out.date == NULL) {
220 }
221
222 if (r->headers_out.date && r->headers_out.date->key.len) {
223 len += r->headers_out.date->key.len
224 + r->headers_out.date->value.len + 2;
225 } else {
226 len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; 227 len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
227 } 228 }
228 229
229 if (r->headers_out.content_length == NULL) { 230 if (r->headers_out.content_type.len) {
230 if (r->headers_out.content_length_n >= 0) {
231 len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
232 }
233 }
234
235 if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
236 r->headers_out.content_type->key.len = 0;
237 len += sizeof("Content-Type: ") - 1 231 len += sizeof("Content-Type: ") - 1
238 + r->headers_out.content_type->value.len + 2; 232 + r->headers_out.content_type.len + 2;
239 233
240 if (r->headers_out.charset.len) { 234 if (r->headers_out.charset.len) {
241 len += sizeof("; charset=") - 1 + r->headers_out.charset.len; 235 len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
242 } 236 }
237 }
238
239 if (r->headers_out.content_length == NULL
240 && r->headers_out.content_length_n >= 0)
241 {
242 len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
243 }
244
245 if (r->headers_out.last_modified == NULL
246 && r->headers_out.last_modified_time != -1)
247 {
248 len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
243 } 249 }
244 250
245 if (r->headers_out.location 251 if (r->headers_out.location
246 && r->headers_out.location->value.len 252 && r->headers_out.location->value.len
247 && r->headers_out.location->value.data[0] == '/') 253 && r->headers_out.location->value.data[0] == '/')
248 { 254 {
249 r->headers_out.location->key.len = 0; 255 r->headers_out.location->hash = 0;
256
250 len += sizeof("Location: http://") - 1 257 len += sizeof("Location: http://") - 1
251 + r->server_name.len + r->headers_out.location->value.len + 2; 258 + r->server_name.len + r->headers_out.location->value.len + 2;
252 259
253 if (r->port != 80) { 260 if (r->port != 80) {
254 len += r->port_text->len; 261 len += r->port_text->len;
255 } 262 }
256 }
257
258 if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
259 len += r->headers_out.last_modified->key.len
260 + r->headers_out.last_modified->value.len + 2;
261
262 } else if (r->headers_out.last_modified_time != -1) {
263 len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
264 } 263 }
265 264
266 if (r->chunked) { 265 if (r->chunked) {
267 len += sizeof("Transfer-Encoding: chunked" CRLF) - 1; 266 len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
268 } 267 }
301 part = part->next; 300 part = part->next;
302 header = part->elts; 301 header = part->elts;
303 i = 0; 302 i = 0;
304 } 303 }
305 304
306 if (header[i].key.len == 0) { 305 if (header[i].hash == 0) {
307 continue; 306 continue;
308 } 307 }
309 308
310 len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len 309 len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len
311 + sizeof(CRLF) - 1; 310 + sizeof(CRLF) - 1;
323 if (r->headers_out.status_line.len) { 322 if (r->headers_out.status_line.len) {
324 b->last = ngx_cpymem(b->last, r->headers_out.status_line.data, 323 b->last = ngx_cpymem(b->last, r->headers_out.status_line.data,
325 r->headers_out.status_line.len); 324 r->headers_out.status_line.len);
326 325
327 } else { 326 } else {
328 b->last = ngx_cpymem(b->last, http_codes[status].data, 327 b->last = ngx_cpymem(b->last, ngx_http_status_lines[status].data,
329 http_codes[status].len); 328 ngx_http_status_lines[status].len);
330 } 329 }
331 *b->last++ = CR; *b->last++ = LF; 330 *b->last++ = CR; *b->last++ = LF;
332 331
333 if (!(r->headers_out.server && r->headers_out.server->key.len)) { 332 if (r->headers_out.server == NULL) {
334 b->last = ngx_cpymem(b->last, server_string, sizeof(server_string) - 1); 333 b->last = ngx_cpymem(b->last, ngx_http_server_string,
335 } 334 sizeof(ngx_http_server_string) - 1);
336 335 }
337 if (!(r->headers_out.date && r->headers_out.date->key.len)) { 336
337 if (r->headers_out.date == NULL) {
338 b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1); 338 b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1);
339 b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, 339 b->last = ngx_cpymem(b->last, ngx_cached_http_time.data,
340 ngx_cached_http_time.len); 340 ngx_cached_http_time.len);
341 341
342 *b->last++ = CR; *b->last++ = LF; 342 *b->last++ = CR; *b->last++ = LF;
343 } 343 }
344 344
345 if (r->headers_out.content_length == NULL) { 345 if (r->headers_out.content_type.len) {
346 if (r->headers_out.content_length_n >= 0) {
347 b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
348 r->headers_out.content_length_n);
349 }
350 }
351
352 if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
353 b->last = ngx_cpymem(b->last, "Content-Type: ", 346 b->last = ngx_cpymem(b->last, "Content-Type: ",
354 sizeof("Content-Type: ") - 1); 347 sizeof("Content-Type: ") - 1);
355 p = b->last; 348 p = b->last;
356 b->last = ngx_cpymem(b->last, r->headers_out.content_type->value.data, 349 b->last = ngx_cpymem(b->last, r->headers_out.content_type.data,
357 r->headers_out.content_type->value.len); 350 r->headers_out.content_type.len);
358 351
359 if (r->headers_out.charset.len) { 352 if (r->headers_out.charset.len) {
360 b->last = ngx_cpymem(b->last, "; charset=", 353 b->last = ngx_cpymem(b->last, "; charset=",
361 sizeof("; charset=") - 1); 354 sizeof("; charset=") - 1);
362 b->last = ngx_cpymem(b->last, r->headers_out.charset.data, 355 b->last = ngx_cpymem(b->last, r->headers_out.charset.data,
363 r->headers_out.charset.len); 356 r->headers_out.charset.len);
364 357
365 r->headers_out.content_type->value.len = b->last - p; 358 /* update r->headers_out.content_type for possible logging */
366 r->headers_out.content_type->value.data = p; 359
367 } 360 r->headers_out.content_type.len = b->last - p;
361 r->headers_out.content_type.data = p;
362 }
363
364 *b->last++ = CR; *b->last++ = LF;
365 }
366
367 if (r->headers_out.content_length == NULL
368 && r->headers_out.content_length_n >= 0)
369 {
370 b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
371 r->headers_out.content_length_n);
372 }
373
374 if (r->headers_out.last_modified == NULL
375 && r->headers_out.last_modified_time != -1)
376 {
377 b->last = ngx_cpymem(b->last, "Last-Modified: ",
378 sizeof("Last-Modified: ") - 1);
379 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
368 380
369 *b->last++ = CR; *b->last++ = LF; 381 *b->last++ = CR; *b->last++ = LF;
370 } 382 }
371 383
372 if (r->headers_out.location 384 if (r->headers_out.location
384 } 396 }
385 397
386 b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, 398 b->last = ngx_cpymem(b->last, r->headers_out.location->value.data,
387 r->headers_out.location->value.len); 399 r->headers_out.location->value.len);
388 400
401 /* update r->headers_out.location->value for possible logging */
402
389 r->headers_out.location->value.len = b->last - p; 403 r->headers_out.location->value.len = b->last - p;
390 r->headers_out.location->value.data = p; 404 r->headers_out.location->value.data = p;
391
392 *b->last++ = CR; *b->last++ = LF;
393 }
394
395 if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
396 && r->headers_out.last_modified_time != -1)
397 {
398 b->last = ngx_cpymem(b->last, "Last-Modified: ",
399 sizeof("Last-Modified: ") - 1);
400 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
401 405
402 *b->last++ = CR; *b->last++ = LF; 406 *b->last++ = CR; *b->last++ = LF;
403 } 407 }
404 408
405 if (r->chunked) { 409 if (r->chunked) {
434 part = part->next; 438 part = part->next;
435 header = part->elts; 439 header = part->elts;
436 i = 0; 440 i = 0;
437 } 441 }
438 442
439 if (header[i].key.len == 0) { 443 if (header[i].hash == 0) {
440 continue; 444 continue;
441 } 445 }
442 446
443 b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len); 447 b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
444 *b->last++ = ':' ; *b->last++ = ' ' ; 448 *b->last++ = ':' ; *b->last++ = ' ' ;