Annotation of embedaddon/nginx/src/http/modules/ngx_http_not_modified_filter_module.c, revision 1.1.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>