11434Szelenkov@nginx.comimport re 21477Szelenkov@nginx.com 31434Szelenkov@nginx.comfrom unit.applications.proto import TestApplicationProto 41434Szelenkov@nginx.com 51434Szelenkov@nginx.com 61434Szelenkov@nginx.comclass TestReturn(TestApplicationProto): 71434Szelenkov@nginx.com prerequisites = {} 81434Szelenkov@nginx.com 91596Szelenkov@nginx.com def setup_method(self): 101434Szelenkov@nginx.com self._load_conf( 111434Szelenkov@nginx.com { 121434Szelenkov@nginx.com "listeners": {"*:7080": {"pass": "routes"}}, 131434Szelenkov@nginx.com "routes": [{"action": {"return": 200}}], 141434Szelenkov@nginx.com "applications": {}, 151434Szelenkov@nginx.com } 161434Szelenkov@nginx.com ) 171434Szelenkov@nginx.com 181434Szelenkov@nginx.com def get_resps_sc(self, req=10): 191434Szelenkov@nginx.com to_send = b"""GET / HTTP/1.1 201434Szelenkov@nginx.comHost: localhost 211434Szelenkov@nginx.com 221434Szelenkov@nginx.com""" * ( 231434Szelenkov@nginx.com req - 1 241434Szelenkov@nginx.com ) 251434Szelenkov@nginx.com 261434Szelenkov@nginx.com to_send += b"""GET / HTTP/1.1 271434Szelenkov@nginx.comHost: localhost 281434Szelenkov@nginx.comConnection: close 291434Szelenkov@nginx.com 301434Szelenkov@nginx.com""" 311434Szelenkov@nginx.com 321434Szelenkov@nginx.com return self.http(to_send, raw_resp=True, raw=True) 331434Szelenkov@nginx.com 341434Szelenkov@nginx.com def test_return(self): 351434Szelenkov@nginx.com resp = self.get() 361596Szelenkov@nginx.com assert resp['status'] == 200 371596Szelenkov@nginx.com assert 'Server' in resp['headers'] 381596Szelenkov@nginx.com assert 'Date' in resp['headers'] 391596Szelenkov@nginx.com assert resp['headers']['Content-Length'] == '0' 401596Szelenkov@nginx.com assert resp['headers']['Connection'] == 'close' 411596Szelenkov@nginx.com assert resp['body'] == '', 'body' 421434Szelenkov@nginx.com 431434Szelenkov@nginx.com resp = self.post(body='blah') 441596Szelenkov@nginx.com assert resp['status'] == 200 451596Szelenkov@nginx.com assert resp['body'] == '', 'body' 461434Szelenkov@nginx.com 471434Szelenkov@nginx.com resp = self.get_resps_sc() 481596Szelenkov@nginx.com assert len(re.findall('200 OK', resp)) == 10 491596Szelenkov@nginx.com assert len(re.findall('Connection:', resp)) == 1 501596Szelenkov@nginx.com assert len(re.findall('Connection: close', resp)) == 1 511434Szelenkov@nginx.com 521434Szelenkov@nginx.com resp = self.get(http_10=True) 531596Szelenkov@nginx.com assert resp['status'] == 200 541596Szelenkov@nginx.com assert 'Server' in resp['headers'] 551596Szelenkov@nginx.com assert 'Date' in resp['headers'] 561596Szelenkov@nginx.com assert resp['headers']['Content-Length'] == '0' 571596Szelenkov@nginx.com assert 'Connection' not in resp['headers'] 581596Szelenkov@nginx.com assert resp['body'] == '', 'body' 591434Szelenkov@nginx.com 601434Szelenkov@nginx.com def test_return_update(self): 611596Szelenkov@nginx.com assert 'success' in self.conf('0', 'routes/0/action/return') 621434Szelenkov@nginx.com 631434Szelenkov@nginx.com resp = self.get() 641596Szelenkov@nginx.com assert resp['status'] == 0 651596Szelenkov@nginx.com assert resp['body'] == '' 661434Szelenkov@nginx.com 671596Szelenkov@nginx.com assert 'success' in self.conf('404', 'routes/0/action/return') 681434Szelenkov@nginx.com 691434Szelenkov@nginx.com resp = self.get() 701596Szelenkov@nginx.com assert resp['status'] == 404 711596Szelenkov@nginx.com assert resp['body'] != '' 721434Szelenkov@nginx.com 731596Szelenkov@nginx.com assert 'success' in self.conf('598', 'routes/0/action/return') 741434Szelenkov@nginx.com 751434Szelenkov@nginx.com resp = self.get() 761596Szelenkov@nginx.com assert resp['status'] == 598 771596Szelenkov@nginx.com assert resp['body'] != '' 781434Szelenkov@nginx.com 791596Szelenkov@nginx.com assert 'success' in self.conf('999', 'routes/0/action/return') 801434Szelenkov@nginx.com 811434Szelenkov@nginx.com resp = self.get() 821596Szelenkov@nginx.com assert resp['status'] == 999 831596Szelenkov@nginx.com assert resp['body'] == '' 841434Szelenkov@nginx.com 851435Szelenkov@nginx.com def test_return_location(self): 862082Salx.manpages@gmail.com reserved = ":/?#[]@!&'()*+,;=" 871596Szelenkov@nginx.com unreserved = ( 881596Szelenkov@nginx.com "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 891596Szelenkov@nginx.com "0123456789-._~" 901596Szelenkov@nginx.com ) 911435Szelenkov@nginx.com unsafe = " \"%<>\\^`{|}" 921435Szelenkov@nginx.com unsafe_enc = "%20%22%25%3C%3E%5C%5E%60%7B%7C%7D" 931435Szelenkov@nginx.com 941435Szelenkov@nginx.com def check_location(location, expect=None): 951435Szelenkov@nginx.com if expect is None: 961435Szelenkov@nginx.com expect = location 971435Szelenkov@nginx.com 981596Szelenkov@nginx.com assert 'success' in self.conf( 991596Szelenkov@nginx.com {"return": 301, "location": location}, 'routes/0/action' 1001596Szelenkov@nginx.com ), 'configure location' 1011435Szelenkov@nginx.com 1021596Szelenkov@nginx.com assert self.get()['headers']['Location'] == expect 1031435Szelenkov@nginx.com 1041435Szelenkov@nginx.com # FAIL: can't specify empty header value. 1051435Szelenkov@nginx.com # check_location("") 1061435Szelenkov@nginx.com 1071435Szelenkov@nginx.com check_location(reserved) 1081435Szelenkov@nginx.com 1091435Szelenkov@nginx.com # After first "?" all other "?" encoded. 1102082Salx.manpages@gmail.com check_location("/?" + reserved, "/?:/%3F#[]@!&'()*+,;=") 1111435Szelenkov@nginx.com check_location("???", "?%3F%3F") 1121435Szelenkov@nginx.com 1131435Szelenkov@nginx.com # After first "#" all other "?" or "#" encoded. 1142082Salx.manpages@gmail.com check_location("/#" + reserved, "/#:/%3F%23[]@!&'()*+,;=") 1151435Szelenkov@nginx.com check_location("##?#?", "#%23%3F%23%3F") 1161435Szelenkov@nginx.com 1171435Szelenkov@nginx.com # After first "?" next "#" not encoded. 1182082Salx.manpages@gmail.com check_location("/?#" + reserved, "/?#:/%3F%23[]@!&'()*+,;=") 1191435Szelenkov@nginx.com check_location("??##", "?%3F#%23") 1201435Szelenkov@nginx.com check_location("/?##?", "/?#%23%3F") 1211435Szelenkov@nginx.com 1221435Szelenkov@nginx.com # Unreserved never encoded. 1231435Szelenkov@nginx.com check_location(unreserved) 1241435Szelenkov@nginx.com check_location("/" + unreserved + "?" + unreserved + "#" + unreserved) 1251435Szelenkov@nginx.com 1261435Szelenkov@nginx.com # Unsafe always encoded. 1271435Szelenkov@nginx.com check_location(unsafe, unsafe_enc) 1281435Szelenkov@nginx.com check_location("?" + unsafe, "?" + unsafe_enc) 1291435Szelenkov@nginx.com check_location("#" + unsafe, "#" + unsafe_enc) 1301435Szelenkov@nginx.com 1311435Szelenkov@nginx.com # %00-%20 and %7F-%FF always encoded. 1321435Szelenkov@nginx.com check_location(u"\u0000\u0018\u001F\u0020\u0021", "%00%18%1F%20!") 1331435Szelenkov@nginx.com check_location(u"\u007F\u0080н\u20BD", "%7F%C2%80%D0%BD%E2%82%BD") 1341435Szelenkov@nginx.com 1351435Szelenkov@nginx.com # Encoded string detection. If at least one char need to be encoded 1361435Szelenkov@nginx.com # then whole string will be encoded. 1371435Szelenkov@nginx.com check_location("%20") 1381435Szelenkov@nginx.com check_location("/%20?%20#%20") 1391435Szelenkov@nginx.com check_location(" %20", "%20%2520") 1401435Szelenkov@nginx.com check_location("%20 ", "%2520%20") 1411435Szelenkov@nginx.com check_location("/%20?%20#%20 ", "/%2520?%2520#%2520%20") 1421435Szelenkov@nginx.com 1431435Szelenkov@nginx.com def test_return_location_edit(self): 1441596Szelenkov@nginx.com assert 'success' in self.conf( 1451596Szelenkov@nginx.com {"return": 302, "location": "blah"}, 'routes/0/action' 1461596Szelenkov@nginx.com ), 'configure init location' 1471596Szelenkov@nginx.com assert self.get()['headers']['Location'] == 'blah' 1481596Szelenkov@nginx.com 1491596Szelenkov@nginx.com assert 'success' in self.conf_delete( 1501596Szelenkov@nginx.com 'routes/0/action/location' 1511596Szelenkov@nginx.com ), 'location delete' 1521596Szelenkov@nginx.com assert 'Location' not in self.get()['headers'] 1531435Szelenkov@nginx.com 1541596Szelenkov@nginx.com assert 'success' in self.conf( 1551596Szelenkov@nginx.com '"blah"', 'routes/0/action/location' 1561596Szelenkov@nginx.com ), 'location restore' 1571596Szelenkov@nginx.com assert self.get()['headers']['Location'] == 'blah' 1581435Szelenkov@nginx.com 1591596Szelenkov@nginx.com assert 'error' in self.conf_post( 1601596Szelenkov@nginx.com '"blah"', 'routes/0/action/location' 1611596Szelenkov@nginx.com ), 'location method not allowed' 1621596Szelenkov@nginx.com assert self.get()['headers']['Location'] == 'blah' 1631435Szelenkov@nginx.com 1642083Salx.manpages@gmail.com assert 'success' in self.conf( 1652083Salx.manpages@gmail.com '"https://${host}${uri}"', 'routes/0/action/location' 1662083Salx.manpages@gmail.com ), 'location with variables' 1672083Salx.manpages@gmail.com assert self.get()['headers']['Location'] == 'https://localhost/' 1682083Salx.manpages@gmail.com 1692083Salx.manpages@gmail.com assert 'success' in self.conf( 1702083Salx.manpages@gmail.com '"/#$host"', 'routes/0/action/location' 1712083Salx.manpages@gmail.com ), 'location with encoding and a variable' 1722083Salx.manpages@gmail.com assert self.get()['headers']['Location'] == '/#localhost' 1732083Salx.manpages@gmail.com 1742083Salx.manpages@gmail.com assert ( 1752083Salx.manpages@gmail.com self.get(headers={"Host": "#foo?bar", "Connection": "close"})[ 1762083Salx.manpages@gmail.com 'headers' 1772083Salx.manpages@gmail.com ]['Location'] 1782083Salx.manpages@gmail.com == "/#%23foo%3Fbar" 1792083Salx.manpages@gmail.com ), 'location with a variable with encoding' 1802083Salx.manpages@gmail.com 181*2099Salx.manpages@gmail.com assert 'success' in self.conf( 182*2099Salx.manpages@gmail.com '""', 'routes/0/action/location' 183*2099Salx.manpages@gmail.com ), 'location empty' 184*2099Salx.manpages@gmail.com assert self.get()['headers']['Location'] == '' 185*2099Salx.manpages@gmail.com 186*2099Salx.manpages@gmail.com assert 'success' in self.conf( 187*2099Salx.manpages@gmail.com '"${host}"', 'routes/0/action/location' 188*2099Salx.manpages@gmail.com ), 'location empty with variable' 189*2099Salx.manpages@gmail.com assert ( 190*2099Salx.manpages@gmail.com self.get(headers={"Host": "", "Connection": "close"})['headers'][ 191*2099Salx.manpages@gmail.com 'Location' 192*2099Salx.manpages@gmail.com ] 193*2099Salx.manpages@gmail.com == "" 194*2099Salx.manpages@gmail.com ), 'location with empty variable' 195*2099Salx.manpages@gmail.com 1961434Szelenkov@nginx.com def test_return_invalid(self): 1971434Szelenkov@nginx.com def check_error(conf): 1981596Szelenkov@nginx.com assert 'error' in self.conf(conf, 'routes/0/action') 1991434Szelenkov@nginx.com 2001434Szelenkov@nginx.com check_error({"return": "200"}) 2011434Szelenkov@nginx.com check_error({"return": []}) 2021441Szelenkov@nginx.com check_error({"return": 80.1}) 2031434Szelenkov@nginx.com check_error({"return": 1000}) 2041443Szelenkov@nginx.com check_error({"return": -1}) 2051434Szelenkov@nginx.com check_error({"return": 200, "share": "/blah"}) 2062083Salx.manpages@gmail.com check_error({"return": 200, "location": "$hos"}) 2072083Salx.manpages@gmail.com check_error({"return": 200, "location": "$hostblah"}) 2081434Szelenkov@nginx.com 2091596Szelenkov@nginx.com assert 'error' in self.conf( 2101596Szelenkov@nginx.com '001', 'routes/0/action/return' 2111596Szelenkov@nginx.com ), 'leading zero' 2121434Szelenkov@nginx.com 2131435Szelenkov@nginx.com check_error({"return": 301, "location": 0}) 2141435Szelenkov@nginx.com check_error({"return": 301, "location": []}) 215