diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/http/modules/ngx_http_range_filter_module.c | 105 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.c | 10 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.h | 1 |
3 files changed, 67 insertions, 49 deletions
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index e11240660..02d2bf925 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -58,8 +58,8 @@ typedef struct { } ngx_http_range_filter_ctx_t; -ngx_int_t ngx_http_range_parse(ngx_http_request_t *r, - ngx_http_range_filter_ctx_t *ctx); +static ngx_int_t ngx_http_range_parse(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx, ngx_uint_t ranges); static ngx_int_t ngx_http_range_singlepart_header(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx); static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, @@ -146,7 +146,7 @@ static ngx_int_t ngx_http_range_header_filter(ngx_http_request_t *r) { time_t if_range; - ngx_int_t rc; + ngx_http_core_loc_conf_t *clcf; ngx_http_range_filter_ctx_t *ctx; if (r->http_version < NGX_HTTP_VERSION_10 @@ -158,6 +158,12 @@ ngx_http_range_header_filter(ngx_http_request_t *r) return ngx_http_next_header_filter(r); } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->max_ranges == 0) { + return ngx_http_next_header_filter(r); + } + if (r->headers_in.range == NULL || r->headers_in.range->value.len < 7 || ngx_strncasecmp(r->headers_in.range->value.data, @@ -192,10 +198,9 @@ ngx_http_range_header_filter(ngx_http_request_t *r) return NGX_ERROR; } - rc = ngx_http_range_parse(r, ctx); - - if (rc == NGX_OK) { + switch (ngx_http_range_parse(r, ctx, clcf->max_ranges)) { + case NGX_OK: ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; @@ -206,15 +211,16 @@ ngx_http_range_header_filter(ngx_http_request_t *r) } return ngx_http_range_multipart_header(r, ctx); - } - if (rc == NGX_HTTP_RANGE_NOT_SATISFIABLE) { + case NGX_HTTP_RANGE_NOT_SATISFIABLE: return ngx_http_range_not_satisfiable(r); - } - /* rc == NGX_ERROR */ + case NGX_ERROR: + return NGX_ERROR; - return rc; + default: /* NGX_DECLINED */ + break; + } next_filter: @@ -231,15 +237,18 @@ next_filter: } -ngx_int_t -ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) +static ngx_int_t +ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, + ngx_uint_t ranges) { u_char *p; - off_t start, end; + off_t start, end, size, content_length; ngx_uint_t suffix; ngx_http_range_t *range; p = r->headers_in.range->value.data + 6; + size = 0; + content_length = r->headers_out.content_length_n; for ( ;; ) { start = 0; @@ -263,26 +272,11 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - if (start >= r->headers_out.content_length_n) { - return NGX_HTTP_RANGE_NOT_SATISFIABLE; - } - while (*p == ' ') { p++; } if (*p == ',' || *p == '\0') { - range = ngx_array_push(&ctx->ranges); - if (range == NULL) { - return NGX_ERROR; - } - - range->start = start; - range->end = r->headers_out.content_length_n; - - if (*p++ != ',') { - return NGX_OK; - } - - continue; + end = content_length; + goto found; } } else { @@ -305,36 +299,49 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) } if (suffix) { - start = r->headers_out.content_length_n - end; - end = r->headers_out.content_length_n - 1; + start = content_length - end; + end = content_length - 1; } - if (start > end) { - return NGX_HTTP_RANGE_NOT_SATISFIABLE; - } + if (end >= content_length) { + end = content_length; - range = ngx_array_push(&ctx->ranges); - if (range == NULL) { - return NGX_ERROR; + } else { + end++; } - range->start = start; + found: - if (end >= r->headers_out.content_length_n) { - /* - * Download Accelerator sends the last byte position - * that equals to the file length - */ - range->end = r->headers_out.content_length_n; + if (start < end) { + range = ngx_array_push(&ctx->ranges); + if (range == NULL) { + return NGX_ERROR; + } - } else { - range->end = end + 1; + range->start = start; + range->end = end; + + size += end - start; + + if (ranges-- == 0) { + return NGX_DECLINED; + } } if (*p++ != ',') { - return NGX_OK; + break; } } + + if (ctx->ranges.nelts == 0) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + if (size > content_length) { + return NGX_DECLINED; + } + + return NGX_OK; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index bbb9311cf..ebe22ceaf 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -631,6 +631,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, if_modified_since), &ngx_http_core_if_modified_since }, + { ngx_string("max_ranges"), + 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_core_loc_conf_t, max_ranges), + NULL }, + { ngx_string("chunked_transfer_encoding"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, @@ -3253,6 +3260,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->keepalive_disable = NGX_CONF_UNSET_UINT; clcf->satisfy = NGX_CONF_UNSET_UINT; clcf->if_modified_since = NGX_CONF_UNSET_UINT; + clcf->max_ranges = NGX_CONF_UNSET_UINT; clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT; clcf->client_body_in_single_buffer = NGX_CONF_UNSET; clcf->internal = NGX_CONF_UNSET; @@ -3459,6 +3467,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) NGX_HTTP_SATISFY_ALL); ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since, NGX_HTTP_IMS_EXACT); + ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges, + 0x7fffffff); ngx_conf_merge_uint_value(conf->client_body_in_file_only, prev->client_body_in_file_only, 0); ngx_conf_merge_value(conf->client_body_in_single_buffer, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 165e7c051..df20b5d3a 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -363,6 +363,7 @@ struct ngx_http_core_loc_conf_s { ngx_uint_t satisfy; /* satisfy */ ngx_uint_t lingering_close; /* lingering_close */ ngx_uint_t if_modified_since; /* if_modified_since */ + ngx_uint_t max_ranges; /* max_ranges */ ngx_uint_t client_body_in_file_only; /* client_body_in_file_only */ ngx_flag_t client_body_in_single_buffer; |
