xref: /unit/test/test_variables.py (revision 2159:cd24064ec2ee)
1from unit.applications.proto import TestApplicationProto
2
3
4class TestVariables(TestApplicationProto):
5    prerequisites = {}
6
7    def setup_method(self):
8        assert 'success' in self.conf(
9            {
10                "listeners": {"*:7080": {"pass": "routes/$method"}},
11                "routes": {
12                    "GET": [{"action": {"return": 201}}],
13                    "POST": [{"action": {"return": 202}}],
14                    "3": [{"action": {"return": 203}}],
15                    "4*": [{"action": {"return": 204}}],
16                    "blahGET}": [{"action": {"return": 205}}],
17                    "5GET": [{"action": {"return": 206}}],
18                    "GETGET": [{"action": {"return": 207}}],
19                    "localhost": [{"action": {"return": 208}}],
20                    "9?q#a": [{"action": {"return": 209}}],
21                    "blah": [{"action": {"return": 210}}],
22                    "127.0.0.1": [{"action": {"return": 211}}],
23                    "::1": [{"action": {"return": 212}}],
24                    "referer-value": [{"action": {"return": 213}}],
25                    "MSIE": [{"action": {"return": 214}}],
26                },
27            },
28        ), 'configure routes'
29
30    def conf_routes(self, routes):
31        assert 'success' in self.conf(routes, 'listeners/*:7080/pass')
32
33    def test_variables_method(self):
34        assert self.get()['status'] == 201, 'method GET'
35        assert self.post()['status'] == 202, 'method POST'
36
37    def test_variables_request_uri(self):
38        self.conf_routes("\"routes$request_uri\"")
39
40        assert self.get(url='/3')['status'] == 203, 'request_uri'
41        assert self.get(url='/4*')['status'] == 204, 'request_uri 2'
42        assert self.get(url='/4%2A')['status'] == 204, 'request_uri 3'
43        assert self.get(url='/9?q#a')['status'] == 209, 'request_uri query'
44
45    def test_variables_uri(self):
46        self.conf_routes("\"routes$uri\"")
47
48        assert self.get(url='/3')['status'] == 203, 'uri'
49        assert self.get(url='/4*')['status'] == 204, 'uri 2'
50        assert self.get(url='/4%2A')['status'] == 204, 'uri 3'
51
52    def test_variables_host(self):
53        self.conf_routes("\"routes/$host\"")
54
55        def check_host(host, status=208):
56            assert (
57                self.get(headers={'Host': host, 'Connection': 'close'})[
58                    'status'
59                ]
60                == status
61            )
62
63        check_host('localhost')
64        check_host('localhost.')
65        check_host('localhost:7080')
66        check_host('.localhost', 404)
67        check_host('www.localhost', 404)
68        check_host('localhost1', 404)
69
70    def test_variables_remote_addr(self):
71        self.conf_routes("\"routes/$remote_addr\"")
72        assert self.get()['status'] == 211
73
74        assert 'success' in self.conf(
75            {"[::1]:7080": {"pass": "routes/$remote_addr"}}, 'listeners'
76        )
77        assert self.get(sock_type='ipv6')['status'] == 212
78
79    def test_variables_header_referer(self):
80        self.conf_routes("\"routes/$header_referer\"")
81
82        def check_referer(referer, status=213):
83            assert (
84                self.get(
85                    headers={
86                        'Host': 'localhost',
87                        'Connection': 'close',
88                        'Referer': referer,
89                    }
90                )['status']
91                == status
92            )
93
94        check_referer('referer-value')
95        check_referer('', 404)
96        check_referer('no', 404)
97
98    def test_variables_header_user_agent(self):
99        self.conf_routes("\"routes/$header_user_agent\"")
100
101        def check_user_agent(user_agent, status=214):
102            assert (
103                self.get(
104                    headers={
105                        'Host': 'localhost',
106                        'Connection': 'close',
107                        'User-Agent': user_agent,
108                    }
109                )['status']
110                == status
111            )
112
113        check_user_agent('MSIE')
114        check_user_agent('', 404)
115        check_user_agent('no', 404)
116
117    def test_variables_dollar(self):
118        assert 'success' in self.conf(
119            {
120                "listeners": {"*:7080": {"pass": "routes"}},
121                "routes": [{"action": {"return": 301}}],
122            }
123        )
124
125        def check_dollar(location, expect):
126            assert 'success' in self.conf(
127                '"' + location + '"',
128                'routes/0/action/location',
129            )
130            assert self.get()['headers']['Location'] == expect
131
132        check_dollar(
133            'https://${host}${uri}path${dollar}dollar',
134            'https://localhost/path$dollar',
135        )
136        check_dollar('path$dollar${dollar}', 'path$$')
137
138    def test_variables_many(self):
139        self.conf_routes("\"routes$uri$method\"")
140        assert self.get(url='/5')['status'] == 206, 'many'
141
142        self.conf_routes("\"routes${uri}${method}\"")
143        assert self.get(url='/5')['status'] == 206, 'many 2'
144
145        self.conf_routes("\"routes${uri}$method\"")
146        assert self.get(url='/5')['status'] == 206, 'many 3'
147
148        self.conf_routes("\"routes/$method$method\"")
149        assert self.get()['status'] == 207, 'many 4'
150
151        self.conf_routes("\"routes/$method$uri\"")
152        assert self.get()['status'] == 404, 'no route'
153        assert self.get(url='/blah')['status'] == 404, 'no route 2'
154
155    def test_variables_replace(self):
156        assert self.get()['status'] == 201
157
158        self.conf_routes("\"routes$uri\"")
159        assert self.get(url='/3')['status'] == 203
160
161        self.conf_routes("\"routes/${method}\"")
162        assert self.post()['status'] == 202
163
164        self.conf_routes("\"routes${uri}\"")
165        assert self.get(url='/4*')['status'] == 204
166
167        self.conf_routes("\"routes/blah$method}\"")
168        assert self.get()['status'] == 205
169
170    def test_variables_upstream(self):
171        assert 'success' in self.conf(
172            {
173                "listeners": {
174                    "*:7080": {"pass": "upstreams$uri"},
175                    "*:7081": {"pass": "routes/one"},
176                },
177                "upstreams": {"1": {"servers": {"127.0.0.1:7081": {}}}},
178                "routes": {"one": [{"action": {"return": 200}}]},
179            },
180        ), 'upstreams initial configuration'
181
182        assert self.get(url='/1')['status'] == 200
183        assert self.get(url='/2')['status'] == 404
184
185    def test_variables_empty(self):
186        def update_pass(prefix):
187            assert 'success' in self.conf(
188                {"listeners": {"*:7080": {"pass": prefix + "/$method"}}},
189            ), 'variables empty'
190
191        update_pass("routes")
192        assert self.get(url='/1')['status'] == 404
193
194        update_pass("upstreams")
195        assert self.get(url='/2')['status'] == 404
196
197        update_pass("applications")
198        assert self.get(url='/3')['status'] == 404
199
200    def test_variables_dynamic(self):
201        self.conf_routes("\"routes/$header_foo$arg_foo$cookie_foo\"")
202
203        self.get(
204            url='/?foo=h',
205            headers={'Foo': 'b', 'Cookie': 'foo=la', 'Connection': 'close'},
206        )['status'] = 210
207
208    def test_variables_dynamic_headers(self):
209        def check_header(header, status=210):
210            assert (
211                self.get(headers={header: "blah", 'Connection': 'close'})[
212                    'status'
213                ]
214                == status
215            )
216
217        self.conf_routes("\"routes/$header_foo_bar\"")
218        check_header('foo-bar')
219        check_header('Foo-Bar')
220        check_header('foo_bar', 404)
221        check_header('Foo', 404)
222        check_header('Bar', 404)
223        check_header('foobar', 404)
224
225        self.conf_routes("\"routes/$header_Foo_Bar\"")
226        check_header('Foo-Bar')
227        check_header('foo-bar')
228        check_header('foo_bar', 404)
229        check_header('foobar', 404)
230
231        self.conf_routes("\"routes/$header_foo-bar\"")
232        check_header('foo_bar', 404)
233
234    def test_variables_dynamic_arguments(self):
235        self.conf_routes("\"routes/$arg_foo_bar\"")
236        assert self.get(url='/?foo_bar=blah')['status'] == 210
237        assert self.get(url='/?foo_b%61r=blah')['status'] == 210
238        assert self.get(url='/?bar&foo_bar=blah&foo')['status'] == 210
239        assert self.get(url='/?Foo_bar=blah')['status'] == 404
240        assert self.get(url='/?foo-bar=blah')['status'] == 404
241        assert self.get()['status'] == 404
242        assert self.get(url='/?foo_bar=')['status'] == 404
243        assert self.get(url='/?foo_bar=l&foo_bar=blah')['status'] == 210
244        assert self.get(url='/?foo_bar=blah&foo_bar=l')['status'] == 404
245
246        self.conf_routes("\"routes/$arg_foo_b%61r\"")
247        assert self.get(url='/?foo_b=blah')['status'] == 404
248        assert self.get(url='/?foo_bar=blah')['status'] == 404
249
250        self.conf_routes("\"routes/$arg_f!~\"")
251        assert self.get(url='/?f=blah')['status'] == 404
252        assert self.get(url='/?f!~=blah')['status'] == 404
253
254    def test_variables_dynamic_cookies(self):
255        def check_cookie(cookie, status=210):
256            assert (
257                self.get(
258                    headers={
259                        'Host': 'localhost',
260                        'Cookie': cookie,
261                        'Connection': 'close',
262                    },
263                )['status']
264                == status
265            ), 'match cookie'
266
267        self.conf_routes("\"routes/$cookie_foo_bar\"")
268        check_cookie('foo_bar=blah', 210)
269        check_cookie('fOo_bar=blah', 404)
270        assert self.get()['status'] == 404
271        check_cookie('foo_bar', 404)
272        check_cookie('foo_bar=', 404)
273
274    def test_variables_invalid(self):
275        def check_variables(routes):
276            assert 'error' in self.conf(
277                routes, 'listeners/*:7080/pass'
278            ), 'invalid variables'
279
280        check_variables("\"routes$\"")
281        check_variables("\"routes${\"")
282        check_variables("\"routes${}\"")
283        check_variables("\"routes$ur\"")
284        check_variables("\"routes$uriblah\"")
285        check_variables("\"routes${uri\"")
286        check_variables("\"routes${{uri}\"")
287        check_variables("\"routes$ar\"")
288        check_variables("\"routes$arg\"")
289        check_variables("\"routes$arg_\"")
290        check_variables("\"routes$cookie\"")
291        check_variables("\"routes$cookie_\"")
292        check_variables("\"routes$header\"")
293        check_variables("\"routes$header_\"")
294