Mercurial > hg > nginx-quic
changeset 200:abeaebe0a33c
nginx-0.0.1-2003-11-28-20:41:47 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 28 Nov 2003 17:41:47 +0000 |
parents | a65b630b3a66 |
children | 267ea1d98683 |
files | src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_static_handler.c src/http/ngx_http.h src/http/ngx_http_cache.c src/http/ngx_http_cache.h src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_request.h |
diffstat | 8 files changed, 371 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -117,12 +117,12 @@ ngx_log_debug(r->connection->log, "index redirect.len = cache->data.value.len; if (!(redirect.data = ngx_palloc(r->pool, redirect.len + 1))) { - ngx_http_cache_unlock(ilcf->cache, cache); + ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_memcpy(redirect.data, cache->data.value.data, redirect.len + 1); - ngx_http_cache_unlock(ilcf->cache, cache); + ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); return ngx_http_internal_redirect(r, &redirect, NULL); } @@ -230,7 +230,8 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti { cache->accessed = ngx_cached_time; cache->updated = ngx_cached_time; - ngx_http_cache_unlock(ilcf->cache, cache); + ngx_http_cache_unlock(ilcf->cache, cache, + r->connection->log); return ngx_http_internal_redirect(r, &redirect, NULL); @@ -270,7 +271,7 @@ ngx_log_debug(r->connection->log, "index } if (cache) { - ngx_http_cache_unlock(ilcf->cache, cache); + ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); } return ngx_http_internal_redirect(r, &redirect, NULL);
--- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -41,9 +41,10 @@ ngx_module_t ngx_http_static_module = { ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) { - ngx_int_t rc, level; + char *location, *last, *path; uint32_t crc; - char *location, *last; + ngx_int_t rc, level; + ngx_str_t name; ngx_err_t err; ngx_http_cache_t *cache; ngx_http_cache_conf_t *ccf; @@ -55,62 +56,67 @@ ngx_int_t ngx_http_static_translate_hand clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->uri.data[r->uri.len - 1] == '/') { - if (r->path.data == NULL) { - ngx_test_null(r->path.data, - ngx_palloc(r->pool, - clcf->doc_root.len + r->uri.len), - NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data, - clcf->doc_root.len), - r->uri.data, r->uri.len + 1); + /* there is no index handler */ - } else { - r->path.data[r->path.len] = '\0'; + if (!(path = ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; } + ngx_cpystrn(ngx_cpymem(path, clcf->doc_root.data, clcf->doc_root.len), + r->uri.data, r->uri.len + 1); + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "directory index of \"%s\" is forbidden", r->path.data); + "directory index of \"%s\" is forbidden", path); return NGX_HTTP_FORBIDDEN; } - /* "+ 2" is for trailing '/' in possible redirect and '\0' */ - ngx_test_null(r->file.name.data, + + /* "+ 2" is for a trailing '/' in a possible redirect and '\0' */ + ngx_test_null(name.data, ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), NGX_HTTP_INTERNAL_SERVER_ERROR); - location = ngx_cpymem(r->file.name.data, clcf->doc_root.data, - clcf->doc_root.len), - + location = ngx_cpymem(name.data, clcf->doc_root.data, clcf->doc_root.len); last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1); -ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); + ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ data); + - ccf = ngx_http_get_module_loc_conf(r, ngx_http_cache_module); + if (r->cache == NULL) { + + /* look up an open files cache */ - if (ccf->open_files) { - cache = ngx_http_cache_get(ccf->open_files, &r->file.name, &crc); + ccf = ngx_http_get_module_loc_conf(r, ngx_http_cache_module); -ngx_log_debug(r->connection->log, "cache get: %x" _ cache); + if (ccf->open_files) { + cache = ngx_http_cache_get(ccf->open_files, &name, &crc); + + ngx_log_debug(r->connection->log, "cache get: %x" _ cache); - if (cache - && ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) - || ccf->open_files->update >= ngx_cached_time - cache->updated)) - { - cache->refs++; - r->file.fd = cache->fd; - r->file.name = cache->key; - r->content_handler = ngx_http_static_handler; + if (cache + && ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) + || ccf->open_files->update + >= ngx_cached_time - cache->updated)) + { + r->cache = cache; + r->content_handler = ngx_http_static_handler; - return NGX_OK; + return NGX_OK; + } + + } else { + cache = NULL; } } else { - cache = NULL; + cache = r->cache; } + #if (WIN9X) if (ngx_win32_version < NGX_WIN_NT) { @@ -121,10 +127,10 @@ ngx_log_debug(r->connection->log, "cache * so we need to check its type before the opening */ - if (ngx_file_info(r->file.name.data, &r->file.info) == NGX_FILE_ERROR) { + if (ngx_file_info(name.data, &r->file.info) == NGX_FILE_ERROR) { err = ngx_errno; ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - ngx_file_info_n " \"%s\" failed", r->file.name.data); + ngx_file_info_n " \"%s\" failed", name.data); if (err == NGX_ENOENT || err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; @@ -138,7 +144,7 @@ ngx_log_debug(r->connection->log, "cache } if (ngx_is_dir(&r->file.info)) { -ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); + ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ name.data); if (!(r->headers_out.location = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) @@ -159,6 +165,7 @@ ngx_log_debug(r->connection->log, "HTTP #endif + if (r->file.fd == NGX_INVALID_FILE) { r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); @@ -282,6 +289,7 @@ static int ngx_http_static_handler(ngx_h ngx_hunk_t *h; ngx_chain_t out; ngx_http_type_t *type; + ngx_http_cleanup_t *cleanup; ngx_http_log_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; @@ -294,6 +302,10 @@ static int ngx_http_static_handler(ngx_h ctx = r->connection->log->data; ctx->action = "sending response to client"; + if (!(cleanup = ngx_push_array(&r->cleanup))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + if (r->file.fd == NGX_INVALID_FILE) { r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); @@ -316,6 +328,10 @@ static int ngx_http_static_handler(ngx_h } } + cleanup->data.file.fd = r->file.fd; + cleanup->data.file.name = r->file.name.data; + cleanup->cache = 0; + if (!r->file.info_valid) { if (ngx_fd_info(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, @@ -379,7 +395,6 @@ static int ngx_http_static_handler(ngx_h ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), NGX_HTTP_INTERNAL_SERVER_ERROR); - rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
--- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -48,8 +48,11 @@ int ngx_http_init(ngx_pool_t *pool, ngx_ /**/ void ngx_http_init_connection(ngx_connection_t *c); + int ngx_http_parse_request_line(ngx_http_request_t *r); +int ngx_http_parse_complex_uri(ngx_http_request_t *r); int ngx_http_parse_header_line(ngx_http_request_t *r, ngx_hunk_t *h); + int ngx_http_find_server_conf(ngx_http_request_t *r); void ngx_http_handler(ngx_http_request_t *r); void ngx_http_finalize_request(ngx_http_request_t *r, int error);
--- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -176,6 +176,29 @@ ngx_http_cache_t *ngx_http_cache_alloc(n } +void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, + ngx_http_cache_t *cache, ngx_log_t *log) +{ + ngx_mutex_lock(&hash->mutex); + + cache->refs--; + + if (cache->refs == 0 && cache->deleted) { +ngx_log_debug(log, "CLOSE FILE: %d" _ cache->fd); + if (cache->fd != NGX_INVALID_FILE) { + if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", + cache->key.data); + } + } + cache->key.data = NULL; + } + + ngx_mutex_unlock(&hash->mutex); +} + + int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq) { ssize_t n;
--- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -74,12 +74,6 @@ typedef struct { } ngx_http_cache_conf_t; -#define ngx_http_cache_unlock(ch, ce) \ - ngx_mutex_lock(&ch->mutex); \ - ce->refs--; \ - ngx_mutex_unlock(&ch->mutex); - - #define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_AGED 2 @@ -96,6 +90,9 @@ ngx_http_cache_t *ngx_http_cache_get(ngx ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache, ngx_str_t *key, uint32_t crc, ngx_log_t *log); +void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, + ngx_http_cache_t *cache, ngx_log_t *log); + int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, ngx_dir_t *dir);
--- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -5,8 +5,7 @@ int ngx_http_parse_request_line(ngx_http_request_t *r) { - char ch; - char *p; + char ch, *p; enum { sw_start = 0, sw_G, @@ -198,9 +197,7 @@ int ngx_http_parse_request_line(ngx_http state = sw_uri; break; case '/': -#if (WIN32) r->complex_uri = 1; -#endif break; case '?': r->args_start = p; @@ -421,11 +418,11 @@ int ngx_http_parse_request_line(ngx_http } } + int ngx_http_parse_header_line(ngx_http_request_t *r, ngx_hunk_t *h) { - char c, ch; - char *p; - enum { + char c, ch, *p; + enum { sw_start = 0, sw_name, sw_space_before_value, @@ -622,3 +619,197 @@ int ngx_http_parse_header_line(ngx_http_ return NGX_AGAIN; } } + + +int ngx_http_parse_complex_uri(ngx_http_request_t *r) +{ + char c, ch, decoded, *p, *u; + enum { + sw_usual = 0, + sw_slash, + sw_dot, + sw_dot_dot, +#if (WIN32) + sw_dot_dot_dot, +#endif + sw_quoted, + sw_quoted_second + } state, quoted_state; + + decoded = '\0'; + quoted_state = sw_usual; + + state = sw_usual; + p = r->uri_start; + u = r->uri.data; + + ch = *p++; + + while (p < r->uri_start + r->uri.len + 1) { + +ngx_log_debug(r->connection->log, "S: %d UN: '%x:%c', URI: '%c'" _ + state _ ch _ ch _ *u); + + switch (state) { + case sw_usual: + switch(ch) { + case '/': + state = sw_slash; + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_slash: + switch(ch) { + case '/': + break; + case '.': + state = sw_dot; + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_dot: + switch(ch) { + case '/': + state = sw_slash; + u--; + break; + case '.': + state = sw_dot_dot; + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_dot_dot: + switch(ch) { + case '/': + state = sw_slash; + u -= 4; + if (u < r->uri.data) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + while (*(u - 1) != '/') { + u--; + } + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; +#if (WIN32) + case '.': + state = sw_dot_dot_dot; + *u++ = ch; + break; +#endif + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + +#if (WIN32) + case sw_dot_dot_dot: + switch(ch) { + case '/': + state = sw_slash; + u -= 5; + if (u < r->uri.data) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + while (*u != '/') { + u--; + } + if (u < r->uri.data) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + while (*(u - 1) != '/') { + u--; + } + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; +#endif + + case sw_quoted: + if (ch >= '0' && ch <= '9') { + decoded = ch - '0'; + state = sw_quoted_second; + ch = *p++; + break; + } + + c = ch | 0x20; + if (c >= 'a' && c <= 'f') { + decoded = c - 'a' + 10; + state = sw_quoted_second; + ch = *p++; + break; + } + + return NGX_HTTP_PARSE_INVALID_REQUEST; + + case sw_quoted_second: + if (ch >= '0' && ch <= '9') { + ch = (decoded << 4) + ch - '0'; + state = quoted_state; + break; + } + + c = ch | 0x20; + if (c >= 'a' && c <= 'f') { + ch = (decoded << 4) + c - 'a' + 10; + state = quoted_state; + break; + } + + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + } + + r->uri.len = u - r->uri.data; + r->uri.data[r->uri.len] = '\0'; + + return NGX_OK; +}
--- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -225,6 +225,21 @@ ngx_log_debug(rev->log, "IN: %08x" _ in_ return; } + r->cleanup.elts = ngx_palloc(r->pool, 5 * sizeof(ngx_http_cleanup_t)); + if (r->cleanup.elts == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } + /* + * set by ngx_pcalloc(): + * + * r->cleanup.nelts = 0; + */ + r->cleanup.nalloc = 5; + r->cleanup.size = sizeof(ngx_http_cleanup_t); + r->cleanup.pool = r->pool; + /* TODO: ngx_init_table */ if (!(r->headers_out.headers = ngx_create_table(r->pool, 20))) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -289,7 +304,7 @@ static void ngx_http_process_request_lin /* the request line has been parsed successfully */ /* TODO: we need to handle such URIs */ - if (r->complex_uri || r->unusual_uri) { + if (r->unusual_uri) { r->request_line.len = r->request_end - r->request_start; r->request_line.data = r->request_start; r->request_line.data[r->request_line.len] = '\0'; @@ -313,6 +328,20 @@ static void ngx_http_process_request_lin } + /* copy unparsed URI */ + + r->unparsed_uri.len = r->uri_end - r->uri_start; + r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1); + if (r->unparsed_uri.data == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } + + ngx_cpystrn(r->unparsed_uri.data, r->uri_start, + r->unparsed_uri.len + 1); + + /* copy URI */ if (r->args_start) { @@ -327,22 +356,13 @@ static void ngx_http_process_request_lin return; } - ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); - - - /* copy unparsed URI */ + if (r->complex_uri) { + rc = ngx_http_parse_complex_uri(r); - r->unparsed_uri.len = r->uri_end - r->uri_start; - r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1); - if (r->unparsed_uri.data == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; + } else { + ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); } - ngx_cpystrn(r->unparsed_uri.data, r->uri_start, - r->unparsed_uri.len + 1); - r->request_line.len = r->request_end - r->request_start; @@ -369,6 +389,16 @@ static void ngx_http_process_request_lin } + if (rc != NGX_OK) { + /* + * we check ngx_http_parse_complex_uri() result here to log + * the request line + */ + ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); + return; + } + + if (r->uri_ext) { /* copy URI extention */ @@ -1356,7 +1386,9 @@ int ngx_http_send_last(ngx_http_request_ void ngx_http_close_request(ngx_http_request_t *r, int error) { + ngx_int_t i; ngx_http_log_ctx_t *ctx; + ngx_http_cleanup_t *cleanup; ngx_log_debug(r->connection->log, "close http request"); @@ -1372,6 +1404,22 @@ void ngx_http_close_request(ngx_http_req ngx_http_log_handler(r); + cleanup = r->cleanup.elts; + for (i = 0; i < r->cleanup.nelts; i++) { + if (cleanup[i].cache) { + ngx_http_cache_unlock(cleanup[i].data.cache.hash, + cleanup[i].data.cache.cache, + r->connection->log); + continue; + } + + if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", + cleanup[i].data.file.name); + } + } + if (r->file.fd != NGX_INVALID_FILE) { if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
--- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -144,17 +144,34 @@ typedef struct { } ngx_http_headers_out_t; +typedef struct { + union { + struct { + ngx_fd_t fd; + char *name; + } file; + + struct { + ngx_http_cache_hash_t *hash; + ngx_http_cache_t *cache; + } cache; + } data; + + unsigned cache:1; +} ngx_http_cleanup_t; + + typedef int (*ngx_http_handler_pt)(ngx_http_request_t *r); struct ngx_http_request_s { - ngx_connection_t *connection; + ngx_connection_t *connection; - void **ctx; - void **main_conf; - void **srv_conf; - void **loc_conf; + void **ctx; + void **main_conf; + void **srv_conf; + void **loc_conf; - ngx_http_cache_t *cache; + ngx_http_cache_t *cache; ngx_file_t file; @@ -199,6 +216,8 @@ struct ngx_http_request_s { void (*request_body_handler) (void *data); void *data; + ngx_array_t cleanup; + char *discarded_buffer; void **err_ctx; int err_status;