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>