Skip to content

Commit 680ecee

Browse files
committed
implemented general response header caching and added new directives srcache_store_hide_header and srcache_store_pass_header to control which headers to cache and which not.
1 parent 6f9d155 commit 680ecee

10 files changed

+792
-415
lines changed

src/ngx_http_srcache_filter_module.c

Lines changed: 52 additions & 379 deletions
Large diffs are not rendered by default.

src/ngx_http_srcache_filter_module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ typedef struct {
4343
ngx_flag_t store_no_cache;
4444
ngx_flag_t ignore_content_encoding;
4545

46+
ngx_hash_t hide_headers_hash;
47+
ngx_array_t *hide_headers;
48+
ngx_array_t *pass_headers;
49+
50+
unsigned hide_content_type;
51+
4652
unsigned postponed_to_access_phase_end;
4753
} ngx_http_srcache_loc_conf_t;
4854

src/ngx_http_srcache_util.c

Lines changed: 169 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -143,108 +143,97 @@ ngx_http_srcache_parse_method_name(ngx_str_t **method_name_ptr)
143143
if (ngx_http_srcache_strcmp_const(method_name->data, "GET") == 0) {
144144
*method_name_ptr = &ngx_http_srcache_get_method;
145145
return NGX_HTTP_GET;
146-
break;
147146
}
148147

149148
if (ngx_http_srcache_strcmp_const(method_name->data, "PUT") == 0) {
150149
*method_name_ptr = &ngx_http_srcache_put_method;
151150
return NGX_HTTP_PUT;
152-
break;
153151
}
154152

155153
return NGX_HTTP_UNKNOWN;
156-
break;
157154

158155
case 4:
159156
if (ngx_http_srcache_strcmp_const(method_name->data, "POST") == 0) {
160157
*method_name_ptr = &ngx_http_srcache_post_method;
161158
return NGX_HTTP_POST;
162-
break;
163159
}
160+
164161
if (ngx_http_srcache_strcmp_const(method_name->data, "HEAD") == 0) {
165162
*method_name_ptr = &ngx_http_srcache_head_method;
166163
return NGX_HTTP_HEAD;
167-
break;
168164
}
165+
169166
if (ngx_http_srcache_strcmp_const(method_name->data, "COPY") == 0) {
170167
*method_name_ptr = &ngx_http_srcache_copy_method;
171168
return NGX_HTTP_COPY;
172-
break;
173169
}
170+
174171
if (ngx_http_srcache_strcmp_const(method_name->data, "MOVE") == 0) {
175172
*method_name_ptr = &ngx_http_srcache_move_method;
176173
return NGX_HTTP_MOVE;
177-
break;
178174
}
175+
179176
if (ngx_http_srcache_strcmp_const(method_name->data, "LOCK") == 0) {
180177
*method_name_ptr = &ngx_http_srcache_lock_method;
181178
return NGX_HTTP_LOCK;
182-
break;
183179
}
180+
184181
return NGX_HTTP_UNKNOWN;
185-
break;
186182

187183
case 5:
188184
if (ngx_http_srcache_strcmp_const(method_name->data, "MKCOL") == 0) {
189185
*method_name_ptr = &ngx_http_srcache_mkcol_method;
190186
return NGX_HTTP_MKCOL;
191-
break;
192187
}
188+
193189
if (ngx_http_srcache_strcmp_const(method_name->data, "TRACE") == 0) {
194190
*method_name_ptr = &ngx_http_srcache_trace_method;
195191
return NGX_HTTP_TRACE;
196-
break;
197192
}
193+
198194
return NGX_HTTP_UNKNOWN;
199-
break;
200195

201196
case 6:
202197
if (ngx_http_srcache_strcmp_const(method_name->data, "DELETE") == 0) {
203198
*method_name_ptr = &ngx_http_srcache_delete_method;
204199
return NGX_HTTP_DELETE;
205-
break;
206200
}
207201

208202
if (ngx_http_srcache_strcmp_const(method_name->data, "UNLOCK") == 0) {
209203
*method_name_ptr = &ngx_http_srcache_unlock_method;
210204
return NGX_HTTP_UNLOCK;
211-
break;
212205
}
206+
213207
return NGX_HTTP_UNKNOWN;
214-
break;
215208

216209
case 7:
217210
if (ngx_http_srcache_strcmp_const(method_name->data, "OPTIONS") == 0) {
218211
*method_name_ptr = &ngx_http_srcache_options_method;
219212
return NGX_HTTP_OPTIONS;
220-
break;
221213
}
214+
222215
return NGX_HTTP_UNKNOWN;
223-
break;
224216

225217
case 8:
226218
if (ngx_http_srcache_strcmp_const(method_name->data, "PROPFIND") == 0) {
227219
*method_name_ptr = &ngx_http_srcache_propfind_method;
228220
return NGX_HTTP_PROPFIND;
229-
break;
230221
}
222+
231223
return NGX_HTTP_UNKNOWN;
232-
break;
233224

234225
case 9:
235226
if (ngx_http_srcache_strcmp_const(method_name->data, "PROPPATCH")
236227
== 0)
237228
{
238229
*method_name_ptr = &ngx_http_srcache_proppatch_method;
239230
return NGX_HTTP_PROPPATCH;
240-
break;
241231
}
232+
242233
return NGX_HTTP_UNKNOWN;
243-
break;
244234

245235
default:
246236
return NGX_HTTP_UNKNOWN;
247-
break;
248237
}
249238

250239
return NGX_HTTP_UNKNOWN;
@@ -653,7 +642,9 @@ ngx_http_srcache_process_header(ngx_http_request_t *r, ngx_buf_t *b)
653642
truncate = 0;
654643
}
655644

656-
ctx->header_buf->last = ngx_copy(ctx->header_buf->last, b->pos, (size_t) len);
645+
ctx->header_buf->last = ngx_copy(ctx->header_buf->last, b->pos,
646+
(size_t) len);
647+
657648
p = ctx->header_buf->pos;
658649

659650
rc = ngx_http_parse_header_line(r, ctx->header_buf, 1);
@@ -761,6 +752,10 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
761752
ngx_list_part_t *part;
762753
ngx_table_elt_t *header;
763754

755+
ngx_http_srcache_loc_conf_t *conf;
756+
757+
conf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module);
758+
764759
dd("request: %p, uri: %.*s", r, (int) r->uri.len, r->uri.data);
765760

766761
len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1
@@ -793,7 +788,7 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
793788
}
794789
}
795790

796-
if (r->headers_out.content_type.len) {
791+
if (!conf->hide_content_type && r->headers_out.content_type.len) {
797792
len += sizeof("Content-Type: ") - 1
798793
+ r->headers_out.content_type.len + 2;
799794

@@ -823,10 +818,8 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
823818
continue;
824819
}
825820

826-
/* XXX we should really store other headers too */
827-
if (header[i].key.len != sizeof("Content-Type") - 1
828-
|| ngx_strncasecmp(header[i].key.data, (u_char *) "Content-Type",
829-
sizeof("Content-Type") - 1) != 0)
821+
if (ngx_hash_find(&conf->hide_headers_hash, header[i].hash,
822+
header[i].lowcase_key, header[i].key.len))
830823
{
831824
continue;
832825
}
@@ -852,7 +845,7 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
852845
}
853846
*b->last++ = CR; *b->last++ = LF;
854847

855-
if (r->headers_out.content_type.len) {
848+
if (!conf->hide_content_type && r->headers_out.content_type.len) {
856849
b->last = ngx_cpymem(b->last, "Content-Type: ",
857850
sizeof("Content-Type: ") - 1);
858851
b->last = ngx_copy(b->last, r->headers_out.content_type.data,
@@ -889,14 +882,23 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
889882
continue;
890883
}
891884

892-
/* XXX we should really store other headers too */
893-
if (header[i].key.len != sizeof("Content-Type") - 1
894-
|| ngx_strncasecmp(header[i].key.data, (u_char *) "Content-Type",
895-
sizeof("Content-Type") - 1) != 0)
885+
dd("header lowcase key: %s", header[i].lowcase_key);
886+
887+
dd("header key: %.*s", (int) header[i].key.len, header[i].key.data);
888+
889+
dd("header hash: %lu, hash lc: %lu", (unsigned long) header[i].hash,
890+
(unsigned long) ngx_hash_key_lc(header[i].key.data, header[i].key.len));
891+
892+
if (ngx_hash_find(&conf->hide_headers_hash, header[i].hash,
893+
header[i].lowcase_key, header[i].key.len))
896894
{
895+
dd("skipped header key: %.*s", (int) header[i].key.len,
896+
header[i].key.data);
897897
continue;
898898
}
899899

900+
dd("header not skipped");
901+
900902
b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
901903
*b->last++ = ':'; *b->last++ = ' ';
902904

@@ -905,15 +907,16 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
905907
}
906908

907909
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
908-
"%*s", (size_t) (b->last - b->pos), b->pos);
910+
"srcache store header %*s", (size_t) (b->last - b->pos),
911+
b->pos);
909912

910913
/* the end of HTTP header */
911914
*b->last++ = CR; *b->last++ = LF;
912915

913916
if (b->last != b->end) {
914917
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
915918
"srcache_fetch: buffer error when serializing the "
916-
"response header");
919+
"response header: %O left", (off_t) (b->last - b->end));
917920

918921
return NGX_ERROR;
919922
}
@@ -933,3 +936,134 @@ ngx_http_srcache_store_response_header(ngx_http_request_t *r,
933936
return NGX_OK;
934937
}
935938

939+
940+
ngx_int_t
941+
ngx_http_srcache_hide_headers_hash(ngx_conf_t *cf,
942+
ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_loc_conf_t *prev,
943+
ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
944+
{
945+
ngx_str_t *h;
946+
ngx_uint_t i, j;
947+
ngx_array_t hide_headers;
948+
ngx_hash_key_t *hk;
949+
950+
if (conf->hide_headers == NGX_CONF_UNSET_PTR
951+
&& conf->pass_headers == NGX_CONF_UNSET_PTR)
952+
{
953+
conf->hide_headers_hash = prev->hide_headers_hash;
954+
955+
if (conf->hide_headers_hash.buckets)
956+
{
957+
return NGX_OK;
958+
}
959+
960+
conf->hide_headers = prev->hide_headers;
961+
conf->pass_headers = prev->pass_headers;
962+
conf->hide_content_type = prev->hide_content_type;
963+
964+
} else {
965+
if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
966+
conf->hide_headers = prev->hide_headers;
967+
}
968+
969+
if (conf->pass_headers == NGX_CONF_UNSET_PTR) {
970+
conf->pass_headers = prev->pass_headers;
971+
}
972+
}
973+
974+
dd("init hide headers");
975+
976+
if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
977+
!= NGX_OK)
978+
{
979+
return NGX_ERROR;
980+
}
981+
982+
for (h = default_hide_headers; h->len; h++) {
983+
hk = ngx_array_push(&hide_headers);
984+
if (hk == NULL) {
985+
return NGX_ERROR;
986+
}
987+
988+
hk->key = *h;
989+
hk->key_hash = ngx_hash_key_lc(h->data, h->len);
990+
hk->value = (void *) 1;
991+
}
992+
993+
if (conf->hide_headers != NGX_CONF_UNSET_PTR) {
994+
dd("hide headers not empty");
995+
996+
h = conf->hide_headers->elts;
997+
998+
for (i = 0; i < conf->hide_headers->nelts; i++) {
999+
1000+
hk = hide_headers.elts;
1001+
1002+
for (j = 0; j < hide_headers.nelts; j++) {
1003+
if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
1004+
goto exist;
1005+
}
1006+
}
1007+
1008+
hk = ngx_array_push(&hide_headers);
1009+
if (hk == NULL) {
1010+
return NGX_ERROR;
1011+
}
1012+
1013+
hk->key = h[i];
1014+
hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
1015+
hk->value = (void *) 1;
1016+
1017+
if (h[i].len == sizeof("Content-Type") - 1
1018+
&& ngx_strncasecmp(h[i].data, (u_char *) "Content-Type",
1019+
sizeof("Content-Type") - 1)
1020+
== 0)
1021+
{
1022+
conf->hide_content_type = 1;
1023+
}
1024+
1025+
dd("adding header to hide headers: %.*s", (int) h[i].len,
1026+
h[i].data);
1027+
1028+
exist:
1029+
1030+
continue;
1031+
}
1032+
}
1033+
1034+
if (conf->pass_headers != NGX_CONF_UNSET_PTR) {
1035+
1036+
h = conf->pass_headers->elts;
1037+
hk = hide_headers.elts;
1038+
1039+
for (i = 0; i < conf->pass_headers->nelts; i++) {
1040+
for (j = 0; j < hide_headers.nelts; j++) {
1041+
1042+
if (hk[j].key.data == NULL) {
1043+
continue;
1044+
}
1045+
1046+
if (h[i].len == sizeof("Content-Type") - 1
1047+
&& ngx_strncasecmp(h[i].data, (u_char *) "Content-Type",
1048+
sizeof("Content-Type") - 1)
1049+
== 0)
1050+
{
1051+
conf->hide_content_type = 0;
1052+
}
1053+
1054+
if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
1055+
hk[j].key.data = NULL;
1056+
break;
1057+
}
1058+
}
1059+
}
1060+
}
1061+
1062+
hash->hash = &conf->hide_headers_hash;
1063+
hash->key = ngx_hash_key_lc;
1064+
hash->pool = cf->pool;
1065+
hash->temp_pool = NULL;
1066+
1067+
return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
1068+
}
1069+

src/ngx_http_srcache_util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ ngx_int_t ngx_http_srcache_process_header(ngx_http_request_t *r,
4444
ngx_buf_t *b);
4545
ngx_int_t ngx_http_srcache_store_response_header(ngx_http_request_t *r,
4646
ngx_http_srcache_ctx_t *ctx);
47+
ngx_int_t ngx_http_srcache_hide_headers_hash(ngx_conf_t *cf,
48+
ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_loc_conf_t *prev,
49+
ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
4750

4851

4952
#endif /* NGX_HTTP_SRCACHE_UTIL_H */

t/disk.t

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use Test::Nginx::Socket;
55

66
#repeat_each(100);
77

8-
plan tests => repeat_each() * 2 * blocks();
8+
plan tests => repeat_each() * (2 * blocks() + 1);
99

1010
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
1111

@@ -43,6 +43,8 @@ GET /flush
4343
}
4444
--- request
4545
GET /index.html
46+
--- response_headers
47+
Accept-Ranges: bytes
4648
--- response_body_like: It works!
4749
4850

0 commit comments

Comments
 (0)