11184Szelenkov@nginx.comimport os 21204Szelenkov@nginx.comimport socket 31477Szelenkov@nginx.com 41635Szelenkov@nginx.comimport pytest 51848Szelenkov@nginx.com 61184Szelenkov@nginx.comfrom unit.applications.proto import TestApplicationProto 71730Szelenkov@nginx.comfrom unit.option import option 81735Szelenkov@nginx.comfrom unit.utils import waitforfiles 91184Szelenkov@nginx.com 101184Szelenkov@nginx.com 111184Szelenkov@nginx.comclass TestStatic(TestApplicationProto): 121184Szelenkov@nginx.com prerequisites = {} 131184Szelenkov@nginx.com 141596Szelenkov@nginx.com def setup_method(self): 151654Szelenkov@nginx.com os.makedirs(option.temp_dir + '/assets/dir') 161654Szelenkov@nginx.com with open(option.temp_dir + '/assets/index.html', 'w') as index, open( 171654Szelenkov@nginx.com option.temp_dir + '/assets/README', 'w' 181654Szelenkov@nginx.com ) as readme, open( 191654Szelenkov@nginx.com option.temp_dir + '/assets/log.log', 'w' 201654Szelenkov@nginx.com ) as log, open( 211654Szelenkov@nginx.com option.temp_dir + '/assets/dir/file', 'w' 221596Szelenkov@nginx.com ) as file: 231184Szelenkov@nginx.com index.write('0123456789') 241184Szelenkov@nginx.com readme.write('readme') 251184Szelenkov@nginx.com log.write('[debug]') 261184Szelenkov@nginx.com file.write('blah') 271184Szelenkov@nginx.com 281184Szelenkov@nginx.com self._load_conf( 291184Szelenkov@nginx.com { 301184Szelenkov@nginx.com "listeners": {"*:7080": {"pass": "routes"}}, 31*1960Sz.hong@f5.com "routes": [ 32*1960Sz.hong@f5.com {"action": {"share": option.temp_dir + "/assets$uri"}} 33*1960Sz.hong@f5.com ], 341184Szelenkov@nginx.com "settings": { 351184Szelenkov@nginx.com "http": { 361184Szelenkov@nginx.com "static": { 371184Szelenkov@nginx.com "mime_types": {"text/plain": [".log", "README"]} 381184Szelenkov@nginx.com } 391184Szelenkov@nginx.com } 401184Szelenkov@nginx.com }, 411184Szelenkov@nginx.com } 421184Szelenkov@nginx.com ) 431184Szelenkov@nginx.com 441184Szelenkov@nginx.com def test_static_index(self): 451596Szelenkov@nginx.com assert self.get(url='/index.html')['body'] == '0123456789', 'index' 461596Szelenkov@nginx.com assert self.get(url='/')['body'] == '0123456789', 'index 2' 471596Szelenkov@nginx.com assert self.get(url='//')['body'] == '0123456789', 'index 3' 481596Szelenkov@nginx.com assert self.get(url='/.')['body'] == '0123456789', 'index 4' 491596Szelenkov@nginx.com assert self.get(url='/./')['body'] == '0123456789', 'index 5' 501596Szelenkov@nginx.com assert self.get(url='/?blah')['body'] == '0123456789', 'index vars' 511596Szelenkov@nginx.com assert self.get(url='/#blah')['body'] == '0123456789', 'index anchor' 521596Szelenkov@nginx.com assert self.get(url='/dir/')['status'] == 404, 'index not found' 531184Szelenkov@nginx.com 541184Szelenkov@nginx.com resp = self.get(url='/index.html/') 551596Szelenkov@nginx.com assert resp['status'] == 404, 'index not found 2 status' 561596Szelenkov@nginx.com assert ( 571596Szelenkov@nginx.com resp['headers']['Content-Type'] == 'text/html' 581596Szelenkov@nginx.com ), 'index not found 2 Content-Type' 591184Szelenkov@nginx.com 601654Szelenkov@nginx.com def test_static_large_file(self, temp_dir): 611184Szelenkov@nginx.com file_size = 32 * 1024 * 1024 621654Szelenkov@nginx.com with open(temp_dir + '/assets/large', 'wb') as f: 631184Szelenkov@nginx.com f.seek(file_size - 1) 641184Szelenkov@nginx.com f.write(b'\0') 651184Szelenkov@nginx.com 661596Szelenkov@nginx.com assert ( 671596Szelenkov@nginx.com len(self.get(url='/large', read_buffer_size=1024 * 1024)['body']) 681596Szelenkov@nginx.com == file_size 691596Szelenkov@nginx.com ), 'large file' 701184Szelenkov@nginx.com 711654Szelenkov@nginx.com def test_static_etag(self, temp_dir): 721184Szelenkov@nginx.com etag = self.get(url='/')['headers']['ETag'] 731184Szelenkov@nginx.com etag_2 = self.get(url='/README')['headers']['ETag'] 741184Szelenkov@nginx.com 751596Szelenkov@nginx.com assert etag != etag_2, 'different ETag' 761596Szelenkov@nginx.com assert etag == self.get(url='/')['headers']['ETag'], 'same ETag' 771184Szelenkov@nginx.com 781654Szelenkov@nginx.com with open(temp_dir + '/assets/index.html', 'w') as f: 791184Szelenkov@nginx.com f.write('blah') 801184Szelenkov@nginx.com 811596Szelenkov@nginx.com assert etag != self.get(url='/')['headers']['ETag'], 'new ETag' 821184Szelenkov@nginx.com 831184Szelenkov@nginx.com def test_static_redirect(self): 841184Szelenkov@nginx.com resp = self.get(url='/dir') 851596Szelenkov@nginx.com assert resp['status'] == 301, 'redirect status' 861596Szelenkov@nginx.com assert resp['headers']['Location'] == '/dir/', 'redirect Location' 871596Szelenkov@nginx.com assert 'Content-Type' not in resp['headers'], 'redirect Content-Type' 881184Szelenkov@nginx.com 891654Szelenkov@nginx.com def test_static_space_in_name(self, temp_dir): 901184Szelenkov@nginx.com os.rename( 911848Szelenkov@nginx.com temp_dir + '/assets/dir/file', temp_dir + '/assets/dir/fi le', 921184Szelenkov@nginx.com ) 931654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/dir/fi le') 941596Szelenkov@nginx.com assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name' 951184Szelenkov@nginx.com 961654Szelenkov@nginx.com os.rename(temp_dir + '/assets/dir', temp_dir + '/assets/di r') 971654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/di r/fi le') 981596Szelenkov@nginx.com assert self.get(url='/di r/fi le')['body'] == 'blah', 'dir name' 991184Szelenkov@nginx.com 1001848Szelenkov@nginx.com os.rename(temp_dir + '/assets/di r', temp_dir + '/assets/ di r ') 1011654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/ di r /fi le') 1021596Szelenkov@nginx.com assert ( 1031596Szelenkov@nginx.com self.get(url='/ di r /fi le')['body'] == 'blah' 1041596Szelenkov@nginx.com ), 'dir name enclosing' 1051596Szelenkov@nginx.com 1061596Szelenkov@nginx.com assert ( 1071596Szelenkov@nginx.com self.get(url='/%20di%20r%20/fi le')['body'] == 'blah' 1081596Szelenkov@nginx.com ), 'dir encoded' 1091596Szelenkov@nginx.com assert ( 1101596Szelenkov@nginx.com self.get(url='/ di r %2Ffi le')['body'] == 'blah' 1111596Szelenkov@nginx.com ), 'slash encoded' 1121596Szelenkov@nginx.com assert ( 1131596Szelenkov@nginx.com self.get(url='/ di r /fi%20le')['body'] == 'blah' 1141596Szelenkov@nginx.com ), 'file encoded' 1151596Szelenkov@nginx.com assert ( 1161596Szelenkov@nginx.com self.get(url='/%20di%20r%20%2Ffi%20le')['body'] == 'blah' 1171596Szelenkov@nginx.com ), 'encoded' 1181596Szelenkov@nginx.com assert ( 1191596Szelenkov@nginx.com self.get(url='/%20%64%69%20%72%20%2F%66%69%20%6C%65')['body'] 1201596Szelenkov@nginx.com == 'blah' 1211596Szelenkov@nginx.com ), 'encoded 2' 1221184Szelenkov@nginx.com 1231184Szelenkov@nginx.com os.rename( 1241654Szelenkov@nginx.com temp_dir + '/assets/ di r /fi le', 1251654Szelenkov@nginx.com temp_dir + '/assets/ di r / fi le ', 1261184Szelenkov@nginx.com ) 1271654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/ di r / fi le ') 1281596Szelenkov@nginx.com assert ( 1291596Szelenkov@nginx.com self.get(url='/%20di%20r%20/%20fi%20le%20')['body'] == 'blah' 1301596Szelenkov@nginx.com ), 'file name enclosing' 1311184Szelenkov@nginx.com 1321184Szelenkov@nginx.com try: 1331654Szelenkov@nginx.com open(temp_dir + '/ф а', 'a').close() 1341184Szelenkov@nginx.com utf8 = True 1351184Szelenkov@nginx.com 1361706Smax.romanov@nginx.com except KeyboardInterrupt: 1371706Smax.romanov@nginx.com raise 1381706Smax.romanov@nginx.com 1391184Szelenkov@nginx.com except: 1401184Szelenkov@nginx.com utf8 = False 1411184Szelenkov@nginx.com 1421184Szelenkov@nginx.com if utf8: 1431184Szelenkov@nginx.com os.rename( 1441654Szelenkov@nginx.com temp_dir + '/assets/ di r / fi le ', 1451654Szelenkov@nginx.com temp_dir + '/assets/ di r /фа йл', 1461184Szelenkov@nginx.com ) 1471654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/ di r /фа йл') 1481596Szelenkov@nginx.com assert ( 1491596Szelenkov@nginx.com self.get(url='/ di r /фа йл')['body'] == 'blah' 1501596Szelenkov@nginx.com ), 'file name 2' 1511184Szelenkov@nginx.com 1521184Szelenkov@nginx.com os.rename( 1531848Szelenkov@nginx.com temp_dir + '/assets/ di r ', temp_dir + '/assets/ди ректория', 1541184Szelenkov@nginx.com ) 1551654Szelenkov@nginx.com assert waitforfiles(temp_dir + '/assets/ди ректория/фа йл') 1561596Szelenkov@nginx.com assert ( 1571596Szelenkov@nginx.com self.get(url='/ди ректория/фа йл')['body'] == 'blah' 1581596Szelenkov@nginx.com ), 'dir name 2' 1591184Szelenkov@nginx.com 1601654Szelenkov@nginx.com def test_static_unix_socket(self, temp_dir): 1611204Szelenkov@nginx.com sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 1621654Szelenkov@nginx.com sock.bind(temp_dir + '/assets/unix_socket') 1631204Szelenkov@nginx.com 1641596Szelenkov@nginx.com assert self.get(url='/unix_socket')['status'] == 404, 'socket' 1651204Szelenkov@nginx.com 1661204Szelenkov@nginx.com sock.close() 1671204Szelenkov@nginx.com 1681654Szelenkov@nginx.com def test_static_unix_fifo(self, temp_dir): 1691654Szelenkov@nginx.com os.mkfifo(temp_dir + '/assets/fifo') 1701204Szelenkov@nginx.com 1711596Szelenkov@nginx.com assert self.get(url='/fifo')['status'] == 404, 'fifo' 1721204Szelenkov@nginx.com 1731368Szelenkov@nginx.com def test_static_method(self): 1741368Szelenkov@nginx.com resp = self.head() 1751596Szelenkov@nginx.com assert resp['status'] == 200, 'HEAD status' 1761596Szelenkov@nginx.com assert resp['body'] == '', 'HEAD empty body' 1771368Szelenkov@nginx.com 1781596Szelenkov@nginx.com assert self.delete()['status'] == 405, 'DELETE' 1791596Szelenkov@nginx.com assert self.post()['status'] == 405, 'POST' 1801596Szelenkov@nginx.com assert self.put()['status'] == 405, 'PUT' 1811368Szelenkov@nginx.com 1821368Szelenkov@nginx.com def test_static_path(self): 1831596Szelenkov@nginx.com assert self.get(url='/dir/../dir/file')['status'] == 200, 'relative' 1841368Szelenkov@nginx.com 1851596Szelenkov@nginx.com assert self.get(url='./')['status'] == 400, 'path invalid' 1861596Szelenkov@nginx.com assert self.get(url='../')['status'] == 400, 'path invalid 2' 1871596Szelenkov@nginx.com assert self.get(url='/..')['status'] == 400, 'path invalid 3' 1881596Szelenkov@nginx.com assert self.get(url='../assets/')['status'] == 400, 'path invalid 4' 1891596Szelenkov@nginx.com assert self.get(url='/../assets/')['status'] == 400, 'path invalid 5' 1901184Szelenkov@nginx.com 1911184Szelenkov@nginx.com def test_static_two_clients(self): 1921184Szelenkov@nginx.com _, sock = self.get(url='/', start=True, no_recv=True) 1931184Szelenkov@nginx.com _, sock2 = self.get(url='/', start=True, no_recv=True) 1941184Szelenkov@nginx.com 1951596Szelenkov@nginx.com assert sock.recv(1) == b'H', 'client 1' 1961596Szelenkov@nginx.com assert sock2.recv(1) == b'H', 'client 2' 1971596Szelenkov@nginx.com assert sock.recv(1) == b'T', 'client 1 again' 1981596Szelenkov@nginx.com assert sock2.recv(1) == b'T', 'client 2 again' 1991184Szelenkov@nginx.com 2001184Szelenkov@nginx.com sock.close() 2011184Szelenkov@nginx.com sock2.close() 2021184Szelenkov@nginx.com 2031184Szelenkov@nginx.com def test_static_mime_types(self): 2041596Szelenkov@nginx.com assert 'success' in self.conf( 2051596Szelenkov@nginx.com { 2061596Szelenkov@nginx.com "text/x-code/x-blah/x-blah": "readme", 2071596Szelenkov@nginx.com "text/plain": [".html", ".log", "file"], 2081596Szelenkov@nginx.com }, 2091596Szelenkov@nginx.com 'settings/http/static/mime_types', 2101596Szelenkov@nginx.com ), 'configure mime_types' 2111184Szelenkov@nginx.com 2121596Szelenkov@nginx.com assert ( 2131596Szelenkov@nginx.com self.get(url='/README')['headers']['Content-Type'] 2141596Szelenkov@nginx.com == 'text/x-code/x-blah/x-blah' 2151596Szelenkov@nginx.com ), 'mime_types string case insensitive' 2161596Szelenkov@nginx.com assert ( 2171596Szelenkov@nginx.com self.get(url='/index.html')['headers']['Content-Type'] 2181596Szelenkov@nginx.com == 'text/plain' 2191596Szelenkov@nginx.com ), 'mime_types html' 2201596Szelenkov@nginx.com assert ( 2211596Szelenkov@nginx.com self.get(url='/')['headers']['Content-Type'] == 'text/plain' 2221596Szelenkov@nginx.com ), 'mime_types index default' 2231596Szelenkov@nginx.com assert ( 2241596Szelenkov@nginx.com self.get(url='/dir/file')['headers']['Content-Type'] 2251596Szelenkov@nginx.com == 'text/plain' 2261596Szelenkov@nginx.com ), 'mime_types file in dir' 2271184Szelenkov@nginx.com 2281184Szelenkov@nginx.com def test_static_mime_types_partial_match(self): 2291596Szelenkov@nginx.com assert 'success' in self.conf( 2301596Szelenkov@nginx.com {"text/x-blah": ["ile", "fil", "f", "e", ".file"],}, 2311596Szelenkov@nginx.com 'settings/http/static/mime_types', 2321596Szelenkov@nginx.com ), 'configure mime_types' 2331596Szelenkov@nginx.com assert 'Content-Type' not in self.get(url='/dir/file'), 'partial match' 2341184Szelenkov@nginx.com 2351184Szelenkov@nginx.com def test_static_mime_types_reconfigure(self): 2361596Szelenkov@nginx.com assert 'success' in self.conf( 2371596Szelenkov@nginx.com { 2381596Szelenkov@nginx.com "text/x-code": "readme", 2391596Szelenkov@nginx.com "text/plain": [".html", ".log", "file"], 2401596Szelenkov@nginx.com }, 2411596Szelenkov@nginx.com 'settings/http/static/mime_types', 2421596Szelenkov@nginx.com ), 'configure mime_types' 2431184Szelenkov@nginx.com 2441596Szelenkov@nginx.com assert self.conf_get('settings/http/static/mime_types') == { 2451596Szelenkov@nginx.com 'text/x-code': 'readme', 2461596Szelenkov@nginx.com 'text/plain': ['.html', '.log', 'file'], 2471596Szelenkov@nginx.com }, 'mime_types get' 2481596Szelenkov@nginx.com assert ( 2491596Szelenkov@nginx.com self.conf_get('settings/http/static/mime_types/text%2Fx-code') 2501596Szelenkov@nginx.com == 'readme' 2511596Szelenkov@nginx.com ), 'mime_types get string' 2521596Szelenkov@nginx.com assert self.conf_get( 2531596Szelenkov@nginx.com 'settings/http/static/mime_types/text%2Fplain' 2541596Szelenkov@nginx.com ) == ['.html', '.log', 'file'], 'mime_types get array' 2551596Szelenkov@nginx.com assert ( 2561596Szelenkov@nginx.com self.conf_get('settings/http/static/mime_types/text%2Fplain/1') 2571596Szelenkov@nginx.com == '.log' 2581596Szelenkov@nginx.com ), 'mime_types get array element' 2591184Szelenkov@nginx.com 2601596Szelenkov@nginx.com assert 'success' in self.conf_delete( 2611596Szelenkov@nginx.com 'settings/http/static/mime_types/text%2Fplain/2' 2621596Szelenkov@nginx.com ), 'mime_types remove array element' 2631596Szelenkov@nginx.com assert ( 2641596Szelenkov@nginx.com 'Content-Type' not in self.get(url='/dir/file')['headers'] 2651596Szelenkov@nginx.com ), 'mime_types removed' 2661596Szelenkov@nginx.com 2671596Szelenkov@nginx.com assert 'success' in self.conf_post( 2681596Szelenkov@nginx.com '"file"', 'settings/http/static/mime_types/text%2Fplain' 2691596Szelenkov@nginx.com ), 'mime_types add array element' 2701596Szelenkov@nginx.com assert ( 2711596Szelenkov@nginx.com self.get(url='/dir/file')['headers']['Content-Type'] 2721596Szelenkov@nginx.com == 'text/plain' 2731596Szelenkov@nginx.com ), 'mime_types reverted' 2741184Szelenkov@nginx.com 2751596Szelenkov@nginx.com assert 'success' in self.conf( 2761596Szelenkov@nginx.com '"file"', 'settings/http/static/mime_types/text%2Fplain' 2771596Szelenkov@nginx.com ), 'configure mime_types update' 2781596Szelenkov@nginx.com assert ( 2791596Szelenkov@nginx.com self.get(url='/dir/file')['headers']['Content-Type'] 2801596Szelenkov@nginx.com == 'text/plain' 2811596Szelenkov@nginx.com ), 'mime_types updated' 2821596Szelenkov@nginx.com assert ( 2831596Szelenkov@nginx.com 'Content-Type' not in self.get(url='/log.log')['headers'] 2841596Szelenkov@nginx.com ), 'mime_types updated 2' 2851184Szelenkov@nginx.com 2861596Szelenkov@nginx.com assert 'success' in self.conf( 2871596Szelenkov@nginx.com '".log"', 'settings/http/static/mime_types/text%2Fblahblahblah' 2881596Szelenkov@nginx.com ), 'configure mime_types create' 2891596Szelenkov@nginx.com assert ( 2901596Szelenkov@nginx.com self.get(url='/log.log')['headers']['Content-Type'] 2911596Szelenkov@nginx.com == 'text/blahblahblah' 2921596Szelenkov@nginx.com ), 'mime_types create' 2931184Szelenkov@nginx.com 2941184Szelenkov@nginx.com def test_static_mime_types_correct(self): 2951596Szelenkov@nginx.com assert 'error' in self.conf( 2961596Szelenkov@nginx.com {"text/x-code": "readme", "text/plain": "readme"}, 2971596Szelenkov@nginx.com 'settings/http/static/mime_types', 2981596Szelenkov@nginx.com ), 'mime_types same extensions' 2991596Szelenkov@nginx.com assert 'error' in self.conf( 3001596Szelenkov@nginx.com {"text/x-code": [".h", ".c"], "text/plain": ".c"}, 3011596Szelenkov@nginx.com 'settings/http/static/mime_types', 3021596Szelenkov@nginx.com ), 'mime_types same extensions array' 3031596Szelenkov@nginx.com assert 'error' in self.conf( 3041596Szelenkov@nginx.com {"text/x-code": [".h", ".c", "readme"], "text/plain": "README",}, 3051596Szelenkov@nginx.com 'settings/http/static/mime_types', 3061596Szelenkov@nginx.com ), 'mime_types same extensions case insensitive' 3071184Szelenkov@nginx.com 3081596Szelenkov@nginx.com @pytest.mark.skip('not yet') 3091654Szelenkov@nginx.com def test_static_mime_types_invalid(self, temp_dir): 3101596Szelenkov@nginx.com assert 'error' in self.http( 3111596Szelenkov@nginx.com b"""PUT /config/settings/http/static/mime_types/%0%00% HTTP/1.1\r 3121184Szelenkov@nginx.comHost: localhost\r 3131184Szelenkov@nginx.comConnection: close\r 3141184Szelenkov@nginx.comContent-Length: 6\r 3151184Szelenkov@nginx.com\r 3161184Szelenkov@nginx.com\"blah\"""", 3171596Szelenkov@nginx.com raw_resp=True, 3181596Szelenkov@nginx.com raw=True, 3191596Szelenkov@nginx.com sock_type='unix', 3201654Szelenkov@nginx.com addr=temp_dir + '/control.unit.sock', 3211596Szelenkov@nginx.com ), 'mime_types invalid' 322