Mercurial > hg > nginx-vendor-0-5
comparison src/http/ngx_http_upstream.c @ 322:56675f002600 NGINX_0_5_31
nginx 0.5.31
*) Feature: named locations.
*) Feature: the "proxy_store" and "fastcgi_store" directives.
*) Feature: the "proxy_store_access" and "fastcgi_store_access"
directives.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 15 Aug 2007 00:00:00 +0400 |
parents | 1e9e2c5e7c14 |
children | 7cf404023f50 |
comparison
equal
deleted
inserted
replaced
321:6762c33c7da8 | 322:56675f002600 |
---|---|
31 static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data); | 31 static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data); |
32 static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, | 32 static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, |
33 ssize_t bytes); | 33 ssize_t bytes); |
34 static void ngx_http_upstream_process_downstream(ngx_http_request_t *r); | 34 static void ngx_http_upstream_process_downstream(ngx_http_request_t *r); |
35 static void ngx_http_upstream_process_body(ngx_event_t *ev); | 35 static void ngx_http_upstream_process_body(ngx_event_t *ev); |
36 static void ngx_http_upstream_store(ngx_http_request_t *r, | |
37 ngx_http_upstream_t *u); | |
36 static void ngx_http_upstream_dummy_handler(ngx_event_t *wev); | 38 static void ngx_http_upstream_dummy_handler(ngx_event_t *wev); |
37 static void ngx_http_upstream_next(ngx_http_request_t *r, | 39 static void ngx_http_upstream_next(ngx_http_request_t *r, |
38 ngx_http_upstream_t *u, ngx_uint_t ft_type); | 40 ngx_http_upstream_t *u, ngx_uint_t ft_type); |
39 static void ngx_http_upstream_cleanup(void *data); | 41 static void ngx_http_upstream_cleanup(void *data); |
40 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, | 42 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, |
114 ngx_http_upstream_process_header_line, | 116 ngx_http_upstream_process_header_line, |
115 offsetof(ngx_http_upstream_headers_in_t, date), | 117 offsetof(ngx_http_upstream_headers_in_t, date), |
116 ngx_http_upstream_copy_header_line, | 118 ngx_http_upstream_copy_header_line, |
117 offsetof(ngx_http_headers_out_t, date), 0 }, | 119 offsetof(ngx_http_headers_out_t, date), 0 }, |
118 | 120 |
121 { ngx_string("Last-Modified"), | |
122 ngx_http_upstream_process_header_line, | |
123 offsetof(ngx_http_upstream_headers_in_t, last_modified), | |
124 ngx_http_upstream_copy_header_line, | |
125 offsetof(ngx_http_headers_out_t, last_modified), 0 }, | |
126 | |
119 { ngx_string("Server"), | 127 { ngx_string("Server"), |
120 ngx_http_upstream_process_header_line, | 128 ngx_http_upstream_process_header_line, |
121 offsetof(ngx_http_upstream_headers_in_t, server), | 129 offsetof(ngx_http_upstream_headers_in_t, server), |
122 ngx_http_upstream_copy_header_line, | 130 ngx_http_upstream_copy_header_line, |
123 offsetof(ngx_http_headers_out_t, server), 0 }, | 131 offsetof(ngx_http_headers_out_t, server), 0 }, |
362 | 370 |
363 cln->handler = ngx_http_upstream_cleanup; | 371 cln->handler = ngx_http_upstream_cleanup; |
364 cln->data = r; | 372 cln->data = r; |
365 u->cleanup = &cln->handler; | 373 u->cleanup = &cln->handler; |
366 | 374 |
375 u->store = (u->conf->store || u->conf->store_lengths); | |
376 | |
367 ngx_http_upstream_connect(r, u); | 377 ngx_http_upstream_connect(r, u); |
368 } | 378 } |
369 | 379 |
370 | 380 |
371 static void | 381 static void |
422 | 432 |
423 if (ev->kq_errno) { | 433 if (ev->kq_errno) { |
424 ev->error = 1; | 434 ev->error = 1; |
425 } | 435 } |
426 | 436 |
427 if (!u->cachable && u->peer.connection) { | 437 if (!u->cachable && !u->store && u->peer.connection) { |
428 ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, | 438 ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, |
429 "kevent() reported that client closed prematurely " | 439 "kevent() reported that client closed prematurely " |
430 "connection, so upstream connection is closed too"); | 440 "connection, so upstream connection is closed too"); |
431 ngx_http_upstream_finalize_request(r, u, | 441 ngx_http_upstream_finalize_request(r, u, |
432 NGX_HTTP_CLIENT_CLOSED_REQUEST); | 442 NGX_HTTP_CLIENT_CLOSED_REQUEST); |
488 } | 498 } |
489 | 499 |
490 ev->eof = 1; | 500 ev->eof = 1; |
491 c->error = 1; | 501 c->error = 1; |
492 | 502 |
493 if (!u->cachable && u->peer.connection) { | 503 if (!u->cachable && !u->store && u->peer.connection) { |
494 ngx_log_error(NGX_LOG_INFO, ev->log, err, | 504 ngx_log_error(NGX_LOG_INFO, ev->log, err, |
495 "client closed prematurely connection, " | 505 "client closed prematurely connection, " |
496 "so upstream connection is closed too"); | 506 "so upstream connection is closed too"); |
497 ngx_http_upstream_finalize_request(r, u, | 507 ngx_http_upstream_finalize_request(r, u, |
498 NGX_HTTP_CLIENT_CLOSED_REQUEST); | 508 NGX_HTTP_CLIENT_CLOSED_REQUEST); |
1521 p->upstream = u->peer.connection; | 1531 p->upstream = u->peer.connection; |
1522 p->downstream = c; | 1532 p->downstream = c; |
1523 p->pool = r->pool; | 1533 p->pool = r->pool; |
1524 p->log = c->log; | 1534 p->log = c->log; |
1525 | 1535 |
1526 p->cachable = u->cachable; | 1536 p->cachable = u->cachable || u->store; |
1527 | 1537 |
1528 p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); | 1538 p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); |
1529 if (p->temp_file == NULL) { | 1539 if (p->temp_file == NULL) { |
1530 ngx_http_upstream_finalize_request(r, u, 0); | 1540 ngx_http_upstream_finalize_request(r, u, 0); |
1531 return; | 1541 return; |
1534 p->temp_file->file.fd = NGX_INVALID_FILE; | 1544 p->temp_file->file.fd = NGX_INVALID_FILE; |
1535 p->temp_file->file.log = c->log; | 1545 p->temp_file->file.log = c->log; |
1536 p->temp_file->path = u->conf->temp_path; | 1546 p->temp_file->path = u->conf->temp_path; |
1537 p->temp_file->pool = r->pool; | 1547 p->temp_file->pool = r->pool; |
1538 | 1548 |
1539 if (u->cachable) { | 1549 if (u->cachable || u->store) { |
1540 p->temp_file->persistent = 1; | 1550 p->temp_file->persistent = 1; |
1551 | |
1541 } else { | 1552 } else { |
1542 p->temp_file->log_level = NGX_LOG_WARN; | 1553 p->temp_file->log_level = NGX_LOG_WARN; |
1543 p->temp_file->warn = "an upstream response is buffered " | 1554 p->temp_file->warn = "an upstream response is buffered " |
1544 "to a temporary file"; | 1555 "to a temporary file"; |
1545 } | 1556 } |
1550 p->preread_bufs = ngx_alloc_chain_link(r->pool); | 1561 p->preread_bufs = ngx_alloc_chain_link(r->pool); |
1551 if (p->preread_bufs == NULL) { | 1562 if (p->preread_bufs == NULL) { |
1552 ngx_http_upstream_finalize_request(r, u, 0); | 1563 ngx_http_upstream_finalize_request(r, u, 0); |
1553 return; | 1564 return; |
1554 } | 1565 } |
1566 | |
1555 p->preread_bufs->buf = &u->buffer; | 1567 p->preread_bufs->buf = &u->buffer; |
1556 p->preread_bufs->next = NULL; | 1568 p->preread_bufs->next = NULL; |
1557 u->buffer.recycled = 1; | 1569 u->buffer.recycled = 1; |
1558 | 1570 |
1559 p->preread_size = u->buffer.last - u->buffer.pos; | 1571 p->preread_size = u->buffer.last - u->buffer.pos; |
1560 | 1572 |
1561 if (u->cachable) { | 1573 if (u->cachable) { |
1574 | |
1562 p->buf_to_file = ngx_calloc_buf(r->pool); | 1575 p->buf_to_file = ngx_calloc_buf(r->pool); |
1563 if (p->buf_to_file == NULL) { | 1576 if (p->buf_to_file == NULL) { |
1564 ngx_http_upstream_finalize_request(r, u, 0); | 1577 ngx_http_upstream_finalize_request(r, u, 0); |
1565 return; | 1578 return; |
1566 } | 1579 } |
1580 | |
1567 p->buf_to_file->pos = u->buffer.start; | 1581 p->buf_to_file->pos = u->buffer.start; |
1568 p->buf_to_file->last = u->buffer.pos; | 1582 p->buf_to_file->last = u->buffer.pos; |
1569 p->buf_to_file->temporary = 1; | 1583 p->buf_to_file->temporary = 1; |
1570 } | 1584 } |
1571 | 1585 |
1908 } | 1922 } |
1909 } | 1923 } |
1910 | 1924 |
1911 if (u->peer.connection) { | 1925 if (u->peer.connection) { |
1912 | 1926 |
1927 if (u->store) { | |
1928 | |
1929 if (p->upstream_eof && u->headers_in.status_n == NGX_HTTP_OK) { | |
1930 | |
1931 ngx_http_upstream_store(r, u); | |
1932 | |
1933 } else if ((p->upstream_error | |
1934 || (p->upstream_eof | |
1935 && u->headers_in.status_n != NGX_HTTP_OK)) | |
1936 && u->pipe->temp_file->file.fd != NGX_INVALID_FILE) | |
1937 { | |
1938 if (ngx_delete_file(u->pipe->temp_file->file.name.data) | |
1939 == NGX_FILE_ERROR) | |
1940 { | |
1941 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
1942 ngx_delete_file_n " \"%s\" failed", | |
1943 u->pipe->temp_file->file.name.data); | |
1944 } | |
1945 } | |
1946 } | |
1947 | |
1913 #if (NGX_HTTP_FILE_CACHE) | 1948 #if (NGX_HTTP_FILE_CACHE) |
1914 | 1949 |
1915 if (p->upstream_done && u->cachable) { | 1950 if (p->upstream_done && u->cachable) { |
1916 if (ngx_http_cache_update(r) == NGX_ERROR) { | 1951 if (ngx_http_cache_update(r) == NGX_ERROR) { |
1917 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); | 1952 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); |
1949 | 1984 |
1950 if (!u->cachable && u->peer.connection) { | 1985 if (!u->cachable && u->peer.connection) { |
1951 ngx_http_upstream_finalize_request(r, u, 0); | 1986 ngx_http_upstream_finalize_request(r, u, 0); |
1952 } | 1987 } |
1953 } | 1988 } |
1989 } | |
1990 | |
1991 | |
1992 static void | |
1993 ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u) | |
1994 { | |
1995 char *failed; | |
1996 u_char *name; | |
1997 size_t root; | |
1998 time_t lm; | |
1999 ngx_err_t err; | |
2000 ngx_str_t *temp, path, *last_modified; | |
2001 ngx_temp_file_t *tf; | |
2002 | |
2003 if (u->pipe->temp_file->file.fd == NGX_INVALID_FILE) { | |
2004 | |
2005 /* create file for empty 200 response */ | |
2006 | |
2007 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); | |
2008 if (tf == NULL) { | |
2009 return; | |
2010 } | |
2011 | |
2012 tf->file.fd = NGX_INVALID_FILE; | |
2013 tf->file.log = r->connection->log; | |
2014 tf->path = u->conf->temp_path; | |
2015 tf->pool = r->pool; | |
2016 tf->persistent = 1; | |
2017 | |
2018 if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, | |
2019 tf->persistent, tf->clean, tf->access) | |
2020 != NGX_OK) | |
2021 { | |
2022 return; | |
2023 } | |
2024 | |
2025 u->pipe->temp_file = tf; | |
2026 } | |
2027 | |
2028 temp = &u->pipe->temp_file->file.name; | |
2029 | |
2030 #if !(NGX_WIN32) | |
2031 | |
2032 if (ngx_change_file_access(temp->data, u->conf->store_access) | |
2033 == NGX_FILE_ERROR) | |
2034 { | |
2035 err = ngx_errno; | |
2036 failed = ngx_change_file_access_n; | |
2037 name = temp->data; | |
2038 | |
2039 goto failed; | |
2040 } | |
2041 | |
2042 #endif | |
2043 | |
2044 if (r->upstream->headers_in.last_modified) { | |
2045 | |
2046 last_modified = &r->upstream->headers_in.last_modified->value; | |
2047 | |
2048 lm = ngx_http_parse_time(last_modified->data, last_modified->len); | |
2049 | |
2050 if (lm != NGX_ERROR) { | |
2051 if (ngx_set_file_time(temp->data, u->pipe->temp_file->file.fd, lm) | |
2052 != NGX_OK) | |
2053 { | |
2054 err = ngx_errno; | |
2055 failed = ngx_set_file_time_n; | |
2056 name = temp->data; | |
2057 | |
2058 goto failed; | |
2059 } | |
2060 } | |
2061 } | |
2062 | |
2063 if (u->conf->store_lengths == NULL) { | |
2064 | |
2065 ngx_http_map_uri_to_path(r, &path, &root, 0); | |
2066 | |
2067 } else { | |
2068 if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0, | |
2069 u->conf->store_values->elts) | |
2070 == NULL) | |
2071 { | |
2072 return; | |
2073 } | |
2074 } | |
2075 | |
2076 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
2077 "upstream stores \"%s\" to \"%s\"", temp->data, path.data); | |
2078 | |
2079 failed = ngx_rename_file_n; | |
2080 name = path.data; | |
2081 | |
2082 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
2083 return; | |
2084 } | |
2085 | |
2086 err = ngx_errno; | |
2087 | |
2088 if (err == NGX_ENOENT) { | |
2089 | |
2090 err = ngx_create_full_path(path.data, | |
2091 ngx_dir_access(u->conf->store_access)); | |
2092 if (err == 0) { | |
2093 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
2094 return; | |
2095 } | |
2096 | |
2097 err = ngx_errno; | |
2098 } | |
2099 } | |
2100 | |
2101 #if (NGX_WIN32) | |
2102 | |
2103 if (err == NGX_EEXIST) { | |
2104 if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) { | |
2105 | |
2106 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
2107 return; | |
2108 } | |
2109 } | |
2110 | |
2111 err = ngx_errno; | |
2112 } | |
2113 | |
2114 #endif | |
2115 | |
2116 failed: | |
2117 | |
2118 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { | |
2119 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
2120 ngx_delete_file_n " \"%s\" failed", | |
2121 temp->data); | |
2122 } | |
2123 | |
2124 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, | |
2125 "%s \"%s\" failed", failed, name); | |
1954 } | 2126 } |
1955 | 2127 |
1956 | 2128 |
1957 static void | 2129 static void |
1958 ngx_http_upstream_dummy_handler(ngx_event_t *wev) | 2130 ngx_http_upstream_dummy_handler(ngx_event_t *wev) |