diff options
Diffstat (limited to 'src/http/modules')
-rw-r--r-- | src/http/modules/ngx_http_auth_basic_module.c | 41 | ||||
-rw-r--r-- | src/http/modules/ngx_http_empty_gif_module.c | 82 | ||||
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 119 | ||||
-rw-r--r-- | src/http/modules/ngx_http_log_module.c | 17 | ||||
-rw-r--r-- | src/http/modules/ngx_http_memcached_module.c | 616 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 55 | ||||
-rw-r--r-- | src/http/modules/ngx_http_range_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_realip_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_static_module.c | 2 |
9 files changed, 805 insertions, 131 deletions
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index b129a9874..cf855575c 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -332,32 +332,10 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_auth_basic_loc_conf_t *prev = parent; ngx_http_auth_basic_loc_conf_t *conf = child; - size_t len; - u_char *realm, *p; - - if (conf->realm.data) { - if (conf->realm.len) { - len = sizeof("Basic realm=\"") - 1 + conf->realm.len + 1; - - realm = ngx_palloc(cf->pool, len); - if (realm == NULL) { - return NGX_CONF_ERROR; - } - - p = ngx_cpymem(realm, "Basic realm=\"", - sizeof("Basic realm=\"") - 1); - p = ngx_cpymem(p, conf->realm.data, conf->realm.len); - *p = '"'; - - conf->realm.len = len; - conf->realm.data = realm; - } - - } else { + if (conf->realm.data == NULL) { conf->realm = prev->realm; } - if (conf->user_file.data) { if (ngx_conf_full_name(cf->cycle, &conf->user_file) != NGX_OK) { return NGX_CONF_ERROR; @@ -395,10 +373,27 @@ ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data) { ngx_str_t *realm = data; + size_t len; + u_char *basic, *p; + if (ngx_strcmp(realm->data, "off") == 0) { realm->len = 0; realm->data = (u_char *) ""; } + len = sizeof("Basic realm=\"") - 1 + realm->len + 1; + + basic = ngx_palloc(cf->pool, len); + if (basic == NULL) { + return NGX_CONF_ERROR; + } + + p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1); + p = ngx_cpymem(p, realm->data, realm->len); + *p = '"'; + + realm->len = len; + realm->data = basic; + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c index 5c9a415c7..c7af1214c 100644 --- a/src/http/modules/ngx_http_empty_gif_module.c +++ b/src/http/modules/ngx_http_empty_gif_module.c @@ -28,49 +28,49 @@ static ngx_command_t ngx_http_empty_gif_commands[] = { static u_char ngx_empty_gif[] = { - 'G', 'I', 'F', '8', '9', 'a', /* header */ - - /* logical screen descriptor */ - 0x01, 0x00, /* logical screen width */ - 0x01, 0x00, /* logical screen height */ - 0x80, /* global 1-bit color table */ - 0x01, /* background color #1 */ - 0x00, /* no aspect ratio */ - - /* global color table */ - 0x00, 0x00, 0x00, /* #0: black */ - 0xff, 0xff, 0xff, /* #1: white */ - - /* graphic control extension */ - 0x21, /* extension introducer */ - 0xf9, /* graphic control label */ - 0x04, /* block size */ - 0x01, /* transparent color is given, */ - /* no disposal specified, */ - /* user input is not expected */ - 0x00, 0x00, /* delay time */ - 0x01, /* transparent color #1 */ - 0x00, /* block terminator */ - - /* image descriptor */ - 0x2c, /* image separator */ - 0x00, 0x00, /* image left position */ - 0x00, 0x00, /* image top position */ - 0x01, 0x00, /* image width */ - 0x01, 0x00, /* image height */ - 0x00, /* no local color table, no interlaced */ - - /* table based image data */ - 0x02, /* LZW minimum code size, */ - /* must be at least 2-bit */ - 0x02, /* block size */ + 'G', 'I', 'F', '8', '9', 'a', /* header */ + + /* logical screen descriptor */ + 0x01, 0x00, /* logical screen width */ + 0x01, 0x00, /* logical screen height */ + 0x80, /* global 1-bit color table */ + 0x01, /* background color #1 */ + 0x00, /* no aspect ratio */ + + /* global color table */ + 0x00, 0x00, 0x00, /* #0: black */ + 0xff, 0xff, 0xff, /* #1: white */ + + /* graphic control extension */ + 0x21, /* extension introducer */ + 0xf9, /* graphic control label */ + 0x04, /* block size */ + 0x01, /* transparent color is given, */ + /* no disposal specified, */ + /* user input is not expected */ + 0x00, 0x00, /* delay time */ + 0x01, /* transparent color #1 */ + 0x00, /* block terminator */ + + /* image descriptor */ + 0x2c, /* image separator */ + 0x00, 0x00, /* image left position */ + 0x00, 0x00, /* image top position */ + 0x01, 0x00, /* image width */ + 0x01, 0x00, /* image height */ + 0x00, /* no local color table, no interlaced */ + + /* table based image data */ + 0x02, /* LZW minimum code size, */ + /* must be at least 2-bit */ + 0x02, /* block size */ 0x4c, 0x01, /* compressed bytes 01_001_100, 0000000_1 */ - /* 100: clear code */ - /* 001: 1 */ - /* 101: end of information code */ - 0x00, /* block terminator */ + /* 100: clear code */ + /* 001: 1 */ + /* 101: end of information code */ + 0x00, /* block terminator */ - 0x3B /* trailer */ + 0x3B /* trailer */ }; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 5d2c153e2..125b8e023 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -11,16 +11,16 @@ typedef struct { - ngx_http_upstream_conf_t upstream; + ngx_http_upstream_conf_t upstream; - ngx_peers_t *peers; + ngx_peers_t *peers; - ngx_str_t index; + ngx_str_t index; - ngx_array_t *flushes; - ngx_array_t *params_len; - ngx_array_t *params; - ngx_array_t *params_source; + ngx_array_t *flushes; + ngx_array_t *params_len; + ngx_array_t *params; + ngx_array_t *params_source; } ngx_http_fastcgi_loc_conf_t; @@ -39,14 +39,14 @@ typedef enum { typedef struct { - ngx_http_fastcgi_state_e state; - u_char *pos; - u_char *last; - ngx_uint_t type; - size_t length; - size_t padding; - - ngx_uint_t header; + ngx_http_fastcgi_state_e state; + u_char *pos; + u_char *last; + ngx_uint_t type; + size_t length; + size_t padding; + + ngx_uint_t header; } ngx_http_fastcgi_ctx_t; @@ -151,6 +151,10 @@ static ngx_str_t ngx_http_fastcgi_script_name = static ngx_conf_post_t ngx_http_fastcgi_lowat_post = { ngx_http_fastcgi_lowat_check }; +static ngx_conf_deprecated_t ngx_conf_deprecated_fastcgi_header_buffer_size = { + ngx_conf_deprecated, "fastcgi_header_buffer_size", "fastcgi_buffer_size" +}; + static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, @@ -199,13 +203,20 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_lowat), &ngx_http_fastcgi_lowat_post }, - { ngx_string("fastcgi_header_buffer_size"), + { ngx_string("fastcgi_buffer_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size), + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffer_size), NULL }, + { ngx_string("fastcgi_header_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffer_size), + &ngx_conf_deprecated_fastcgi_header_buffer_size }, + { ngx_string("fastcgi_pass_request_headers"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -371,8 +382,13 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r) u->abort_request = ngx_http_fastcgi_abort_request; u->finalize_request = ngx_http_fastcgi_finalize_request; - u->pipe.input_filter = ngx_http_fastcgi_input_filter; - u->pipe.input_ctx = r; + u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); + if (u->pipe == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + u->pipe->input_filter = ngx_http_fastcgi_input_filter; + u->pipe->input_ctx = r; r->upstream = u; @@ -799,13 +815,13 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) if (f->state < ngx_http_fastcgi_st_data) { - f->pos = u->header_in.pos; - f->last = u->header_in.last; + f->pos = u->buffer.pos; + f->last = u->buffer.last; rc = ngx_http_fastcgi_process_record(r, f); - u->header_in.pos = f->pos; - u->header_in.last = f->last; + u->buffer.pos = f->pos; + u->buffer.last = f->last; if (rc == NGX_AGAIN) { return NGX_AGAIN; @@ -835,22 +851,22 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) if (f->state == ngx_http_fastcgi_st_padding) { - if (u->header_in.pos + f->padding < u->header_in.last) { + if (u->buffer.pos + f->padding < u->buffer.last) { f->state = ngx_http_fastcgi_st_version; - u->header_in.pos += f->padding; + u->buffer.pos += f->padding; continue; } - if (u->header_in.pos + f->padding == u->header_in.last) { + if (u->buffer.pos + f->padding == u->buffer.last) { f->state = ngx_http_fastcgi_st_version; - u->header_in.pos = u->header_in.last; + u->buffer.pos = u->buffer.last; return NGX_AGAIN; } - f->padding -= u->header_in.last - u->header_in.pos; - u->header_in.pos = u->header_in.last; + f->padding -= u->buffer.last - u->buffer.pos; + u->buffer.pos = u->buffer.last; return NGX_AGAIN; } @@ -868,18 +884,18 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) } if (f->length) { - line.data = u->header_in.pos; + line.data = u->buffer.pos; - if (u->header_in.pos + f->length <= u->header_in.last) { + if (u->buffer.pos + f->length <= u->buffer.last) { line.len = f->length; - u->header_in.pos += f->length; + u->buffer.pos += f->length; f->length = 0; f->state = ngx_http_fastcgi_st_padding; } else { - line.len = u->header_in.last - u->header_in.pos; - f->length -= u->header_in.last - u->header_in.pos; - u->header_in.pos = u->header_in.last; + line.len = u->buffer.last - u->buffer.pos; + f->length -= u->buffer.last - u->buffer.pos; + u->buffer.pos = u->buffer.last; } while (line.data[line.len - 1] == LF @@ -893,7 +909,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "FastCGI sent in stderr: \"%V\"", &line); - if (u->header_in.pos == u->header_in.last) { + if (u->buffer.pos == u->buffer.last) { return NGX_AGAIN; } @@ -907,17 +923,17 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) /* f->type == NGX_HTTP_FASTCGI_STDOUT */ - start = u->header_in.pos; + start = u->buffer.pos; - if (u->header_in.pos + f->length < u->header_in.last) { + if (u->buffer.pos + f->length < u->buffer.last) { /* - * set u->header_in.last to the end of the FastCGI record data + * set u->buffer.last to the end of the FastCGI record data * for ngx_http_parse_header_line() */ - last = u->header_in.last; - u->header_in.last = u->header_in.pos + f->length; + last = u->buffer.last; + u->buffer.last = u->buffer.pos + f->length; } else { last = NULL; @@ -927,7 +943,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) for ( ;; ) { - rc = ngx_http_parse_header_line(r, &u->header_in); + rc = ngx_http_parse_header_line(r, &u->buffer); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http fastcgi parser: %d", rc); @@ -1024,13 +1040,13 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) } if (last) { - u->header_in.last = last; + u->buffer.last = last; } - f->length -= u->header_in.pos - start; + f->length -= u->buffer.pos - start; if (rc == NGX_AGAIN) { - if (u->header_in.pos == u->header_in.last) { + if (u->buffer.pos == u->buffer.last) { return NGX_AGAIN; } @@ -1439,12 +1455,14 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) * conf->index.data = NULL; */ + conf->upstream.buffering = NGX_CONF_UNSET; + conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; - conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; + conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; @@ -1485,6 +1503,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; + ngx_conf_merge_value(conf->upstream.buffering, + prev->upstream.buffering, 1); + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -1497,8 +1518,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); - ngx_conf_merge_size_value(conf->upstream.header_buffer_size, - prev->upstream.header_buffer_size, + ngx_conf_merge_size_value(conf->upstream.buffer_size, + prev->upstream.buffer_size, (size_t) ngx_pagesize); @@ -1512,7 +1533,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } - size = conf->upstream.header_buffer_size; + size = conf->upstream.buffer_size; if (size < conf->upstream.bufs.size) { size = conf->upstream.bufs.size; } diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index 3bcf73ac9..9436e5983 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -172,7 +172,7 @@ static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH); static ngx_str_t ngx_http_combined_fmt = - ngx_string("$remote_addr - $remote_user [$time_gmt] " + ngx_string("$remote_addr - $remote_user [$time_local] " "\"$request\" $status $body_bytes_sent " "\"$http_referer\" \"$http_user_agent\""); @@ -180,7 +180,7 @@ static ngx_str_t ngx_http_combined_fmt = static ngx_http_log_var_t ngx_http_log_vars[] = { { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection }, { ngx_string("pipe"), 1, ngx_http_log_pipe }, - { ngx_string("time_gmt"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, + { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, ngx_http_log_time }, { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec }, { ngx_string("request_time"), NGX_TIME_T_LEN, ngx_http_log_request_time }, @@ -1019,6 +1019,11 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (cf->args->nelts >= 3) { name = value[2]; + + if (ngx_strcmp(name.data, "combined") == 0) { + lmcf->combined_used = 1; + } + } else { name.len = sizeof("combined") - 1; name.data = (u_char *) "combined"; @@ -1384,6 +1389,7 @@ ngx_http_log_init(ngx_conf_t *cf) { ngx_str_t *value; ngx_array_t a; + ngx_http_handler_pt *h; ngx_http_log_fmt_t *fmt; ngx_http_log_main_conf_t *lmcf; ngx_http_core_main_conf_t *cmcf; @@ -1412,7 +1418,12 @@ ngx_http_log_init(ngx_conf_t *cf) cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - cmcf->log_handler = ngx_http_log_handler; + h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_log_handler; return NGX_OK; } diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c new file mode 100644 index 000000000..6217dd109 --- /dev/null +++ b/src/http/modules/ngx_http_memcached_module.c @@ -0,0 +1,616 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> +#include <ngx_http.h> + + +typedef struct { + ngx_http_upstream_conf_t upstream; + ngx_peers_t *peers; +} ngx_http_memcached_loc_conf_t; + + +typedef struct { + size_t rest; + ngx_http_request_t *request; +} ngx_http_memcached_ctx_t; + + +static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r); +static ngx_int_t ngx_http_memcached_reinit_request(ngx_http_request_t *r); +static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r); +static ngx_int_t ngx_http_memcached_filter_init(void *data); +static ngx_int_t ngx_http_memcached_filter(void *data, ssize_t bytes); +static void ngx_http_memcached_abort_request(ngx_http_request_t *r); +static void ngx_http_memcached_finalize_request(ngx_http_request_t *r, + ngx_int_t rc); + +static void *ngx_http_memcached_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); + +static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_conf_bitmask_t ngx_http_memcached_next_upstream_masks[] = { + { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, + { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, + { ngx_string("invalid_response"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, + { ngx_string("not_found"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_null_string, 0 } +}; + + +static ngx_command_t ngx_http_memcached_commands[] = { + + { ngx_string("memcached_pass"), + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_memcached_pass, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("memcached_connect_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.connect_timeout), + NULL }, + + { ngx_string("memcached_send_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.send_timeout), + NULL }, + + { ngx_string("memcached_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.buffer_size), + NULL }, + + { ngx_string("memcached_read_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.read_timeout), + NULL }, + + { ngx_string("memcached_next_upstream"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), + &ngx_http_memcached_next_upstream_masks }, + + { ngx_string("memcached_upstream_max_fails"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.max_fails), + NULL }, + + { ngx_string("memcached_upstream_fail_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_sec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, upstream.fail_timeout), + NULL }, + + ngx_null_command +}; + + +ngx_http_module_t ngx_http_memcached_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_memcached_create_loc_conf, /* create location configration */ + ngx_http_memcached_merge_loc_conf /* merge location configration */ +}; + + +ngx_module_t ngx_http_memcached_module = { + NGX_MODULE_V1, + &ngx_http_memcached_module_ctx, /* module context */ + ngx_http_memcached_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +#define NGX_HTTP_MEMCACHED_END (sizeof(ngx_http_memcached_end) - 1) +static u_char ngx_http_memcached_end[] = CRLF "END" CRLF; + + +static ngx_int_t +ngx_http_memcached_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_http_upstream_t *u; + ngx_http_memcached_ctx_t *ctx; + ngx_http_memcached_loc_conf_t *mlcf; + + if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + return NGX_HTTP_NOT_ALLOWED; + } + + rc = ngx_http_discard_body(r); + + if (rc != NGX_OK && rc != NGX_AGAIN) { + return rc; + } + + if (ngx_http_set_content_type(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); + + u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); + if (u == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + u->peer.log = r->connection->log; + u->peer.log_error = NGX_ERROR_ERR; + u->peer.peers = mlcf->peers; + u->peer.tries = mlcf->peers->number; +#if (NGX_THREADS) + u->peer.lock = &r->connection->lock; +#endif + + u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; + + u->conf = &mlcf->upstream; + + u->create_request = ngx_http_memcached_create_request; + u->reinit_request = ngx_http_memcached_reinit_request; + u->process_header = ngx_http_memcached_process_header; + u->abort_request = ngx_http_memcached_abort_request; + u->finalize_request = ngx_http_memcached_finalize_request; + + r->upstream = u; + + ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ctx->rest = NGX_HTTP_MEMCACHED_END; + ctx->request = r; + + u->input_filter_init = ngx_http_memcached_filter_init; + u->input_filter = ngx_http_memcached_filter; + u->input_filter_ctx = ctx; + + ngx_http_upstream_init(r); + + return NGX_DONE; +} + + +static ngx_int_t +ngx_http_memcached_create_request(ngx_http_request_t *r) +{ + size_t len; + ngx_buf_t *b; + ngx_chain_t *cl; + + len = sizeof("get ") - 1 + r->uri.len + sizeof(" " CRLF) - 1; + if (r->args.len) { + len += 1+ r->args.len; + } + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + cl->next = NULL; + + r->upstream->request_bufs = cl; + + *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' '; + + b->last = ngx_copy(b->last, r->uri.data, r->uri.len); + + if (r->args.len) { + *b->last++ = '?'; + b->last = ngx_copy(b->last, r->args.data, r->args.len); + } + +#if (NGX_DEBUG) + { + ngx_str_t s; + + s.len = b->last - b->pos; + s.data = b->pos; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http memcached request: \"%V\"", &s); + } +#endif + + *b->last++ = ' '; *b->last++ = CR; *b->last++ = LF; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_memcached_reinit_request(ngx_http_request_t *r) +{ + return NGX_OK; +} + + +static ngx_int_t +ngx_http_memcached_process_header(ngx_http_request_t *r) +{ + u_char *p, *len; + ngx_str_t line; + ngx_http_upstream_t *u; + + u = r->upstream; + + for (p = u->buffer.pos; p < u->buffer.last; p++) { + if (*p == LF) { + goto found; + } + } + + return NGX_AGAIN; + +found: + + *p = '\0'; + + line.len = p - u->buffer.pos - 1; + line.data = u->buffer.pos; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "memcached: \"%V\"", &line); + + p = u->buffer.pos; + + if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) { + + p += sizeof("VALUE ") - 1; + + if (ngx_strncmp(p, r->uri.data, r->uri.len) != 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "memcached sent invalid key in response \"%V\" " + "for key \"%V\"", + &line, &r->uri); + + return NGX_HTTP_UPSTREAM_INVALID_HEADER; + } + + p += r->uri.len; + + if (*p++ != ' ') { + goto no_valid; + } + + /* skip flags */ + + while (*p) { + if (*p++ == ' ') { + goto length; + } + } + + goto no_valid; + + length: + + len = p; + + while (*p && *p++ != CR) { /* void */ } + + r->headers_out.content_length_n = ngx_atoof(len, p - len - 1); + if (r->headers_out.content_length_n == -1) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "memcached sent invalid length in response \"%V\" " + "for key \"%V\"", + &line, &r->uri); + return NGX_HTTP_UPSTREAM_INVALID_HEADER; + } + + u->headers_in.status_n = 200; + u->buffer.pos = p + 1; + + return NGX_OK; + } + + if (ngx_strcmp(p, "END\x0d") == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "key: \"%V\" was not found by memcached", &r->uri); + + u->headers_in.status_n = 404; + + return NGX_OK; + } + +no_valid: + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "memcached sent invalid response: \"%V\"", &line); + + return NGX_HTTP_UPSTREAM_INVALID_HEADER; +} + + +static ngx_int_t +ngx_http_memcached_filter_init(void *data) +{ + ngx_http_memcached_ctx_t *ctx = data; + + ngx_http_upstream_t *u; + + u = ctx->request->upstream; + + u->length += NGX_HTTP_MEMCACHED_END; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_memcached_filter(void *data, ssize_t bytes) +{ + ngx_http_memcached_ctx_t *ctx = data; + + u_char *last; + ngx_buf_t *b; + ngx_chain_t *cl, **ll; + ngx_http_upstream_t *u; + + u = ctx->request->upstream; + b = &u->buffer; + + if (u->length == ctx->rest) { + + if (ngx_strncmp(b->last, + ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END + - ctx->rest, + bytes) != 0) + { + ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, + "memcached sent invalid trailer"); + } + + u->length -= bytes; + ctx->rest -= bytes; + + return NGX_OK; + } + + for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) { + ll = &cl->next; + } + + cl = ngx_chain_get_free_buf(ctx->request->pool, &u->free_bufs); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf->flush = 1; + cl->buf->memory = 1; + + *ll = cl; + + cl->buf->pos = b->last; + b->last += bytes; + cl->buf->last = b->last; + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, + "memcached filter bytes:%z size:%z length:%z rest:%z", + bytes, b->last - b->pos, u->length, ctx->rest); + + if (b->last - b->pos <= (ssize_t) (u->length - NGX_HTTP_MEMCACHED_END)) { + u->length -= bytes; + return NGX_OK; + } + + + last = b->pos + u->length - NGX_HTTP_MEMCACHED_END; + + if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) { + ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, + "memcached sent invalid trailer"); + } + + ctx->rest = u->length - (b->last - b->pos); + b->last = last; + cl->buf->last = last; + u->length = ctx->rest; + + return NGX_OK; +} + + +static void +ngx_http_memcached_abort_request(ngx_http_request_t *r) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "abort http memcached request"); + return; +} + + +static void +ngx_http_memcached_finalize_request(ngx_http_request_t *r, ngx_int_t rc) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "finalize http memcached request"); + return; +} + + +static void * +ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_memcached_loc_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcached_loc_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->upstream.bufs.num = 0; + * conf->upstream.next_upstream = 0; + * conf->upstream.temp_path = NULL; + * conf->upstream.schema = { 0, NULL }; + * conf->upstream.uri = { 0, NULL }; + * conf->upstream.location = NULL; + * + * conf->peers = NULL; + */ + + conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + + conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; + + conf->upstream.max_fails = NGX_CONF_UNSET_UINT; + conf->upstream.fail_timeout = NGX_CONF_UNSET; + + /* "fastcgi_cyclic_temp_file" is disabled */ + conf->upstream.cyclic_temp_file = 0; + + /* the hardcoded values */ + conf->upstream.send_lowat = 0; + conf->upstream.bufs.num = 0; + conf->upstream.busy_buffers_size = 0; + conf->upstream.max_temp_file_size = 0; + conf->upstream.temp_file_write_size = 0; + conf->upstream.pass_x_powered_by = 0; + conf->upstream.redirect_errors = 1; + conf->upstream.redirect_404 = 1; + conf->upstream.pass_server = 1; + conf->upstream.pass_date = 1; + conf->upstream.pass_request_headers = 0; + conf->upstream.pass_request_body = 0; + + return conf; +} + + +static char * +ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_memcached_loc_conf_t *prev = parent; + ngx_http_memcached_loc_conf_t *conf = child; + + ngx_uint_t i; + + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, + prev->upstream.connect_timeout, 60000); + + ngx_conf_merge_msec_value(conf->upstream.send_timeout, + prev->upstream.send_timeout, 60000); + + ngx_conf_merge_msec_value(conf->upstream.read_timeout, + prev->upstream.read_timeout, 60000); + + ngx_conf_merge_size_value(conf->upstream.buffer_size, + prev->upstream.buffer_size, + (size_t) ngx_pagesize); + + ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, + prev->upstream.next_upstream, + (NGX_CONF_BITMASK_SET + |NGX_HTTP_UPSTREAM_FT_ERROR + |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); + + ngx_conf_merge_unsigned_value(conf->upstream.max_fails, + prev->upstream.max_fails, 1); + + ngx_conf_merge_sec_value(conf->upstream.fail_timeout, + prev->upstream.fail_timeout, 10); + + if (conf->peers && conf->peers->number > 1) { + for (i = 0; i < conf->peers->number; i++) { + conf->peers->peer[i].weight = 1; + conf->peers->peer[i].max_fails = conf->upstream.max_fails; + conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout; + } + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_memcached_loc_conf_t *lcf = conf; + + ngx_str_t *value; + ngx_inet_upstream_t inet_upstream; + ngx_http_core_loc_conf_t *clcf; + + if (lcf->upstream.schema.len) { + return "is duplicate"; + } + + value = cf->args->elts; + + ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t)); + + inet_upstream.name = value[1]; + inet_upstream.url = value[1]; + + lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); + if (lcf->peers == NULL) { + return NGX_CONF_ERROR; + } + + lcf->upstream.schema.len = sizeof("memcached://") - 1; + lcf->upstream.schema.data = (u_char *) "memcached://"; + + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + clcf->handler = ngx_http_memcached_handler; + + lcf->upstream.location = clcf->name; + + if (clcf->name.data[clcf->name.len - 1] == '/') { + clcf->auto_redirect = 1; + } + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index f1581e9e7..8278d34e4 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -111,6 +111,10 @@ static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); static ngx_conf_post_t ngx_http_proxy_lowat_post = { ngx_http_proxy_lowat_check }; +static ngx_conf_deprecated_t ngx_conf_deprecated_proxy_header_buffer_size = { + ngx_conf_deprecated, "proxy_header_buffer_size", "proxy_buffer_size" +}; + static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, @@ -138,6 +142,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { 0, NULL }, + { ngx_string("proxy_buffering"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering), + NULL }, + { ngx_string("proxy_connect_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -201,13 +212,20 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body), NULL }, - { ngx_string("proxy_header_buffer_size"), + { ngx_string("proxy_buffer_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, upstream.header_buffer_size), + offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size), NULL }, + { ngx_string("proxy_header_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size), + &ngx_conf_deprecated_proxy_header_buffer_size }, + { ngx_string("proxy_read_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -333,6 +351,7 @@ static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF; static ngx_table_elt_t ngx_http_proxy_headers[] = { { 0, ngx_string("Host"), ngx_string("$proxy_host") }, { 0, ngx_string("Connection"), ngx_string("close") }, + { 0, ngx_string("Keep-Alive"), ngx_string("") }, { 0, ngx_null_string, ngx_null_string } }; @@ -395,7 +414,15 @@ ngx_http_proxy_handler(ngx_http_request_t *r) u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; } - u->pipe.input_filter = ngx_event_pipe_copy_input_filter; + if (plcf->upstream.buffering) { + + u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); + if (u->pipe == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + u->pipe->input_filter = ngx_event_pipe_copy_input_filter; + } u->accel = 1; @@ -828,7 +855,7 @@ ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) state = r->state; - for (pos = u->header_in.pos; pos < u->header_in.last; pos++) { + for (pos = u->buffer.pos; pos < u->buffer.last; pos++) { ch = *pos; switch (state) { @@ -986,14 +1013,14 @@ ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) } } - u->header_in.pos = pos; + u->buffer.pos = pos; r->state = state; return NGX_AGAIN; done: - u->header_in.pos = pos + 1; + u->buffer.pos = pos + 1; if (p->status_end == NULL) { p->status_end = pos; @@ -1019,7 +1046,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r) for ( ;; ) { - rc = ngx_http_parse_header_line(r, &r->upstream->header_in); + rc = ngx_http_parse_header_line(r, &r->upstream->buffer); if (rc == NGX_OK) { @@ -1359,7 +1386,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * conf->upstream.bufs.num = 0; - * conf->upstream.path = NULL; * conf->upstream.next_upstream = 0; * conf->upstream.temp_path = NULL; * conf->upstream.schema = { 0, NULL }; @@ -1377,12 +1403,14 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * conf->rewrite_locations = NULL; */ + conf->upstream.buffering = NGX_CONF_UNSET; + conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; - conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; + conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; @@ -1426,6 +1454,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; + ngx_conf_merge_value(conf->upstream.buffering, + prev->upstream.buffering, 1); + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -1438,8 +1469,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); - ngx_conf_merge_size_value(conf->upstream.header_buffer_size, - prev->upstream.header_buffer_size, + ngx_conf_merge_size_value(conf->upstream.buffer_size, + prev->upstream.buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, @@ -1452,7 +1483,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } - size = conf->upstream.header_buffer_size; + size = conf->upstream.buffer_size; if (size < conf->upstream.bufs.size) { size = conf->upstream.bufs.size; } diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 05e2c9376..7b21eae25 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -136,7 +136,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r) || r->headers_out.status != NGX_HTTP_OK || r->main != r || r->headers_out.content_length_n == -1 - || !r->filter_allow_ranges) + || !r->allow_ranges) { return ngx_http_next_header_filter(r); } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index 8732423fd..210bbf6f3 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -264,7 +264,7 @@ ngx_http_realip_init(ngx_cycle_t *cycle) *h = ngx_http_realip_handler; - h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers); + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); if (h == NULL) { return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index 74cd010a0..808d945ac 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -256,7 +256,7 @@ ngx_http_static_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - r->filter_allow_ranges = 1; + r->allow_ranges = 1; rc = ngx_http_send_header(r); |