@@ -37,6 +37,65 @@ def generate_h2_request(optional_headers=[]) -> list:
37
37
] + optional_headers
38
38
39
39
40
+ def get_expected_response (
41
+ optional_headers : list , expected_headers : list , client , cache : bool , directive : str
42
+ ) -> Response or H2Response :
43
+ if client .proto == "h2" :
44
+ tempesta_headers = [
45
+ ("via" , "2.0 tempesta_fw (Tempesta FW pre-0.7.0)" ),
46
+ ]
47
+ else :
48
+ tempesta_headers = [
49
+ ("via" , "1.1 tempesta_fw (Tempesta FW pre-0.7.0)" ),
50
+ ("Connection" , "keep-alive" ),
51
+ ]
52
+
53
+ if cache :
54
+ tempesta_headers .append (("age" , client .last_response .headers ["age" ]))
55
+
56
+ if directive == "req" :
57
+ expected_response = generate_response (optional_headers = tempesta_headers + optional_headers )
58
+ else :
59
+ expected_response = generate_response (optional_headers = tempesta_headers + expected_headers )
60
+
61
+ if client .proto == "h2" :
62
+ expected_response = H2Response (expected_response .replace ("HTTP/1.1 200 OK" , ":status: 200" ))
63
+ else :
64
+ expected_response = Response (expected_response )
65
+ expected_response .set_expected ()
66
+ return expected_response
67
+
68
+
69
+ def get_expected_request (
70
+ optional_headers : list , expected_headers : list , client , directive : str
71
+ ) -> Request :
72
+ tempesta_headers = [
73
+ ("X-Forwarded-For" , "127.0.0.1" ),
74
+ ("via" , "1.1 tempesta_fw (Tempesta FW pre-0.7.0)" ),
75
+ ]
76
+ if directive == "req" :
77
+ expected_request = generate_http1_request (
78
+ optional_headers = tempesta_headers + expected_headers
79
+ )
80
+ else :
81
+ expected_request = generate_http1_request (
82
+ optional_headers = tempesta_headers + optional_headers
83
+ )
84
+
85
+ if client .proto == "h2" :
86
+ expected_request = expected_request .replace ("Connection: keep-alive\r \n " , "" )
87
+
88
+ expected_request = Request (expected_request )
89
+ expected_request .set_expected ()
90
+
91
+ return expected_request
92
+
93
+
94
+ def update_tempesta_config (tempesta , config : str , cache : bool ):
95
+ cache = "cache 2;\n cache_fulfill * *;\n " if cache else "cache 0;"
96
+ tempesta .config .defconfig += config + "\n " + cache
97
+
98
+
40
99
class TestLogicBase (tester .TempestaTest , base = True ):
41
100
tempesta = {
42
101
"config" : """
@@ -75,13 +134,8 @@ class TestLogicBase(tester.TempestaTest, base=True):
75
134
directive : str
76
135
h2 : bool
77
136
78
- def update_tempesta_config (self , config : str ):
79
- tempesta = self .get_tempesta ()
80
- cache = "cache 2;\n cache_fulfill * *;\n " if self .cache else "cache 0;"
81
- tempesta .config .defconfig += config + "\n " + cache
82
-
83
137
def base_scenario (self , config : str , optional_headers : list , expected_headers : list ):
84
- self .update_tempesta_config ( config = config )
138
+ update_tempesta_config ( tempesta = self .get_tempesta (), config = config , cache = self . cache )
85
139
self .start_all_services ()
86
140
87
141
server = self .get_server ("deproxy" )
@@ -98,72 +152,20 @@ def base_scenario(self, config: str, optional_headers: list, expected_headers: l
98
152
"200" ,
99
153
)
100
154
101
- expected_response = self .get_expected_response (optional_headers , expected_headers , client )
102
- expected_request = self .get_expected_request (optional_headers , expected_headers , client )
155
+ expected_response = get_expected_response (
156
+ optional_headers , expected_headers , client , self .cache , self .directive
157
+ )
158
+ expected_request = get_expected_request (
159
+ optional_headers , expected_headers , client , self .directive
160
+ )
103
161
162
+ client .last_response .headers .delete_all ("Date" )
163
+ expected_response .headers .delete_all ("Date" )
104
164
self .assertEqual (expected_response , client .last_response )
105
165
self .assertEqual (expected_request , server .last_request )
106
166
107
167
return client , server
108
168
109
- def get_expected_response (
110
- self , optional_headers : list , expected_headers : list , client
111
- ) -> Response or H2Response :
112
- if client .proto == "h2" :
113
- tempesta_headers = [
114
- ("via" , "2.0 tempesta_fw (Tempesta FW pre-0.7.0)" ),
115
- ]
116
- else :
117
- tempesta_headers = [
118
- ("via" , "1.1 tempesta_fw (Tempesta FW pre-0.7.0)" ),
119
- ("Connection" , "keep-alive" ),
120
- ]
121
-
122
- if self .cache :
123
- tempesta_headers .append (("age" , client .last_response .headers ["age" ]))
124
-
125
- if self .directive == "req" :
126
- expected_response = generate_response (
127
- optional_headers = tempesta_headers + optional_headers
128
- )
129
- else :
130
- expected_response = generate_response (
131
- optional_headers = tempesta_headers + expected_headers
132
- )
133
-
134
- if client .proto == "h2" :
135
- expected_response = H2Response (
136
- expected_response .replace ("HTTP/1.1 200 OK" , ":status: 200" )
137
- )
138
- else :
139
- expected_response = Response (expected_response )
140
- expected_response .set_expected ()
141
- return expected_response
142
-
143
- def get_expected_request (
144
- self , optional_headers : list , expected_headers : list , client
145
- ) -> Request :
146
- tempesta_headers = [
147
- ("X-Forwarded-For" , "127.0.0.1" ),
148
- ("via" , "1.1 tempesta_fw (Tempesta FW pre-0.7.0)" ),
149
- ]
150
- if self .directive == "req" :
151
- expected_request = generate_http1_request (
152
- optional_headers = tempesta_headers + expected_headers
153
- )
154
- else :
155
- expected_request = generate_http1_request (
156
- optional_headers = tempesta_headers + optional_headers
157
- )
158
-
159
- if client .proto == "h2" :
160
- expected_request = expected_request .replace ("Connection: keep-alive\r \n " , "" )
161
-
162
- expected_request = Request (expected_request )
163
- expected_request .set_expected ()
164
-
165
- return expected_request
166
-
167
169
def test_set_non_exist_header (self ):
168
170
"""
169
171
Header will be added in request/response if it is missing from base request/response.
@@ -174,6 +176,24 @@ def test_set_non_exist_header(self):
174
176
expected_headers = [("non-exist-header" , "qwe" )],
175
177
)
176
178
179
+ def test_set_exist_header (self ):
180
+ self .base_scenario (
181
+ config = f'{ self .directive } _hdr_set exist-header "qwe";\n ' ,
182
+ optional_headers = [("exist-header" , "123" )],
183
+ expected_headers = [("exist-header" , "qwe" )],
184
+ )
185
+
186
+ def test_set_exist_special_header (self ):
187
+ header_name = "set-cookie" if self .directive == "resp" else "if-none-match"
188
+ header_value = "test=cookie" if self .directive == "resp" else '"qwe"'
189
+ new_hdr_value = '"test=cookie2"' if self .directive == "resp" else r'"\"asd\""'
190
+ expected_new_hdr_value = "test=cookie2" if self .directive == "resp" else r'"asd"'
191
+ self .base_scenario (
192
+ config = f"{ self .directive } _hdr_set { header_name } { new_hdr_value } ;\n " ,
193
+ optional_headers = [(header_name , header_value )],
194
+ expected_headers = [(header_name , expected_new_hdr_value )],
195
+ )
196
+
177
197
def test_add_non_exist_header (self ):
178
198
"""
179
199
Header will be added in request/response if it is missing from base request/response.
@@ -241,7 +261,7 @@ def test_delete_many_special_headers(self):
241
261
"""
242
262
Headers must be removed from base request/response if header is in base request/response.
243
263
"""
244
- header_name = "set-cookie" if self .directive == "resp" else "if-match"
264
+ header_name = "set-cookie" if self .directive == "resp" else "if-none- match"
245
265
header_value = "test=cookie" if self .directive == "resp" else '"qwe"'
246
266
client , server = self .base_scenario (
247
267
config = f"{ self .directive } _hdr_set { header_name } ;\n " ,
@@ -305,6 +325,67 @@ class TestCachedRespHeader(TestLogicBase):
305
325
h2 = False
306
326
307
327
328
+ class TestManyRequestHeaders (tester .TempestaTest ):
329
+ tempesta = TestLogicBase .tempesta
330
+
331
+ clients = TestLogicBase .clients
332
+
333
+ backends = TestLogicBase .backends
334
+
335
+ cache = False
336
+ directive = "req"
337
+ h2 = False
338
+ requests_n = 1
339
+ __max_headers = 64
340
+ __headers_n = 64 // 4
341
+
342
+ def test_many_headers (self ):
343
+ set_headers = [(f"set-header-{ step } " , str (step ) * 2000 ) for step in range (self .__headers_n )]
344
+ add_headers = [(f"add-header-{ step } " , str (step ) * 2000 ) for step in range (self .__headers_n )]
345
+ exist_header = [
346
+ (f"exist-header-{ step } " , str (step ) * 1000 ) for step in range (self .__headers_n )
347
+ ]
348
+ changed_headers = [
349
+ (f"changed-header-{ step } " , f"{ step } a" ) for step in range (self .__headers_n )
350
+ ]
351
+ expected_changed_header = [
352
+ (header [0 ], header [1 ].replace ("a" , "" )) for header in changed_headers
353
+ ]
354
+
355
+ config = [
356
+ f'{ self .directive } _hdr_set { header [0 ]} "{ header [1 ]} ";\n ' for header in set_headers
357
+ ]
358
+ config .extend (
359
+ f'{ self .directive } _hdr_add { header [0 ]} "{ header [1 ]} ";\n ' for header in add_headers
360
+ )
361
+ config .extend (f"{ self .directive } _hdr_set { header [0 ]} ;\n " for header in exist_header )
362
+ config .extend (
363
+ f'{ self .directive } _hdr_set { header [0 ]} "{ header [1 ]} ";\n '
364
+ for header in expected_changed_header
365
+ )
366
+
367
+ TestLogicBase .base_scenario (
368
+ self ,
369
+ config = "" .join (config ),
370
+ optional_headers = exist_header + changed_headers ,
371
+ expected_headers = set_headers + add_headers + expected_changed_header ,
372
+ )
373
+
374
+
375
+ class TestManyResponseHeaders (TestManyRequestHeaders ):
376
+ cache = False
377
+ directive = "resp"
378
+ h2 = False
379
+ requests_n = 1
380
+
381
+
382
+ class TestManyCachedResponseHeaders (TestManyRequestHeaders ):
383
+ cache = True
384
+ directive = "resp"
385
+ h2 = False
386
+ requests_n = 2
387
+
388
+
308
389
class TestReqHeaderH2 (H2Config , TestLogicBase ):
309
390
directive = "req"
310
391
cache = False
@@ -330,7 +411,11 @@ def test_add_header_from_static_table(self):
330
411
331
412
def test_add_header_from_dynamic_table (self ):
332
413
"""Tempesta must add header from dynamic table for second response."""
333
- self .update_tempesta_config (config = f'{ self .directive } _hdr_set x-my-hdr "text";\n ' )
414
+ update_tempesta_config (
415
+ tempesta = self .get_tempesta (),
416
+ config = f'{ self .directive } _hdr_set x-my-hdr "text";\n ' ,
417
+ cache = self .cache ,
418
+ )
334
419
self .start_all_services ()
335
420
336
421
optional_headers = [("x-my-hdr" , "text" )]
@@ -353,3 +438,24 @@ class TestCachedRespHeaderH2(H2Config, TestLogicBase):
353
438
cache = True
354
439
requests_n = 2
355
440
h2 = True
441
+
442
+
443
+ class TestManyRequestHeadersH2 (H2Config , TestManyRequestHeaders ):
444
+ cache = False
445
+ directive = "req"
446
+ h2 = True
447
+ requests_n = 2
448
+
449
+
450
+ class TestManyResponseHeadersH2 (H2Config , TestManyRequestHeaders ):
451
+ cache = False
452
+ directive = "resp"
453
+ h2 = True
454
+ requests_n = 2
455
+
456
+
457
+ class TestManyCachedResponseHeadersH2 (H2Config , TestManyRequestHeaders ):
458
+ cache = True
459
+ directive = "resp"
460
+ h2 = True
461
+ requests_n = 2
0 commit comments