Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
0014 static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
0015 static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
0016     ngx_table_elt_t *header, ngx_uint_t weak);
0017 static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
0018 
0019 
0020 static ngx_http_module_t  ngx_http_not_modified_filter_module_ctx = {
0021     NULL,                                  /* preconfiguration */
0022     ngx_http_not_modified_filter_init,     /* postconfiguration */
0023 
0024     NULL,                                  /* create main configuration */
0025     NULL,                                  /* init main configuration */
0026 
0027     NULL,                                  /* create server configuration */
0028     NULL,                                  /* merge server configuration */
0029 
0030     NULL,                                  /* create location configuration */
0031     NULL                                   /* merge location configuration */
0032 };
0033 
0034 
0035 ngx_module_t  ngx_http_not_modified_filter_module = {
0036     NGX_MODULE_V1,
0037     &ngx_http_not_modified_filter_module_ctx, /* module context */
0038     NULL,                                  /* module directives */
0039     NGX_HTTP_MODULE,                       /* module type */
0040     NULL,                                  /* init master */
0041     NULL,                                  /* init module */
0042     NULL,                                  /* init process */
0043     NULL,                                  /* init thread */
0044     NULL,                                  /* exit thread */
0045     NULL,                                  /* exit process */
0046     NULL,                                  /* exit master */
0047     NGX_MODULE_V1_PADDING
0048 };
0049 
0050 
0051 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
0052 
0053 
0054 static ngx_int_t
0055 ngx_http_not_modified_header_filter(ngx_http_request_t *r)
0056 {
0057     if (r->headers_out.status != NGX_HTTP_OK
0058         || r != r->main
0059         || r->disable_not_modified)
0060     {
0061         return ngx_http_next_header_filter(r);
0062     }
0063 
0064     if (r->headers_in.if_unmodified_since
0065         && !ngx_http_test_if_unmodified(r))
0066     {
0067         return ngx_http_filter_finalize_request(r, NULL,
0068                                                 NGX_HTTP_PRECONDITION_FAILED);
0069     }
0070 
0071     if (r->headers_in.if_match
0072         && !ngx_http_test_if_match(r, r->headers_in.if_match, 0))
0073     {
0074         return ngx_http_filter_finalize_request(r, NULL,
0075                                                 NGX_HTTP_PRECONDITION_FAILED);
0076     }
0077 
0078     if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
0079 
0080         if (r->headers_in.if_modified_since
0081             && ngx_http_test_if_modified(r))
0082         {
0083             return ngx_http_next_header_filter(r);
0084         }
0085 
0086         if (r->headers_in.if_none_match
0087             && !ngx_http_test_if_match(r, r->headers_in.if_none_match, 1))
0088         {
0089             return ngx_http_next_header_filter(r);
0090         }
0091 
0092         /* not modified */
0093 
0094         r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
0095         r->headers_out.status_line.len = 0;
0096         r->headers_out.content_type.len = 0;
0097         ngx_http_clear_content_length(r);
0098         ngx_http_clear_accept_ranges(r);
0099 
0100         if (r->headers_out.content_encoding) {
0101             r->headers_out.content_encoding->hash = 0;
0102             r->headers_out.content_encoding = NULL;
0103         }
0104 
0105         return ngx_http_next_header_filter(r);
0106     }
0107 
0108     return ngx_http_next_header_filter(r);
0109 }
0110 
0111 
0112 static ngx_uint_t
0113 ngx_http_test_if_unmodified(ngx_http_request_t *r)
0114 {
0115     time_t  iums;
0116 
0117     if (r->headers_out.last_modified_time == (time_t) -1) {
0118         return 0;
0119     }
0120 
0121     iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data,
0122                                r->headers_in.if_unmodified_since->value.len);
0123 
0124     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
0125                  "http iums:%T lm:%T", iums, r->headers_out.last_modified_time);
0126 
0127     if (iums >= r->headers_out.last_modified_time) {
0128         return 1;
0129     }
0130 
0131     return 0;
0132 }
0133 
0134 
0135 static ngx_uint_t
0136 ngx_http_test_if_modified(ngx_http_request_t *r)
0137 {
0138     time_t                     ims;
0139     ngx_http_core_loc_conf_t  *clcf;
0140 
0141     if (r->headers_out.last_modified_time == (time_t) -1) {
0142         return 1;
0143     }
0144 
0145     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0146 
0147     if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
0148         return 1;
0149     }
0150 
0151     ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data,
0152                               r->headers_in.if_modified_since->value.len);
0153 
0154     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
0155                    "http ims:%T lm:%T", ims, r->headers_out.last_modified_time);
0156 
0157     if (ims == r->headers_out.last_modified_time) {
0158         return 0;
0159     }
0160 
0161     if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
0162         || ims < r->headers_out.last_modified_time)
0163     {
0164         return 1;
0165     }
0166 
0167     return 0;
0168 }
0169 
0170 
0171 static ngx_uint_t
0172 ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header,
0173     ngx_uint_t weak)
0174 {
0175     u_char     *start, *end, ch;
0176     ngx_str_t   etag, *list;
0177 
0178     list = &header->value;
0179 
0180     if (list->len == 1 && list->data[0] == '*') {
0181         return 1;
0182     }
0183 
0184     if (r->headers_out.etag == NULL) {
0185         return 0;
0186     }
0187 
0188     etag = r->headers_out.etag->value;
0189 
0190     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
0191                    "http im:\"%V\" etag:%V", list, &etag);
0192 
0193     if (weak
0194         && etag.len > 2
0195         && etag.data[0] == 'W'
0196         && etag.data[1] == '/')
0197     {
0198         etag.len -= 2;
0199         etag.data += 2;
0200     }
0201 
0202     start = list->data;
0203     end = list->data + list->len;
0204 
0205     while (start < end) {
0206 
0207         if (weak
0208             && end - start > 2
0209             && start[0] == 'W'
0210             && start[1] == '/')
0211         {
0212             start += 2;
0213         }
0214 
0215         if (etag.len > (size_t) (end - start)) {
0216             return 0;
0217         }
0218 
0219         if (ngx_strncmp(start, etag.data, etag.len) != 0) {
0220             goto skip;
0221         }
0222 
0223         start += etag.len;
0224 
0225         while (start < end) {
0226             ch = *start;
0227 
0228             if (ch == ' ' || ch == '\t') {
0229                 start++;
0230                 continue;
0231             }
0232 
0233             break;
0234         }
0235 
0236         if (start == end || *start == ',') {
0237             return 1;
0238         }
0239 
0240     skip:
0241 
0242         while (start < end && *start != ',') { start++; }
0243         while (start < end) {
0244             ch = *start;
0245 
0246             if (ch == ' ' || ch == '\t' || ch == ',') {
0247                 start++;
0248                 continue;
0249             }
0250 
0251             break;
0252         }
0253     }
0254 
0255     return 0;
0256 }
0257 
0258 
0259 static ngx_int_t
0260 ngx_http_not_modified_filter_init(ngx_conf_t *cf)
0261 {
0262     ngx_http_next_header_filter = ngx_http_top_header_filter;
0263     ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
0264 
0265     return NGX_OK;
0266 }