Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_addition_filter_module.c @ 5762:b522d5b137fd
SPDY: fix support for headers with multiple values.
Split SPDY header with multiple, NULL-separated values:
cookie: foo\0bar
into two separate HTTP headers with the same name:
cookie: foo
cookie: bar
Even though the logic for this behavior already existed
in the source code, it doesn't look that it ever worked
and SPDY streams with such headers were simply rejected.
Signed-off-by: Piotr Sikora <piotr@cloudflare.com>
author | Piotr Sikora <piotr@cloudflare.com> |
---|---|
date | Tue, 08 Jul 2014 02:17:44 -0700 |
parents | e491b26fa5a1 |
children | ebba2f980489 |
rev | line source |
---|---|
629 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
629 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
2167 | 14 ngx_str_t before_body; |
15 ngx_str_t after_body; | |
16 | |
17 ngx_hash_t types; | |
18 ngx_array_t *types_keys; | |
629 | 19 } ngx_http_addition_conf_t; |
20 | |
21 | |
22 typedef struct { | |
2167 | 23 ngx_uint_t before_body_sent; |
629 | 24 } ngx_http_addition_ctx_t; |
25 | |
26 | |
27 static void *ngx_http_addition_create_conf(ngx_conf_t *cf); | |
28 static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, | |
29 void *child); | |
681 | 30 static ngx_int_t ngx_http_addition_filter_init(ngx_conf_t *cf); |
629 | 31 |
32 | |
33 static ngx_command_t ngx_http_addition_commands[] = { | |
34 | |
35 { ngx_string("add_before_body"), | |
36 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
37 ngx_conf_set_str_slot, | |
38 NGX_HTTP_LOC_CONF_OFFSET, | |
39 offsetof(ngx_http_addition_conf_t, before_body), | |
40 NULL }, | |
41 | |
42 { ngx_string("add_after_body"), | |
43 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
44 ngx_conf_set_str_slot, | |
45 NGX_HTTP_LOC_CONF_OFFSET, | |
46 offsetof(ngx_http_addition_conf_t, after_body), | |
47 NULL }, | |
48 | |
3146
29ba1de1ab0b
fix typo in addition_types directive name
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
49 { ngx_string("addition_types"), |
2167 | 50 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
51 ngx_http_types_slot, | |
52 NGX_HTTP_LOC_CONF_OFFSET, | |
53 offsetof(ngx_http_addition_conf_t, types_keys), | |
54 &ngx_http_html_default_types[0] }, | |
55 | |
629 | 56 ngx_null_command |
57 }; | |
58 | |
59 | |
60 static ngx_http_module_t ngx_http_addition_filter_module_ctx = { | |
61 NULL, /* preconfiguration */ | |
681 | 62 ngx_http_addition_filter_init, /* postconfiguration */ |
629 | 63 |
64 NULL, /* create main configuration */ | |
65 NULL, /* init main configuration */ | |
66 | |
67 NULL, /* create server configuration */ | |
68 NULL, /* merge server configuration */ | |
69 | |
70 ngx_http_addition_create_conf, /* create location configuration */ | |
71 ngx_http_addition_merge_conf /* merge location configuration */ | |
72 }; | |
73 | |
74 | |
75 ngx_module_t ngx_http_addition_filter_module = { | |
76 NGX_MODULE_V1, | |
77 &ngx_http_addition_filter_module_ctx, /* module context */ | |
78 ngx_http_addition_commands, /* module directives */ | |
79 NGX_HTTP_MODULE, /* module type */ | |
80 NULL, /* init master */ | |
681 | 81 NULL, /* init module */ |
629 | 82 NULL, /* init process */ |
83 NULL, /* init thread */ | |
84 NULL, /* exit thread */ | |
85 NULL, /* exit process */ | |
86 NULL, /* exit master */ | |
87 NGX_MODULE_V1_PADDING | |
88 }; | |
89 | |
90 | |
91 static ngx_http_output_header_filter_pt ngx_http_next_header_filter; | |
92 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | |
93 | |
94 | |
95 static ngx_int_t | |
96 ngx_http_addition_header_filter(ngx_http_request_t *r) | |
97 { | |
98 ngx_http_addition_ctx_t *ctx; | |
99 ngx_http_addition_conf_t *conf; | |
100 | |
2167 | 101 if (r->headers_out.status != NGX_HTTP_OK || r != r->main) { |
629 | 102 return ngx_http_next_header_filter(r); |
103 } | |
104 | |
631 | 105 conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); |
106 | |
107 if (conf->before_body.len == 0 && conf->after_body.len == 0) { | |
108 return ngx_http_next_header_filter(r); | |
109 } | |
110 | |
2167 | 111 if (ngx_http_test_content_type(r, &conf->types) == NULL) { |
629 | 112 return ngx_http_next_header_filter(r); |
113 } | |
114 | |
115 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t)); | |
116 if (ctx == NULL) { | |
117 return NGX_ERROR; | |
118 } | |
119 | |
120 ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module); | |
121 | |
122 ngx_http_clear_content_length(r); | |
123 ngx_http_clear_accept_ranges(r); | |
5733
e491b26fa5a1
Entity tags: downgrade strong etags to weak ones as needed.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4746
diff
changeset
|
124 ngx_http_weak_etag(r); |
629 | 125 |
126 return ngx_http_next_header_filter(r); | |
127 } | |
128 | |
129 | |
130 static ngx_int_t | |
131 ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
132 { | |
133 ngx_int_t rc; | |
134 ngx_uint_t last; | |
135 ngx_chain_t *cl; | |
758
86bb73dc8d40
fix <!--#include virtual=... wait="yes" -->
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
136 ngx_http_request_t *sr; |
629 | 137 ngx_http_addition_ctx_t *ctx; |
138 ngx_http_addition_conf_t *conf; | |
139 | |
140 if (in == NULL || r->header_only) { | |
141 return ngx_http_next_body_filter(r, in); | |
142 } | |
143 | |
144 ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module); | |
145 | |
146 if (ctx == NULL) { | |
147 return ngx_http_next_body_filter(r, in); | |
148 } | |
149 | |
150 conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); | |
151 | |
152 if (!ctx->before_body_sent) { | |
153 ctx->before_body_sent = 1; | |
154 | |
155 if (conf->before_body.len) { | |
2377
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
156 if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
157 != NGX_OK) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
158 { |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
159 return NGX_ERROR; |
629 | 160 } |
161 } | |
162 } | |
163 | |
846
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
164 if (conf->after_body.len == 0) { |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
165 ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
166 return ngx_http_next_body_filter(r, in); |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
167 } |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
168 |
629 | 169 last = 0; |
170 | |
171 for (cl = in; cl; cl = cl->next) { | |
172 if (cl->buf->last_buf) { | |
173 cl->buf->last_buf = 0; | |
631 | 174 cl->buf->sync = 1; |
629 | 175 last = 1; |
176 } | |
177 } | |
178 | |
179 rc = ngx_http_next_body_filter(r, in); | |
180 | |
631 | 181 if (rc == NGX_ERROR || !last || conf->after_body.len == 0) { |
629 | 182 return rc; |
183 } | |
184 | |
2377
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
185 if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
186 != NGX_OK) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
187 { |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
188 return NGX_ERROR; |
629 | 189 } |
190 | |
631 | 191 ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); |
629 | 192 |
193 return ngx_http_send_special(r, NGX_HTTP_LAST); | |
194 } | |
195 | |
196 | |
197 static ngx_int_t | |
681 | 198 ngx_http_addition_filter_init(ngx_conf_t *cf) |
629 | 199 { |
200 ngx_http_next_header_filter = ngx_http_top_header_filter; | |
201 ngx_http_top_header_filter = ngx_http_addition_header_filter; | |
202 | |
203 ngx_http_next_body_filter = ngx_http_top_body_filter; | |
204 ngx_http_top_body_filter = ngx_http_addition_body_filter; | |
205 | |
206 return NGX_OK; | |
207 } | |
208 | |
209 | |
210 static void * | |
211 ngx_http_addition_create_conf(ngx_conf_t *cf) | |
212 { | |
213 ngx_http_addition_conf_t *conf; | |
214 | |
215 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t)); | |
216 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2377
diff
changeset
|
217 return NULL; |
629 | 218 } |
219 | |
220 /* | |
221 * set by ngx_pcalloc(): | |
222 * | |
2167 | 223 * conf->before_body = { 0, NULL }; |
224 * conf->after_body = { 0, NULL }; | |
225 * conf->types = { NULL }; | |
226 * conf->types_keys = NULL; | |
629 | 227 */ |
228 | |
229 return conf; | |
230 } | |
231 | |
232 | |
233 static char * | |
234 ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
235 { | |
236 ngx_http_addition_conf_t *prev = parent; | |
237 ngx_http_addition_conf_t *conf = child; | |
238 | |
239 ngx_conf_merge_str_value(conf->before_body, prev->before_body, ""); | |
240 ngx_conf_merge_str_value(conf->after_body, prev->after_body, ""); | |
241 | |
3372
6b8e5c882e47
support "*" in gzip_types, ssi_types, etc
Igor Sysoev <igor@sysoev.ru>
parents:
3146
diff
changeset
|
242 if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, |
6b8e5c882e47
support "*" in gzip_types, ssi_types, etc
Igor Sysoev <igor@sysoev.ru>
parents:
3146
diff
changeset
|
243 &prev->types_keys, &prev->types, |
2167 | 244 ngx_http_html_default_types) |
245 != NGX_OK) | |
246 { | |
247 return NGX_CONF_ERROR; | |
248 } | |
249 | |
629 | 250 return NGX_CONF_OK; |
251 } |