diff options
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_autoindex_module.c | 93 | ||||
-rw-r--r-- | src/http/modules/ngx_http_gzip_filter_module.c | 82 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 6 | ||||
-rw-r--r-- | src/http/modules/ngx_http_rewrite_module.c | 28 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssi_filter_module.c | 115 | ||||
-rw-r--r-- | src/http/modules/ngx_http_static_module.c | 6 | ||||
-rw-r--r-- | src/http/ngx_http_copy_filter_module.c | 12 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 17 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_postpone_filter_module.c | 15 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 52 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 3 | ||||
-rw-r--r-- | src/http/ngx_http_request_body.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_script.c | 10 | ||||
-rw-r--r-- | src/http/ngx_http_script.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_special_response.c | 3 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 86 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.h | 6 | ||||
-rw-r--r-- | src/http/ngx_http_variables.c | 4 | ||||
-rw-r--r-- | src/http/ngx_http_write_filter_module.c | 15 |
20 files changed, 430 insertions, 127 deletions
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c index e26d2947e..d12834083 100644 --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -35,6 +35,7 @@ typedef struct { typedef struct { ngx_flag_t enable; ngx_flag_t localtime; + ngx_flag_t exact_size; } ngx_http_autoindex_loc_conf_t; @@ -67,6 +68,13 @@ static ngx_command_t ngx_http_autoindex_commands[] = { offsetof(ngx_http_autoindex_loc_conf_t, localtime), NULL }, + { ngx_string("autoindex_exact_size"), + 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_autoindex_loc_conf_t, exact_size), + NULL }, + ngx_null_command }; @@ -117,10 +125,11 @@ static u_char tail[] = static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { - u_char *last; - size_t len; + u_char *last, scale; + off_t length; + size_t len, copy; ngx_tm_t tm; - ngx_int_t rc; + ngx_int_t rc, size; ngx_uint_t i, level; ngx_err_t err; ngx_buf_t *b; @@ -351,7 +360,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 - + 19 + + 20 + 2; } @@ -396,14 +405,27 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) *b->last++ = '"'; *b->last++ = '>'; - b->last = ngx_cpystrn(b->last, entry[i].name.data, - NGX_HTTP_AUTOINDEX_NAME_LEN + 1); - len = entry[i].utf_len; + if (len) { + if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { + copy = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; + + } else { + copy = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; + } + + b->last = ngx_utf_cpystrn(b->last, entry[i].name.data, copy); + last = b->last; + + } else { + b->last = ngx_cpystrn(b->last, entry[i].name.data, + NGX_HTTP_AUTOINDEX_NAME_LEN + 1); + last = b->last - 3; + } + if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { - b->last = ngx_cpymem(b->last - 3, "..></a>", - sizeof("..></a>") - 1); + b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1); } else { if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { @@ -427,12 +449,55 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) tm.ngx_tm_hour, tm.ngx_tm_min); - if (entry[i].dir) { - b->last = ngx_cpymem(b->last, " -", - sizeof(" -") - 1); + if (alcf->exact_size) { + if (entry[i].dir) { + b->last = ngx_cpymem(b->last, " -", + sizeof(" -") - 1); + } else { + b->last = ngx_sprintf(b->last, "%19O", entry[i].size); + } } else { - b->last = ngx_sprintf(b->last, "%19O", entry[i].size); + if (entry[i].dir) { + b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); + + } else { + length = entry[i].size; + + if (length > 1024 * 1024 * 1024 - 1) { + size = (ngx_int_t) (length / (1024 * 1024 * 1024)); + if ((length % (1024 * 1024 * 1024)) + > (1024 * 1024 * 1024 / 2 - 1)) + { + size++; + } + scale = 'G'; + + } else if (length > 1024 * 1024 - 1) { + size = (ngx_int_t) (length / (1024 * 1024)); + if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { + size++; + } + scale = 'M'; + + } else if (length > 9999) { + size = (ngx_int_t) (length / 1024); + if (length % 1024 > 511) { + size++; + } + scale = 'K'; + + } else { + size = (ngx_int_t) length; + scale = ' '; + } + + b->last = ngx_sprintf(b->last, "%6i", size); + + if (scale != ' ') { + *b->last++ = scale; + } + } } *b->last++ = CR; @@ -559,6 +624,7 @@ ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf) conf->enable = NGX_CONF_UNSET; conf->localtime = NGX_CONF_UNSET; + conf->exact_size = NGX_CONF_UNSET; return conf; } @@ -572,6 +638,7 @@ ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->localtime, prev->localtime, 0); + ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1); return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index f7cb92c18..596e52403 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -15,7 +15,7 @@ typedef struct { ngx_flag_t enable; ngx_flag_t no_buffer; - ngx_array_t *types; /* array of ngx_http_gzip_type_t */ + ngx_array_t *types; /* array of ngx_str_t */ ngx_bufs_t bufs; @@ -29,12 +29,6 @@ typedef struct { } ngx_http_gzip_conf_t; -typedef struct { - ngx_str_t name; - ngx_uint_t enable; -} ngx_http_gzip_type_t; - - #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 @@ -91,20 +85,18 @@ static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle); static void *ngx_http_gzip_create_conf(ngx_conf_t *cf); static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child); -static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, +static char *ngx_http_gzip_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data); -static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_gzip_window(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_gzip_hash(ngx_conf_t *cf, void *post, void *data); static ngx_conf_num_bounds_t ngx_http_gzip_comp_level_bounds = { ngx_conf_check_num_bounds, 1, 9 }; -static ngx_conf_post_handler_pt ngx_http_gzip_set_window_p = - ngx_http_gzip_set_window; -static ngx_conf_post_handler_pt ngx_http_gzip_set_hash_p = - ngx_http_gzip_set_hash; +static ngx_conf_post_handler_pt ngx_http_gzip_window_p = ngx_http_gzip_window; +static ngx_conf_post_handler_pt ngx_http_gzip_hash_p = ngx_http_gzip_hash; @@ -148,7 +140,7 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { { ngx_string("gzip_types"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_http_gzip_set_types, + ngx_http_gzip_types, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, @@ -165,14 +157,14 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_gzip_conf_t, wbits), - &ngx_http_gzip_set_window_p }, + &ngx_http_gzip_window_p }, { ngx_string("gzip_hash"), 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_gzip_conf_t, memlevel), - &ngx_http_gzip_set_hash_p }, + &ngx_http_gzip_hash_p }, { ngx_string("gzip_no_buffer"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, @@ -270,10 +262,10 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) { - ngx_uint_t i, found; + ngx_str_t *type; + ngx_uint_t i; ngx_http_gzip_ctx_t *ctx; ngx_http_gzip_conf_t *conf; - ngx_http_gzip_type_t *type; conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); @@ -297,24 +289,21 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r) } - found = 0; type = conf->types->elts; - for (i = 0; i < conf->types->nelts; i++) { - if (r->headers_out.content_type.len >= type[i].name.len + if (r->headers_out.content_type.len >= type[i].len && ngx_strncasecmp(r->headers_out.content_type.data, - type[i].name.data, type[i].name.len) == 0) + type[i].data, type[i].len) == 0) { - found = 1; - break; + goto found; } } - if (!found) { - return ngx_http_next_header_filter(r); - } + return ngx_http_next_header_filter(r); +found: + if (r->headers_in.via) { if (conf->proxied & NGX_HTTP_GZIP_PROXIED_OFF) { return ngx_http_next_header_filter(r); @@ -1031,7 +1020,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_gzip_conf_t *prev = parent; ngx_http_gzip_conf_t *conf = child; - ngx_http_gzip_type_t *type; + ngx_str_t *type; ngx_conf_merge_value(conf->enable, prev->enable, 0); @@ -1051,8 +1040,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->types == NULL) { if (prev->types == NULL) { - conf->types = ngx_array_create(cf->pool, 1, - sizeof(ngx_http_gzip_type_t)); + conf->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t)); if (conf->types == NULL) { return NGX_CONF_ERROR; } @@ -1062,9 +1050,8 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - type->name.len = sizeof("text/html") - 1; - type->name.data = (u_char *) "text/html"; - type->enable = 1; + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; } else { conf->types = prev->types; @@ -1076,17 +1063,15 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child) static char * -ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +ngx_http_gzip_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_gzip_conf_t *gcf = conf; - ngx_str_t *value; - ngx_uint_t i; - ngx_http_gzip_type_t *type; + ngx_str_t *value, *type; + ngx_uint_t i; if (gcf->types == NULL) { - gcf->types = ngx_array_create(cf->pool, 4, - sizeof(ngx_http_gzip_type_t)); + gcf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); if (gcf->types == NULL) { return NGX_CONF_ERROR; } @@ -1096,9 +1081,8 @@ ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - type->name.len = sizeof("text/html") - 1; - type->name.data = (u_char *) "text/html"; - type->enable = 1; + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; } value = cf->args->elts; @@ -1114,14 +1098,14 @@ ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - type->name.len = value[i].len; + type->len = value[i].len; - type->name.data = ngx_palloc(cf->pool, type->name.len + 1); - if (type->name.data == NULL) { + type->data = ngx_palloc(cf->pool, type->len + 1); + if (type->data == NULL) { return NGX_CONF_ERROR; } - ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1); + ngx_cpystrn(type->data, value[i].data, type->len + 1); } return NGX_CONF_OK; @@ -1129,7 +1113,7 @@ ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char * -ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data) +ngx_http_gzip_window(ngx_conf_t *cf, void *post, void *data) { int *np = data; @@ -1153,7 +1137,7 @@ ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data) static char * -ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data) +ngx_http_gzip_hash(ngx_conf_t *cf, void *post, void *data) { int *np = data; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 83625be7b..85503d0ac 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -914,7 +914,7 @@ ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) } break; - /* end of request line */ + /* end of status line */ case sw_almost_done: p->status_end = pos - 1; switch (ch) { @@ -926,7 +926,7 @@ ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) } } - u->header_in.pos = pos + 1; + u->header_in.pos = pos; r->state = state; return NGX_AGAIN; @@ -1803,7 +1803,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } for (i = 0; i < plcf->peers->number; i++) { - plcf->peers->peer[i].uri_separator = ":"; + plcf->peers->peer[i].uri_separator = ""; } plcf->host_header = inet_upstream.host_header; diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index ed7abd66a..5f73c026c 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -36,6 +36,8 @@ static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, @@ -66,6 +68,14 @@ static ngx_command_t ngx_http_rewrite_commands[] = { 0, NULL }, + { ngx_string("break"), + NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_NOARGS, + ngx_http_rewrite_break, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + { ngx_string("if"), NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, ngx_http_rewrite_if, @@ -601,6 +611,24 @@ ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char * +ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_rewrite_loc_conf_t *lcf = conf; + + ngx_http_script_code_pt *code; + + code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t)); + if (code == NULL) { + return NGX_CONF_ERROR; + } + + *code = ngx_http_script_break_code; + + return NGX_CONF_OK; +} + + +static char * ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_rewrite_loc_conf_t *lcf = conf; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 2992ff59d..856726a35 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -24,6 +24,8 @@ typedef struct { ngx_flag_t silent_errors; ngx_flag_t ignore_recycled_buffers; + ngx_array_t *types; /* array of ngx_str_t */ + size_t min_file_chunk; size_t value_len; } ngx_http_ssi_conf_t; @@ -127,6 +129,8 @@ static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r, static ngx_http_variable_value_t * ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt); +static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf); static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf, @@ -164,6 +168,13 @@ static ngx_command_t ngx_http_ssi_filter_commands[] = { offsetof(ngx_http_ssi_conf_t, min_file_chunk), NULL }, + { ngx_string("ssi_types"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_ssi_types, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; @@ -201,7 +212,7 @@ static ngx_int_t (*ngx_http_next_body_filter) (ngx_http_request_t *r, static u_char ngx_http_ssi_string[] = "<!--"; static u_char ngx_http_ssi_error_string[] = - "[an error occurred while processing the directive]"; + "[an error occurred while processing the directive]"; static ngx_str_t ngx_http_ssi_none = ngx_string("(none)"); @@ -280,24 +291,34 @@ static ngx_http_variable_t ngx_http_ssi_vars[] = { static ngx_int_t ngx_http_ssi_header_filter(ngx_http_request_t *r) { + ngx_uint_t i; + ngx_str_t *type; ngx_http_ssi_ctx_t *ctx; ngx_http_ssi_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); - if (!conf->enable) { + if (!conf->enable + || r->headers_out.content_type.len == 0) + { return ngx_http_next_header_filter(r); } - /* TODO: "text/html" -> custom types */ - if (r->headers_out.content_type.len == 0 - || ngx_strncasecmp(r->headers_out.content_type.data, "text/html", 5) - != 0) - { - return ngx_http_next_header_filter(r); + type = conf->types->elts; + for (i = 0; i < conf->types->nelts; i++) { + if (r->headers_out.content_type.len >= type[i].len + && ngx_strncasecmp(r->headers_out.content_type.data, + type[i].data, type[i].len) == 0) + { + goto found; + } } + return ngx_http_next_header_filter(r); + + +found: ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t)); if (ctx == NULL) { @@ -1632,6 +1653,56 @@ ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt) } +static char * +ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_ssi_conf_t *scf = conf; + + ngx_str_t *value, *type; + ngx_uint_t i; + + if (scf->types == NULL) { + scf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); + if (scf->types == NULL) { + return NGX_CONF_ERROR; + } + + type = ngx_array_push(scf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "text/html") == 0) { + continue; + } + + type = ngx_array_push(scf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = value[i].len; + + type->data = ngx_palloc(cf->pool, type->len + 1); + if (type->data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_cpystrn(type->data, value[i].data, type->len + 1); + } + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf) { @@ -1661,6 +1732,12 @@ ngx_http_ssi_create_conf(ngx_conf_t *cf) return NGX_CONF_ERROR; } + /* + * set by ngx_pcalloc(): + * + * conf->types = NULL; + */ + conf->enable = NGX_CONF_UNSET; conf->silent_errors = NGX_CONF_UNSET; conf->ignore_recycled_buffers = NGX_CONF_UNSET; @@ -1678,6 +1755,8 @@ ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_ssi_conf_t *prev = parent; ngx_http_ssi_conf_t *conf = child; + ngx_str_t *type; + ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0); ngx_conf_merge_value(conf->ignore_recycled_buffers, @@ -1686,6 +1765,26 @@ ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024); ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256); + if (conf->types == NULL) { + if (prev->types == NULL) { + conf->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t)); + if (conf->types == NULL) { + return NGX_CONF_ERROR; + } + + type = ngx_array_push(conf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; + + } else { + conf->types = prev->types; + } + } + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index a84a70eb6..54e624fa8 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -210,8 +210,10 @@ ngx_http_static_handler(ngx_http_request_t *r) rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } - ngx_log_error(level, log, err, - ngx_open_file_n " \"%s\" failed", name.data); + if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { + ngx_log_error(level, log, err, + ngx_open_file_n " \"%s\" failed", name.data); + } return rc; } diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index 5561134da..46715482a 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -68,13 +68,17 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_output_chain_ctx_t *ctx; ngx_http_copy_filter_conf_t *conf; - if (r->connection->write->error) { - return NGX_ERROR; - } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "copy filter: \"%V\"", &r->uri); + if (r->connection->closed) { + rc = ngx_http_next_filter(r, in); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "copy closed filter: %i \"%V\"", rc, &r->uri); + return rc; + } + ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module); if (ctx == NULL) { diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 1d399704f..ad5058512 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -326,6 +326,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, msie_padding), NULL }, + { ngx_string("log_not_found"), + 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_core_loc_conf_t, log_not_found), + NULL }, + { ngx_string("error_page"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_2MORE, @@ -633,6 +640,8 @@ ngx_http_find_location_config(ngx_http_request_t *r) return NGX_HTTP_MOVED_PERMANENTLY; } + r->limit_rate = clcf->limit_rate; + if (clcf->handler) { r->content_handler = clcf->handler; } @@ -862,10 +871,6 @@ ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; - if (r->connection->write->error) { - return NGX_ERROR; - } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http output filter \"%V\"", &r->uri); @@ -873,7 +878,7 @@ ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in) if (rc == NGX_ERROR) { /* NGX_ERROR may be returned by any filter */ - r->connection->write->error = 1; + r->connection->closed = 1; } return rc; @@ -1727,6 +1732,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) lcf->reset_timedout_connection = NGX_CONF_UNSET; lcf->port_in_redirect = NGX_CONF_UNSET; lcf->msie_padding = NGX_CONF_UNSET; + lcf->log_not_found = NGX_CONF_UNSET; return lcf; } @@ -1841,6 +1847,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, prev->reset_timedout_connection, 0); ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1); ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1); + ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1); if (conf->open_files == NULL) { conf->open_files = prev->open_files; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 11640467e..1f6b185ca 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -224,6 +224,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ ngx_flag_t port_in_redirect; /* port_in_redirect */ ngx_flag_t msie_padding; /* msie_padding */ + ngx_flag_t log_not_found; /* log_not_found */ ngx_array_t *error_pages; /* error_page */ diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c index 8e47816fb..d7d338f09 100644 --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -48,13 +48,18 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_http_request_t *mr; ngx_http_postponed_request_t *pr, **ppr; - if (r->connection->write->error) { - return NGX_ERROR; - } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http postpone filter \"%V\" %p", &r->uri, in); + if (r->connection->closed) { + + if (r->postponed) { + r->postponed = r->postponed->next; + } + + return NGX_ERROR; + } + if (r != r->connection->data || (r->postponed && in)) { if (r->postponed) { @@ -112,7 +117,7 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) if (rc == NGX_ERROR) { /* NGX_ERROR may be returned by any filter */ - r->connection->write->error = 1; + r->connection->closed = 1; } return rc; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 9ced028a5..f41a891b7 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -90,11 +90,6 @@ ngx_http_header_t ngx_http_headers_in[] = { { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range), ngx_http_process_header_line }, -#if 0 - { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range), - ngx_http_process_header_line }, -#endif - #if (NGX_HTTP_GZIP) { ngx_string("Accept-Encoding"), offsetof(ngx_http_headers_in_t, accept_encoding), @@ -1441,6 +1436,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) r->done = 1; if (r != r->connection->data) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http finalize non-active request: \"%V\"", &r->uri); return; } @@ -1448,12 +1445,18 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) pr = r->parent; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http parent request: \"%V\"", &pr->uri); + if (rc != NGX_AGAIN) { pr->connection->data = pr; } if (pr->postponed) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http request: \"%V\" has postponed", &pr->uri); + if (rc != NGX_AGAIN && pr->postponed->request == r) { pr->postponed = pr->postponed->next; @@ -1462,9 +1465,13 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) } } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http request: \"%V\" still has postponed", + &pr->uri); + if (pr->done) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http wake request: \"%V\"", &pr->uri); + "http wake parent request: \"%V\"", &pr->uri); pr->write_event_handler(pr); } @@ -1483,7 +1490,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) ngx_del_timer(r->connection->write); } - if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST || r->closed) { + if (r->connection->closed) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); return; @@ -1492,13 +1499,15 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc)); return; + } - } else if (rc == NGX_ERROR) { + if (rc == NGX_ERROR || r->connection->closed) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); return; + } - } else if (rc == NGX_AGAIN || r->out) { + if (rc == NGX_AGAIN || r->out) { (void) ngx_http_set_write_handler(r); return; } @@ -1553,6 +1562,10 @@ ngx_http_set_write_handler(ngx_http_request_t *r) r->write_event_handler = ngx_http_writer; + if (r->connection->closed) { + return NGX_OK; + } + wev = r->connection->write; if (wev->ready && wev->delayed) { @@ -1673,6 +1686,9 @@ static ngx_int_t ngx_http_postponed_handler(ngx_http_request_t *r) { ngx_int_t rc; +#if 0 + ngx_http_request_t *mr; +#endif ngx_http_postponed_request_t *pr; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1687,20 +1703,16 @@ ngx_http_postponed_handler(ngx_http_request_t *r) rc = ngx_http_output_filter(r, NULL); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postponed output filter: %d", rc); + "http postponed output filter: %d", rc); if (rc == NGX_AGAIN) { return rc; } - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->write->error = 1; - - ngx_http_finalize_request(r, rc); - - return NGX_DONE; - } + /* + * we treat NGX_ERROR as NGX_OK, because we need to complete + * all postponed requests + */ pr = r->postponed; @@ -1713,7 +1725,7 @@ ngx_http_postponed_handler(ngx_http_request_t *r) r->connection->data = r; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postponed request \"%V\"", &r->uri); + "http wake child request \"%V\"", &r->uri); r->write_event_handler(r); @@ -1833,7 +1845,7 @@ ngx_http_read_discarded_body(ngx_http_request_t *r) if (n == NGX_ERROR) { - r->closed = 1; + r->connection->closed = 1; /* * if a client request body is discarded then we already set diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 470f58459..d1ba774ef 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -310,6 +310,8 @@ struct ngx_http_request_s { ngx_http_variable_value_t **variables; + size_t limit_rate; + /* used to learn the Apache compatible response length without a header */ size_t header_size; @@ -361,7 +363,6 @@ struct ngx_http_request_s { unsigned keepalive:1; unsigned lingering_close:1; unsigned internal:1; - unsigned closed:1; unsigned done:1; unsigned utf8:1; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 42edfef52..eb2e6a570 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -236,7 +236,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) } if (n == 0 || n == NGX_ERROR) { - r->closed = 1; + c->closed = 1; return NGX_HTTP_BAD_REQUEST; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 89256b355..716a6f054 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -558,6 +558,7 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e) if (code->break_cycle) { r->valid_location = 0; + r->uri_changed = 0; } else { r->uri_changed = 1; @@ -713,6 +714,15 @@ ngx_http_script_return_code(ngx_http_script_engine_t *e) void +ngx_http_script_break_code(ngx_http_script_engine_t *e) +{ + e->request->uri_changed = 0; + + e->ip = ngx_http_script_exit; +} + + +void ngx_http_script_if_code(ngx_http_script_engine_t *e) { ngx_http_script_if_code_t *code; diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index eb6f17ea9..21625427f 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -166,6 +166,7 @@ void ngx_http_script_regex_start_code(ngx_http_script_engine_t *e); void ngx_http_script_regex_end_code(ngx_http_script_engine_t *e); #endif void ngx_http_script_return_code(ngx_http_script_engine_t *e); +void ngx_http_script_break_code(ngx_http_script_engine_t *e); void ngx_http_script_if_code(ngx_http_script_engine_t *e); void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e); void ngx_http_script_value_code(ngx_http_script_engine_t *e); diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index 7a341599a..14d4c8022 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -244,6 +244,9 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) ngx_http_err_page_t *err_page; ngx_http_core_loc_conf_t *clcf; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http special response: %d, \"%V\"", error, &r->uri); + rc = ngx_http_discard_body(r); if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index d7ee08f72..8571b869b 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -39,6 +39,8 @@ static ngx_int_t ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t @@ -143,6 +145,10 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), ngx_http_upstream_ignore_header_line, 0, 0 }, + { ngx_string("X-Accel-Limit-Rate"), + ngx_http_upstream_process_limit_rate, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + #if (NGX_HTTP_GZIP) { ngx_string("Content-Encoding"), ngx_http_upstream_process_header_line, @@ -299,12 +305,19 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, ngx_connection_t *c; ngx_http_upstream_t *u; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0, - "http upstream check client, write event:%d", ev->write); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, + "http upstream check client, write event:%d, \"%V\"", + ev->write, &r->uri); c = r->connection; u = r->upstream; + if (c->closed) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + if (u->peer.connection == NULL) { return; } @@ -318,6 +331,7 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, } ev->eof = 1; + c->closed = 1; if (ev->kq_errno) { ev->error = 1; @@ -325,9 +339,8 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, if (!u->cachable && u->peer.connection) { ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, - "kevent() reported that client closed " - "prematurely connection, " - "so upstream connection is closed too"); + "kevent() reported that client closed prematurely " + "connection, so upstream connection is closed too"); ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); return; @@ -374,6 +387,7 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, } ev->eof = 1; + c->closed = 1; if (n == -1) { if (err == NGX_EAGAIN) { @@ -924,6 +938,8 @@ ngx_http_upstream_process_header(ngx_event_t *rev) } } + r->headers_out.status_line.len = 0; + ngx_http_internal_redirect(r, &r->upstream->headers_in.x_accel_redirect->value, NULL); @@ -1155,9 +1171,33 @@ ngx_http_upstream_process_body(ngx_event_t *ev) if (ev->timedout) { if (ev->write) { - p->downstream_error = 1; - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, - "client timed out"); + if (ev->delayed) { + + ev->timedout = 0; + ev->delayed = 0; + + if (!ev->ready) { + ngx_add_timer(ev, p->send_timeout); + + if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) + { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + return; + } + + if (ngx_event_pipe(p, ev->write) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + } else { + p->downstream_error = 1; + ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, + "client timed out"); + } } else { p->upstream_error = 1; @@ -1166,6 +1206,17 @@ ngx_http_upstream_process_body(ngx_event_t *ev) } } else { + if (ev->write && ev->delayed) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http downstream delayed"); + + if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) { + return; + } + + return; + } + if (ngx_event_pipe(p, ev->write) == NGX_ABORT) { ngx_http_upstream_finalize_request(r, u, 0); return; @@ -1281,6 +1332,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, } if (r->connection->write->eof) { + r->connection->closed = 1; ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); return; @@ -1432,6 +1484,24 @@ ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, static ngx_int_t +ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_int_t n; + + r->upstream->headers_in.x_accel_limit_rate = h; + + n = ngx_atoi(h->value.data, h->value.len); + + if (n != NGX_ERROR) { + r->limit_rate = (size_t) n; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 00a64aca6..428253c42 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -48,6 +48,7 @@ typedef struct { ngx_msec_t connect_timeout; ngx_msec_t send_timeout; ngx_msec_t read_timeout; + ngx_msec_t timeout; size_t send_lowat; size_t header_buffer_size; @@ -103,6 +104,7 @@ typedef struct { ngx_table_elt_t *etag; ngx_table_elt_t *x_accel_expires; ngx_table_elt_t *x_accel_redirect; + ngx_table_elt_t *x_accel_limit_rate; ngx_table_elt_t *content_type; ngx_table_elt_t *content_length; @@ -120,8 +122,6 @@ typedef struct { struct ngx_http_upstream_s { - ngx_http_request_t *request; - ngx_peer_connection_t peer; ngx_event_pipe_t pipe; @@ -146,6 +146,8 @@ struct ngx_http_upstream_s { ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix); + ngx_msec_t timeout; + ngx_uint_t method; ngx_http_log_handler_pt saved_log_handler; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index d66f0dc6c..2a5cf7dcd 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -706,7 +706,9 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) { v[i].handler = av[n].handler; v[i].data = av[n].data; - v[i].flags = av[n].flags | NGX_HTTP_VAR_INDEXED; + + av[n].flags |= NGX_HTTP_VAR_INDEXED; + v[i].flags = av[n].flags; goto next; } diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c index b872f3dd1..af95c99cd 100644 --- a/src/http/ngx_http_write_filter_module.c +++ b/src/http/ngx_http_write_filter_module.c @@ -47,6 +47,12 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; + c = r->connection; + + if (c->closed) { + return NGX_ERROR; + } + size = 0; flush = 0; last = 0; @@ -151,8 +157,6 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) *ll = NULL; - c = r->connection; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "http write filter: l:%d f:%d s:%O", last, flush, size); @@ -197,19 +201,20 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) sent = c->sent; - chain = c->send_chain(c, r->out, clcf->limit_rate); + chain = c->send_chain(c, r->out, r->limit_rate); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http write filter %p", chain); - if (clcf->limit_rate) { + if (r->limit_rate) { sent = c->sent - sent; c->write->delayed = 1; ngx_add_timer(r->connection->write, - (ngx_msec_t) (sent * 1000 / clcf->limit_rate)); + (ngx_msec_t) (sent * 1000 / r->limit_rate)); } if (chain == NGX_CHAIN_ERROR) { + c->closed = 1; return NGX_ERROR; } |