| | varnish-cache/bin/varnishd/cache/cache_vrt_filter.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2006 Verdens Gang AS |
2 |
|
* Copyright (c) 2006-2016 Varnish Software AS |
3 |
|
* All rights reserved. |
4 |
|
* |
5 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
6 |
|
* |
7 |
|
* SPDX-License-Identifier: BSD-2-Clause |
8 |
|
* |
9 |
|
* Redistribution and use in source and binary forms, with or without |
10 |
|
* modification, are permitted provided that the following conditions |
11 |
|
* are met: |
12 |
|
* 1. Redistributions of source code must retain the above copyright |
13 |
|
* notice, this list of conditions and the following disclaimer. |
14 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
15 |
|
* notice, this list of conditions and the following disclaimer in the |
16 |
|
* documentation and/or other materials provided with the distribution. |
17 |
|
* |
18 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
19 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
22 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 |
|
* SUCH DAMAGE. |
29 |
|
* |
30 |
|
*/ |
31 |
|
|
32 |
|
#include "config.h" |
33 |
|
|
34 |
|
#include <stdio.h> |
35 |
|
#include <stdint.h> |
36 |
|
#include <stdlib.h> |
37 |
|
|
38 |
|
#include "cache_varnishd.h" |
39 |
|
#include "cache_vcl.h" |
40 |
|
#include "vrt_obj.h" |
41 |
|
|
42 |
|
#include "vct.h" |
43 |
|
|
44 |
|
#include "cache_filter.h" |
45 |
|
|
46 |
|
/*-------------------------------------------------------------------- |
47 |
|
*/ |
48 |
|
|
49 |
|
struct vfilter { |
50 |
|
unsigned magic; |
51 |
|
#define VFILTER_MAGIC 0xd40894e9 |
52 |
|
const struct vfp *vfp; |
53 |
|
const struct vdp *vdp; |
54 |
|
const char *name; |
55 |
|
int nlen; |
56 |
|
VTAILQ_ENTRY(vfilter) list; |
57 |
|
}; |
58 |
|
|
59 |
|
static struct vfilter_head vrt_filters = |
60 |
|
VTAILQ_HEAD_INITIALIZER(vrt_filters); |
61 |
|
|
62 |
|
static const char * |
63 |
350800 |
is_dup_filter(const struct vfilter_head *head, const struct vfp * vfp, |
64 |
|
const struct vdp *vdp, const char *name) |
65 |
|
{ |
66 |
|
struct vfilter *vp; |
67 |
1694000 |
VTAILQ_FOREACH(vp, head, list) { |
68 |
1343240 |
if (vfp != NULL && vp->vfp != NULL) { |
69 |
411860 |
if (vp->vfp == vfp) |
70 |
40 |
return ("VFP already registered"); |
71 |
411820 |
if (!strcasecmp(vp->name, name)) |
72 |
0 |
return ("VFP name already used"); |
73 |
411820 |
} |
74 |
1343200 |
if (vdp != NULL && vp->vdp != NULL) { |
75 |
283050 |
if (vp->vdp == vdp) |
76 |
0 |
return ("VDP already registered"); |
77 |
283050 |
if (!strcasecmp(vp->name, name)) |
78 |
0 |
return ("VDP name already used"); |
79 |
283050 |
} |
80 |
1343200 |
} |
81 |
350760 |
return (NULL); |
82 |
350800 |
} |
83 |
|
|
84 |
|
static const char * |
85 |
321920 |
vrt_addfilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp) |
86 |
|
{ |
87 |
|
struct vfilter *vp; |
88 |
321920 |
struct vfilter_head *hd = &vrt_filters; |
89 |
321920 |
const char *err, *name = NULL; |
90 |
|
|
91 |
321920 |
CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); |
92 |
321920 |
assert(vfp != NULL || vdp != NULL); |
93 |
321920 |
assert(vfp == NULL || vfp->name != NULL); |
94 |
321920 |
assert(vdp == NULL || vdp->name != NULL); |
95 |
321920 |
assert(vfp == NULL || vdp == NULL || !strcasecmp(vfp->name, vdp->name)); |
96 |
321920 |
if (vfp != NULL) |
97 |
191430 |
name = vfp->name; |
98 |
130490 |
else if (vdp != NULL) |
99 |
130490 |
name = vdp->name; |
100 |
321920 |
AN(name); |
101 |
|
|
102 |
321920 |
err = is_dup_filter(hd, vfp, vdp, name); |
103 |
321920 |
if (err != NULL) { |
104 |
0 |
if (ctx != NULL) |
105 |
0 |
VRT_fail(ctx, "%s: %s (global)", name, err); |
106 |
0 |
return (err); |
107 |
|
} |
108 |
321920 |
if (ctx != NULL) { |
109 |
28880 |
ASSERT_CLI(); |
110 |
28880 |
CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC); |
111 |
28880 |
hd = &ctx->vcl->filters; |
112 |
28880 |
err = is_dup_filter(hd, vfp, vdp, name); |
113 |
28880 |
if (err != NULL) { |
114 |
40 |
VRT_fail(ctx, "%s: %s (per-vcl)", name, err); |
115 |
40 |
return (err); |
116 |
|
} |
117 |
28840 |
} |
118 |
|
|
119 |
321880 |
ALLOC_OBJ(vp, VFILTER_MAGIC); |
120 |
321880 |
AN(vp); |
121 |
321880 |
vp->vfp = vfp; |
122 |
321880 |
vp->vdp = vdp; |
123 |
321880 |
vp->name = name; |
124 |
321880 |
vp->nlen = strlen(name); |
125 |
321880 |
VTAILQ_INSERT_TAIL(hd, vp, list); |
126 |
321880 |
return (err); |
127 |
321920 |
} |
128 |
|
|
129 |
|
const char * |
130 |
28880 |
VRT_AddFilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp) |
131 |
|
{ |
132 |
|
|
133 |
28880 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
134 |
28880 |
return (vrt_addfilter(ctx, vfp, vdp)); |
135 |
|
} |
136 |
|
|
137 |
|
void |
138 |
0 |
VRT_AddVFP(VRT_CTX, const struct vfp *filter) |
139 |
|
{ |
140 |
0 |
AZ(VRT_AddFilter(ctx, filter, NULL)); |
141 |
0 |
} |
142 |
|
|
143 |
|
void |
144 |
0 |
VRT_AddVDP(VRT_CTX, const struct vdp *filter) |
145 |
|
{ |
146 |
0 |
AZ(VRT_AddFilter(ctx, NULL, filter)); |
147 |
0 |
} |
148 |
|
|
149 |
|
void |
150 |
6440 |
VRT_RemoveFilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp) |
151 |
|
{ |
152 |
|
struct vfilter *vp; |
153 |
|
struct vfilter_head *hd; |
154 |
|
|
155 |
6440 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
156 |
6440 |
CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC); |
157 |
6440 |
hd = &ctx->vcl->filters; |
158 |
6440 |
assert(vfp != NULL || vdp != NULL); |
159 |
6440 |
assert(vfp == NULL || vfp->name != NULL); |
160 |
6440 |
assert(vdp == NULL || vdp->name != NULL); |
161 |
6440 |
assert(vfp == NULL || vdp == NULL || !strcasecmp(vfp->name, vdp->name)); |
162 |
|
|
163 |
6440 |
ASSERT_CLI(); |
164 |
9200 |
VTAILQ_FOREACH(vp, hd, list) { |
165 |
9200 |
CHECK_OBJ_NOTNULL(vp, VFILTER_MAGIC); |
166 |
9200 |
if (vp->vfp == vfp && vp->vdp == vdp) |
167 |
6440 |
break; |
168 |
2760 |
} |
169 |
6440 |
AN(vp); |
170 |
6440 |
assert(vfp == NULL || !strcasecmp(vfp->name, vp->name)); |
171 |
6440 |
assert(vdp == NULL || !strcasecmp(vdp->name, vp->name)); |
172 |
6440 |
VTAILQ_REMOVE(hd, vp, list); |
173 |
6440 |
FREE_OBJ(vp); |
174 |
6440 |
} |
175 |
|
|
176 |
|
void |
177 |
0 |
VRT_RemoveVFP(VRT_CTX, const struct vfp *filter) |
178 |
|
{ |
179 |
|
|
180 |
0 |
VRT_RemoveFilter(ctx, filter, NULL); |
181 |
0 |
} |
182 |
|
|
183 |
|
void |
184 |
0 |
VRT_RemoveVDP(VRT_CTX, const struct vdp *filter) |
185 |
|
{ |
186 |
|
|
187 |
0 |
VRT_RemoveFilter(ctx, NULL, filter); |
188 |
0 |
} |
189 |
|
|
190 |
|
static const struct vfilter vfilter_error[1] = {{0}}; |
191 |
|
|
192 |
|
// XXX: idea(fgs): Allow filters (...) arguments in the list |
193 |
|
static const struct vfilter * |
194 |
256361 |
vcl_filter_list_iter(int want_vfp, const struct vfilter_head *h1, |
195 |
|
const struct vfilter_head *h2, const char **flp) |
196 |
|
{ |
197 |
|
const char *fl, *q; |
198 |
|
const struct vfilter *vp; |
199 |
|
|
200 |
256361 |
AN(h1); |
201 |
256361 |
AN(h2); |
202 |
256361 |
AN(flp); |
203 |
|
|
204 |
256361 |
fl = *flp; |
205 |
256361 |
AN(fl); |
206 |
|
|
207 |
299720 |
while (vct_isspace(*fl)) |
208 |
43359 |
fl++; |
209 |
256361 |
if (*fl == '\0') { |
210 |
212042 |
*flp = NULL; |
211 |
212042 |
return (NULL); |
212 |
|
} |
213 |
363555 |
for (q = fl; *q && !vct_isspace(*q); q++) |
214 |
319236 |
continue; |
215 |
44319 |
*flp = q; |
216 |
259350 |
VTAILQ_FOREACH(vp, h1, list) { |
217 |
247671 |
if (want_vfp && vp->vfp == NULL) |
218 |
1560 |
continue; |
219 |
246111 |
else if (!want_vfp && vp->vdp == NULL) |
220 |
123392 |
continue; |
221 |
122719 |
if (vp->nlen == q - fl && !memcmp(fl, vp->name, vp->nlen)) |
222 |
32640 |
return (vp); |
223 |
90079 |
} |
224 |
24519 |
VTAILQ_FOREACH(vp, h2, list) { |
225 |
24399 |
if (want_vfp && vp->vfp == NULL) |
226 |
400 |
continue; |
227 |
23999 |
else if (!want_vfp && vp->vdp == NULL) |
228 |
0 |
continue; |
229 |
23999 |
if (vp->nlen == q - fl && !memcmp(fl, vp->name, vp->nlen)) |
230 |
11559 |
return (vp); |
231 |
12440 |
} |
232 |
120 |
*flp = fl; |
233 |
120 |
return (vfilter_error); |
234 |
256361 |
} |
235 |
|
|
236 |
|
int |
237 |
75478 |
VCL_StackVFP(struct vfp_ctx *vc, const struct vcl *vcl, const char *fl) |
238 |
|
{ |
239 |
|
const struct vfilter *vp; |
240 |
|
|
241 |
75478 |
AN(fl); |
242 |
75478 |
VSLbs(vc->wrk->vsl, SLT_Filters, TOSTRAND(fl)); |
243 |
|
|
244 |
94158 |
while (1) { |
245 |
94158 |
vp = vcl_filter_list_iter(1, &vrt_filters, &vcl->filters, &fl); |
246 |
94158 |
if (vp == NULL) |
247 |
74518 |
return (0); |
248 |
19640 |
if (vp == vfilter_error) |
249 |
80 |
return (VFP_Error(vc, "Filter '...%s' not found", fl)); |
250 |
19560 |
if (VFP_Push(vc, vp->vfp) == NULL) |
251 |
880 |
return (-1); |
252 |
|
} |
253 |
75478 |
} |
254 |
|
|
255 |
|
int |
256 |
140045 |
VCL_StackVDP(struct vdp_ctx *vdc, const struct vcl *vcl, const char *fl, |
257 |
|
struct req *req, struct busyobj *bo) |
258 |
|
{ |
259 |
|
const struct vfilter *vp; |
260 |
|
struct vrt_ctx ctx[1]; |
261 |
|
|
262 |
140045 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
263 |
140045 |
AN(vcl); |
264 |
140045 |
AN(fl); |
265 |
|
|
266 |
140045 |
CHECK_OBJ_ORNULL(req, REQ_MAGIC); |
267 |
140045 |
CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC); |
268 |
|
|
269 |
140045 |
assert((req ? 1 : 0) ^ (bo ? 1 : 0)); |
270 |
|
|
271 |
140045 |
VSLbs(vdc->vsl, SLT_Filters, TOSTRAND(fl)); |
272 |
140045 |
INIT_OBJ(ctx, VRT_CTX_MAGIC); |
273 |
|
|
274 |
140045 |
if (req) |
275 |
139765 |
VCL_Req2Ctx(ctx, req); |
276 |
|
else |
277 |
280 |
VCL_Bo2Ctx(ctx, bo); |
278 |
|
|
279 |
162205 |
while (1) { |
280 |
162205 |
vp = vcl_filter_list_iter(0, &vrt_filters, &vcl->filters, &fl); |
281 |
162205 |
if (vp == NULL) |
282 |
137525 |
return (0); |
283 |
24680 |
if (vp == vfilter_error) { |
284 |
80 |
VSLb(ctx->vsl, SLT_Error, |
285 |
40 |
"Filter '...%s' not found", fl); |
286 |
40 |
return (-1); |
287 |
|
} |
288 |
24640 |
if (VDP_Push(ctx, vdc, ctx->ws, vp->vdp, NULL)) |
289 |
2480 |
return (-1); |
290 |
|
} |
291 |
140045 |
} |
292 |
|
|
293 |
|
void |
294 |
36630 |
VCL_VRT_Init(void) |
295 |
|
{ |
296 |
36630 |
AZ(vrt_addfilter(NULL, &VFP_testgunzip, NULL)); |
297 |
36630 |
AZ(vrt_addfilter(NULL, &VFP_gunzip, NULL)); |
298 |
36630 |
AZ(vrt_addfilter(NULL, &VFP_gzip, NULL)); |
299 |
36630 |
AZ(vrt_addfilter(NULL, &VFP_esi, NULL)); |
300 |
36630 |
AZ(vrt_addfilter(NULL, &VFP_esi_gzip, NULL)); |
301 |
36630 |
AZ(vrt_addfilter(NULL, NULL, &VDP_esi)); |
302 |
36630 |
AZ(vrt_addfilter(NULL, NULL, &VDP_gunzip)); |
303 |
36630 |
AZ(vrt_addfilter(NULL, NULL, &VDP_range)); |
304 |
36630 |
} |
305 |
|
|
306 |
|
/*-------------------------------------------------------------------- |
307 |
|
*/ |
308 |
|
|
309 |
|
typedef void filter_list_t(void *, struct vsb *vsb); |
310 |
|
|
311 |
|
static const char * |
312 |
188563 |
filter_on_ws(struct ws *ws, filter_list_t *func, void *arg) |
313 |
|
{ |
314 |
|
struct vsb vsb[1]; |
315 |
|
const char *p; |
316 |
|
|
317 |
188563 |
AN(func); |
318 |
188563 |
AN(arg); |
319 |
188563 |
WS_VSB_new(vsb, ws); |
320 |
188563 |
func(arg, vsb); |
321 |
188563 |
p = WS_VSB_finish(vsb, ws, NULL); |
322 |
188563 |
if (p == NULL) |
323 |
920 |
p = ""; |
324 |
188563 |
return (p); |
325 |
|
} |
326 |
|
|
327 |
|
/*-------------------------------------------------------------------- |
328 |
|
*/ |
329 |
|
|
330 |
|
static void v_matchproto_(filter_list_t) |
331 |
47399 |
vbf_default_filter_list(void *arg, struct vsb *vsb) |
332 |
|
{ |
333 |
|
const struct busyobj *bo; |
334 |
|
const char *p; |
335 |
47399 |
int do_gzip, do_gunzip, is_gzip = 0, is_gunzip = 0; |
336 |
|
|
337 |
47399 |
CAST_OBJ_NOTNULL(bo, arg, BUSYOBJ_MAGIC); |
338 |
|
|
339 |
47399 |
do_gzip = bo->do_gzip; |
340 |
47399 |
do_gunzip = bo->do_gunzip; |
341 |
|
|
342 |
|
/* |
343 |
|
* The VCL variables beresp.do_g[un]zip tells us how we want the |
344 |
|
* object processed before it is stored. |
345 |
|
* |
346 |
|
* The backend Content-Encoding header tells us what we are going |
347 |
|
* to receive, which we classify in the following three classes: |
348 |
|
* |
349 |
|
* "Content-Encoding: gzip" --> object is gzipped. |
350 |
|
* no Content-Encoding --> object is not gzipped. |
351 |
|
* anything else --> do nothing wrt gzip |
352 |
|
*/ |
353 |
|
|
354 |
|
/* No body -> done */ |
355 |
47399 |
if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0) |
356 |
2 |
return; |
357 |
|
|
358 |
47399 |
if (!cache_param->http_gzip_support) |
359 |
160 |
do_gzip = do_gunzip = 0; |
360 |
|
|
361 |
47399 |
if (http_GetHdr(bo->beresp, H_Content_Encoding, &p)) |
362 |
8001 |
is_gzip = !strcasecmp(p, "gzip"); |
363 |
|
else |
364 |
39398 |
is_gunzip = 1; |
365 |
|
|
366 |
|
/* We won't gunzip unless it is gzipped */ |
367 |
47399 |
if (do_gunzip && !is_gzip) |
368 |
80 |
do_gunzip = 0; |
369 |
|
|
370 |
|
/* We wont gzip unless if it already is gzipped */ |
371 |
47399 |
if (do_gzip && !is_gunzip) |
372 |
0 |
do_gzip = 0; |
373 |
|
|
374 |
47399 |
if (do_gunzip || (is_gzip && bo->do_esi)) |
375 |
6360 |
VSB_cat(vsb, " gunzip"); |
376 |
|
|
377 |
47399 |
if (bo->do_esi && (do_gzip || (is_gzip && !do_gunzip))) { |
378 |
6480 |
VSB_cat(vsb, " esi_gzip"); |
379 |
6480 |
return; |
380 |
|
} |
381 |
|
|
382 |
40919 |
if (bo->do_esi) { |
383 |
6000 |
VSB_cat(vsb, " esi"); |
384 |
6000 |
return; |
385 |
|
} |
386 |
|
|
387 |
34919 |
if (do_gzip) |
388 |
640 |
VSB_cat(vsb, " gzip"); |
389 |
|
|
390 |
34919 |
if (is_gzip && !do_gunzip) |
391 |
1640 |
VSB_cat(vsb, " testgunzip"); |
392 |
47399 |
} |
393 |
|
|
394 |
|
const char * |
395 |
47399 |
VBF_Get_Filter_List(struct busyobj *bo) |
396 |
|
{ |
397 |
|
|
398 |
47399 |
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); |
399 |
47399 |
return (filter_on_ws(bo->ws, vbf_default_filter_list, bo)); |
400 |
|
} |
401 |
|
|
402 |
|
static const char * |
403 |
40 |
bereq_Empty_Filter(struct busyobj *bo) |
404 |
|
{ |
405 |
|
|
406 |
40 |
(void)bo; |
407 |
40 |
return (""); |
408 |
|
} |
409 |
|
|
410 |
|
/*-------------------------------------------------------------------- |
411 |
|
*/ |
412 |
|
|
413 |
|
static void v_matchproto_(filter_list_t) |
414 |
141160 |
resp_default_filter_list(void *arg, struct vsb *vsb) |
415 |
|
{ |
416 |
|
struct req *req; |
417 |
|
|
418 |
141160 |
CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC); |
419 |
|
|
420 |
141160 |
if (!req->disable_esi && req->objcore != NULL && |
421 |
140559 |
ObjHasAttr(req->wrk, req->objcore, OA_ESIDATA)) |
422 |
9000 |
VSB_cat(vsb, " esi"); |
423 |
|
|
424 |
151519 |
if (cache_param->http_gzip_support && |
425 |
140835 |
req->objcore != NULL && |
426 |
140756 |
ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) && |
427 |
10359 |
!RFC2616_Req_Gzip(req->http)) |
428 |
3439 |
VSB_cat(vsb, " gunzip"); |
429 |
|
|
430 |
257757 |
if (cache_param->http_range_support && |
431 |
140994 |
http_GetStatus(req->resp) == 200 && |
432 |
116597 |
http_GetHdr(req->http, H_Range, NULL)) |
433 |
2280 |
VSB_cat(vsb, " range"); |
434 |
141160 |
} |
435 |
|
|
436 |
|
const char * |
437 |
141170 |
resp_Get_Filter_List(struct req *req) |
438 |
|
{ |
439 |
141170 |
CHECK_OBJ_NOTNULL(req, REQ_MAGIC); |
440 |
141170 |
return (filter_on_ws(req->ws, resp_default_filter_list, req)); |
441 |
|
} |
442 |
|
|
443 |
|
static const char * |
444 |
80 |
req_Empty_Filter(struct req *req) |
445 |
|
{ |
446 |
|
|
447 |
80 |
(void)req; |
448 |
80 |
return (""); |
449 |
|
} |
450 |
|
|
451 |
|
/*--------------------------------------------------------------------*/ |
452 |
|
static int |
453 |
400 |
req_filter_can(struct req *req) { |
454 |
400 |
CHECK_OBJ_NOTNULL(req, REQ_MAGIC); |
455 |
|
|
456 |
400 |
return (req->req_body_status->avail == 1); |
457 |
|
} |
458 |
|
|
459 |
|
/*--------------------------------------------------------------------*/ |
460 |
|
|
461 |
|
//lint -emacro(506, FILTER_VAR) constant value boolean |
462 |
|
//lint -emacro(774, FILTER_VAR) if always evaluates to false |
463 |
|
#define FILTER_VAR(vcl, in, func, cond, fld) \ |
464 |
|
VCL_STRING \ |
465 |
|
VRT_r_##vcl##_filters(VRT_CTX) \ |
466 |
|
{ \ |
467 |
|
\ |
468 |
|
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \ |
469 |
|
if (ctx->in->fld != NULL) \ |
470 |
|
return(ctx->in->fld); \ |
471 |
|
return (func(ctx->in)); \ |
472 |
|
} \ |
473 |
|
\ |
474 |
|
VCL_VOID \ |
475 |
|
VRT_l_##vcl##_filters(VRT_CTX, const char *str, VCL_STRANDS s) \ |
476 |
|
{ \ |
477 |
|
const char *b; \ |
478 |
|
\ |
479 |
|
(void)str; \ |
480 |
|
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \ |
481 |
|
if (! (cond)) { \ |
482 |
|
VRT_fail(ctx, #vcl ".filters not settable"); \ |
483 |
|
return; \ |
484 |
|
} \ |
485 |
|
b = VRT_StrandsWS(ctx->in->ws, str, s); \ |
486 |
|
if (b == NULL) \ |
487 |
|
WS_MarkOverflow(ctx->in->ws); \ |
488 |
|
else \ |
489 |
|
ctx->in->fld = b; \ |
490 |
|
} |
491 |
|
|
492 |
320 |
FILTER_VAR(bereq, bo, bereq_Empty_Filter, 1, vdp_filter_list) |
493 |
1680 |
FILTER_VAR(beresp, bo, VBF_Get_Filter_List, 1, vfp_filter_list) |
494 |
480 |
FILTER_VAR(req, req, req_Empty_Filter, req_filter_can(ctx->req), vfp_filter_list) |
495 |
21920 |
FILTER_VAR(resp, req, resp_Get_Filter_List, 1, vdp_filter_list) |