⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngx_http_range_filter_module.c

📁 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>/* * the single part format: * * "HTTP/1.0 206 Partial Content" CRLF * ... header ... * "Content-Type: image/jpeg" CRLF * "Content-Length: SIZE" CRLF * "Content-Range: bytes START-END/SIZE" CRLF * CRLF * ... data ... * * * the mutlipart format: * * "HTTP/1.0 206 Partial Content" CRLF * ... header ... * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF * CRLF * CRLF * "--0123456789" CRLF * "Content-Type: image/jpeg" CRLF * "Content-Range: bytes START0-END0/SIZE" CRLF * CRLF * ... data ... * CRLF * "--0123456789" CRLF * "Content-Type: image/jpeg" CRLF * "Content-Range: bytes START1-END1/SIZE" CRLF * CRLF * ... data ... * CRLF * "--0123456789--" CRLF */typedef struct {    off_t        start;    off_t        end;    ngx_str_t    content_range;} ngx_http_range_t;typedef struct {    off_t        offset;    ngx_str_t    boundary_header;    ngx_array_t  ranges;} ngx_http_range_filter_ctx_t;static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf);static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf);static ngx_http_module_t  ngx_http_range_header_filter_module_ctx = {    NULL,                                  /* preconfiguration */    ngx_http_range_header_filter_init,     /* postconfiguration */    NULL,                                  /* create main configuration */    NULL,                                  /* init main configuration */    NULL,                                  /* create server configuration */    NULL,                                  /* merge server configuration */    NULL,                                  /* create location configuration */    NULL,                                  /* merge location configuration */};ngx_module_t  ngx_http_range_header_filter_module = {    NGX_MODULE_V1,    &ngx_http_range_header_filter_module_ctx, /* module context */    NULL,                                  /* 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};static ngx_http_module_t  ngx_http_range_body_filter_module_ctx = {    NULL,                                  /* preconfiguration */    ngx_http_range_body_filter_init,       /* postconfiguration */    NULL,                                  /* create main configuration */    NULL,                                  /* init main configuration */    NULL,                                  /* create server configuration */    NULL,                                  /* merge server configuration */    NULL,                                  /* create location configuration */    NULL,                                  /* merge location configuration */};ngx_module_t  ngx_http_range_body_filter_module = {    NGX_MODULE_V1,    &ngx_http_range_body_filter_module_ctx, /* module context */    NULL,                                  /* 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};static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;static ngx_int_tngx_http_range_header_filter(ngx_http_request_t *r){    u_char                       *p;    size_t                        len;    off_t                         start, end;    time_t                        if_range;    ngx_int_t                     rc;    ngx_uint_t                    suffix, i;    ngx_atomic_uint_t             boundary;    ngx_table_elt_t              *content_range;    ngx_http_range_t             *range;    ngx_http_range_filter_ctx_t  *ctx;    if (r->http_version < NGX_HTTP_VERSION_10        || r->headers_out.status != NGX_HTTP_OK        || r != r->main        || r->headers_out.content_length_n == -1        || !r->allow_ranges)    {        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,                           (u_char *) "bytes=", 6)           != 0)    {        goto next_filter;    }    if (r->headers_in.if_range && r->headers_out.last_modified_time != -1) {        if_range = ngx_http_parse_time(r->headers_in.if_range->value.data,                                       r->headers_in.if_range->value.len);        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                       "http ir:%d lm:%d",                       if_range, r->headers_out.last_modified_time);        if (if_range != r->headers_out.last_modified_time) {            goto next_filter;        }    }    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_range_filter_ctx_t));    if (ctx == NULL) {        return NGX_ERROR;    }    if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t))        == NGX_ERROR)    {        return NGX_ERROR;    }    rc = 0;    range = NULL;    p = r->headers_in.range->value.data + 6;    for ( ;; ) {        start = 0;        end = 0;        suffix = 0;        while (*p == ' ') { p++; }        if (*p != '-') {            if (*p < '0' || *p > '9') {                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;                break;            }            while (*p >= '0' && *p <= '9') {                start = start * 10 + *p++ - '0';            }            while (*p == ' ') { p++; }            if (*p++ != '-') {                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;                break;            }            if (start >= r->headers_out.content_length_n) {                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;                break;            }            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++ != ',') {                    break;                }                continue;            }        } else {            suffix = 1;            p++;        }        if (*p < '0' || *p > '9') {            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;            break;        }        while (*p >= '0' && *p <= '9') {            end = end * 10 + *p++ - '0';        }        while (*p == ' ') { p++; }        if (*p != ',' && *p != '\0') {            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;            break;        }        if (suffix) {           start = r->headers_out.content_length_n - end;           end = r->headers_out.content_length_n - 1;        }        if (start > end) {            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;            break;        }        range = ngx_array_push(&ctx->ranges);        if (range == NULL) {            return NGX_ERROR;        }        range->start = start;        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;        } else {            range->end = end + 1;        }        if (*p++ != ',') {            break;        }    }    if (rc) {        /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */        r->headers_out.status = rc;        content_range = ngx_list_push(&r->headers_out.headers);        if (content_range == NULL) {            return NGX_ERROR;        }        r->headers_out.content_range = content_range;        content_range->hash = 1;        content_range->key.len = sizeof("Content-Range") - 1;        content_range->key.data = (u_char *) "Content-Range";        content_range->value.data = ngx_palloc(r->pool,                                       sizeof("bytes */") - 1 + NGX_OFF_T_LEN);        if (content_range->value.data == NULL) {            return NGX_ERROR;        }        content_range->value.len = ngx_sprintf(content_range->value.data,                                               "bytes */%O",                                               r->headers_out.content_length_n)                                   - content_range->value.data;        ngx_http_clear_content_length(r);        return rc;    }    ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);    r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;    if (ctx->ranges.nelts == 1) {        content_range = ngx_list_push(&r->headers_out.headers);        if (content_range == NULL) {            return NGX_ERROR;        }        r->headers_out.content_range = content_range;        content_range->hash = 1;        content_range->key.len = sizeof("Content-Range") - 1;        content_range->key.data = (u_char *) "Content-Range";        content_range->value.data =               ngx_palloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);        if (content_range->value.data == NULL) {            return NGX_ERROR;        }        /* "Content-Range: bytes SSSS-EEEE/TTTT" header */        content_range->value.len = ngx_sprintf(content_range->value.data,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -