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