Annotation of embedaddon/nginx/src/http/modules/ngx_http_not_modified_filter_module.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: #include <ngx_http.h>
        !            11: 
        !            12: 
        !            13: static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
        !            14: static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
        !            15: static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
        !            16:     ngx_table_elt_t *header);
        !            17: static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
        !            18: 
        !            19: 
        !            20: static ngx_http_module_t  ngx_http_not_modified_filter_module_ctx = {
        !            21:     NULL,                                  /* preconfiguration */
        !            22:     ngx_http_not_modified_filter_init,     /* postconfiguration */
        !            23: 
        !            24:     NULL,                                  /* create main configuration */
        !            25:     NULL,                                  /* init main configuration */
        !            26: 
        !            27:     NULL,                                  /* create server configuration */
        !            28:     NULL,                                  /* merge server configuration */
        !            29: 
        !            30:     NULL,                                  /* create location configuration */
        !            31:     NULL                                   /* merge location configuration */
        !            32: };
        !            33: 
        !            34: 
        !            35: ngx_module_t  ngx_http_not_modified_filter_module = {
        !            36:     NGX_MODULE_V1,
        !            37:     &ngx_http_not_modified_filter_module_ctx, /* module context */
        !            38:     NULL,                                  /* module directives */
        !            39:     NGX_HTTP_MODULE,                       /* module type */
        !            40:     NULL,                                  /* init master */
        !            41:     NULL,                                  /* init module */
        !            42:     NULL,                                  /* init process */
        !            43:     NULL,                                  /* init thread */
        !            44:     NULL,                                  /* exit thread */
        !            45:     NULL,                                  /* exit process */
        !            46:     NULL,                                  /* exit master */
        !            47:     NGX_MODULE_V1_PADDING
        !            48: };
        !            49: 
        !            50: 
        !            51: static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
        !            52: 
        !            53: 
        !            54: static ngx_int_t
        !            55: ngx_http_not_modified_header_filter(ngx_http_request_t *r)
        !            56: {
        !            57:     if (r->headers_out.status != NGX_HTTP_OK
        !            58:         || r != r->main
        !            59:         || r->headers_out.last_modified_time == -1)
        !            60:     {
        !            61:         return ngx_http_next_header_filter(r);
        !            62:     }
        !            63: 
        !            64:     if (r->headers_in.if_unmodified_since
        !            65:         && !ngx_http_test_if_unmodified(r))
        !            66:     {
        !            67:         return ngx_http_filter_finalize_request(r, NULL,
        !            68:                                                 NGX_HTTP_PRECONDITION_FAILED);
        !            69:     }
        !            70: 
        !            71:     if (r->headers_in.if_match
        !            72:         && !ngx_http_test_if_match(r, r->headers_in.if_match))
        !            73:     {
        !            74:         return ngx_http_filter_finalize_request(r, NULL,
        !            75:                                                 NGX_HTTP_PRECONDITION_FAILED);
        !            76:     }
        !            77: 
        !            78:     if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
        !            79: 
        !            80:         if (r->headers_in.if_modified_since
        !            81:             && ngx_http_test_if_modified(r))
        !            82:         {
        !            83:             return ngx_http_next_header_filter(r);
        !            84:         }
        !            85: 
        !            86:         if (r->headers_in.if_none_match
        !            87:             && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
        !            88:         {
        !            89:             return ngx_http_next_header_filter(r);
        !            90:         }
        !            91: 
        !            92:         /* not modified */
        !            93: 
        !            94:         r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
        !            95:         r->headers_out.status_line.len = 0;
        !            96:         r->headers_out.content_type.len = 0;
        !            97:         ngx_http_clear_content_length(r);
        !            98:         ngx_http_clear_accept_ranges(r);
        !            99: 
        !           100:         if (r->headers_out.content_encoding) {
        !           101:             r->headers_out.content_encoding->hash = 0;
        !           102:             r->headers_out.content_encoding = NULL;
        !           103:         }
        !           104: 
        !           105:         return ngx_http_next_header_filter(r);
        !           106:     }
        !           107: 
        !           108:     return ngx_http_next_header_filter(r);
        !           109: }
        !           110: 
        !           111: 
        !           112: static ngx_uint_t
        !           113: ngx_http_test_if_unmodified(ngx_http_request_t *r)
        !           114: {
        !           115:     time_t  iums;
        !           116: 
        !           117:     iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data,
        !           118:                                r->headers_in.if_unmodified_since->value.len);
        !           119: 
        !           120:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           121:                  "http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
        !           122: 
        !           123:     if (iums >= r->headers_out.last_modified_time) {
        !           124:         return 1;
        !           125:     }
        !           126: 
        !           127:     return 0;
        !           128: }
        !           129: 
        !           130: 
        !           131: static ngx_uint_t
        !           132: ngx_http_test_if_modified(ngx_http_request_t *r)
        !           133: {
        !           134:     time_t                     ims;
        !           135:     ngx_http_core_loc_conf_t  *clcf;
        !           136: 
        !           137:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !           138: 
        !           139:     if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
        !           140:         return 1;
        !           141:     }
        !           142: 
        !           143:     ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
        !           144:                               r->headers_in.if_modified_since->value.len);
        !           145: 
        !           146:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           147:                    "http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
        !           148: 
        !           149:     if (ims == r->headers_out.last_modified_time) {
        !           150:         return 0;
        !           151:     }
        !           152: 
        !           153:     if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
        !           154:         || ims < r->headers_out.last_modified_time)
        !           155:     {
        !           156:         return 1;
        !           157:     }
        !           158: 
        !           159:     return 0;
        !           160: }
        !           161: 
        !           162: 
        !           163: static ngx_uint_t
        !           164: ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
        !           165: {
        !           166:     u_char     *start, *end, ch;
        !           167:     ngx_str_t  *etag, *list;
        !           168: 
        !           169:     list = &header->value;
        !           170: 
        !           171:     if (list->len == 1 && list->data[0] == '*') {
        !           172:         return 1;
        !           173:     }
        !           174: 
        !           175:     if (r->headers_out.etag == NULL) {
        !           176:         return 0;
        !           177:     }
        !           178: 
        !           179:     etag = &r->headers_out.etag->value;
        !           180: 
        !           181:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           182:                    "http im:\"%V\" etag:%V", list, etag);
        !           183: 
        !           184:     start = list->data;
        !           185:     end = list->data + list->len;
        !           186: 
        !           187:     while (start < end) {
        !           188: 
        !           189:         if (etag->len > (size_t) (end - start)) {
        !           190:             return 0;
        !           191:         }
        !           192: 
        !           193:         if (ngx_strncmp(start, etag->data, etag->len) != 0) {
        !           194:             goto skip;
        !           195:         }
        !           196: 
        !           197:         start += etag->len;
        !           198: 
        !           199:         while (start < end) {
        !           200:             ch = *start;
        !           201: 
        !           202:             if (ch == ' ' || ch == '\t') {
        !           203:                 start++;
        !           204:                 continue;
        !           205:             }
        !           206: 
        !           207:             break;
        !           208:         }
        !           209: 
        !           210:         if (start == end || *start == ',') {
        !           211:             return 1;
        !           212:         }
        !           213: 
        !           214:     skip:
        !           215: 
        !           216:         while (start < end && *start != ',') { start++; }
        !           217:         while (start < end) {
        !           218:             ch = *start;
        !           219: 
        !           220:             if (ch == ' ' || ch == '\t' || ch == ',') {
        !           221:                 start++;
        !           222:                 continue;
        !           223:             }
        !           224: 
        !           225:             break;
        !           226:         }
        !           227:     }
        !           228: 
        !           229:     return 0;
        !           230: }
        !           231: 
        !           232: 
        !           233: static ngx_int_t
        !           234: ngx_http_not_modified_filter_init(ngx_conf_t *cf)
        !           235: {
        !           236:     ngx_http_next_header_filter = ngx_http_top_header_filter;
        !           237:     ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
        !           238: 
        !           239:     return NGX_OK;
        !           240: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>