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)