xref: /unit/test/test_proxy_chunked.py (revision 2073:bc6ad31ce286)
11506Szelenkov@nginx.comimport re
21527Szelenkov@nginx.comimport select
31506Szelenkov@nginx.comimport socket
41506Szelenkov@nginx.comimport time
51506Szelenkov@nginx.com
61654Szelenkov@nginx.comfrom conftest import run_process
71506Szelenkov@nginx.comfrom unit.applications.lang.python import TestApplicationPython
81730Szelenkov@nginx.comfrom unit.option import option
91735Szelenkov@nginx.comfrom unit.utils import waitforsocket
101506Szelenkov@nginx.com
111506Szelenkov@nginx.com
121506Szelenkov@nginx.comclass TestProxyChunked(TestApplicationPython):
131506Szelenkov@nginx.com    prerequisites = {'modules': {'python': 'any'}}
141506Szelenkov@nginx.com
151506Szelenkov@nginx.com    SERVER_PORT = 7999
161506Szelenkov@nginx.com
171506Szelenkov@nginx.com    @staticmethod
181596Szelenkov@nginx.com    def run_server(server_port, temp_dir):
191506Szelenkov@nginx.com        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
201506Szelenkov@nginx.com        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
211506Szelenkov@nginx.com        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
221506Szelenkov@nginx.com
231506Szelenkov@nginx.com        server_address = ('127.0.0.1', server_port)
241506Szelenkov@nginx.com        sock.bind(server_address)
251506Szelenkov@nginx.com        sock.listen(10)
261506Szelenkov@nginx.com
271506Szelenkov@nginx.com        def recvall(sock):
281506Szelenkov@nginx.com            buff_size = 4096 * 4096
291506Szelenkov@nginx.com            data = b''
301506Szelenkov@nginx.com            while True:
311506Szelenkov@nginx.com                rlist = select.select([sock], [], [], 0.1)
321506Szelenkov@nginx.com
331506Szelenkov@nginx.com                if not rlist[0]:
341506Szelenkov@nginx.com                    break
351506Szelenkov@nginx.com
361506Szelenkov@nginx.com                part = sock.recv(buff_size)
371506Szelenkov@nginx.com                data += part
381506Szelenkov@nginx.com
391506Szelenkov@nginx.com                if not len(part):
401506Szelenkov@nginx.com                    break
411506Szelenkov@nginx.com
421506Szelenkov@nginx.com            return data
431506Szelenkov@nginx.com
441506Szelenkov@nginx.com        while True:
451506Szelenkov@nginx.com            connection, client_address = sock.accept()
461506Szelenkov@nginx.com
471506Szelenkov@nginx.com            req = """HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked"""
481506Szelenkov@nginx.com
491506Szelenkov@nginx.com            data = recvall(connection).decode()
501506Szelenkov@nginx.com
511506Szelenkov@nginx.com            m = re.search('\x0d\x0a\x0d\x0a(.*)', data, re.M | re.S)
521506Szelenkov@nginx.com            if m is not None:
531506Szelenkov@nginx.com                body = m.group(1)
541506Szelenkov@nginx.com
551506Szelenkov@nginx.com                for line in re.split('\r\n', body):
561506Szelenkov@nginx.com                    add = ''
571635Szelenkov@nginx.com                    m1 = re.search(r'(.*)\sX\s(\d+)', line)
581506Szelenkov@nginx.com
591506Szelenkov@nginx.com                    if m1 is not None:
601506Szelenkov@nginx.com                        add = m1.group(1) * int(m1.group(2))
611506Szelenkov@nginx.com                    else:
621506Szelenkov@nginx.com                        add = line
631506Szelenkov@nginx.com
641506Szelenkov@nginx.com                    req = req + add + '\r\n'
651506Szelenkov@nginx.com
661506Szelenkov@nginx.com            for chunk in re.split(r'([@#])', req):
671506Szelenkov@nginx.com                if chunk == '@' or chunk == '#':
681506Szelenkov@nginx.com                    if chunk == '#':
691506Szelenkov@nginx.com                        time.sleep(0.1)
701506Szelenkov@nginx.com                    continue
711506Szelenkov@nginx.com
721506Szelenkov@nginx.com                connection.sendall(chunk.encode())
731506Szelenkov@nginx.com
741506Szelenkov@nginx.com            connection.close()
751506Szelenkov@nginx.com
761506Szelenkov@nginx.com    def chunks(self, chunks):
771506Szelenkov@nginx.com        body = '\r\n\r\n'
781506Szelenkov@nginx.com
791506Szelenkov@nginx.com        for l, c in chunks:
801506Szelenkov@nginx.com            body = body + l + '\r\n' + c + '\r\n'
811506Szelenkov@nginx.com
821506Szelenkov@nginx.com        return body + '0\r\n\r\n'
831506Szelenkov@nginx.com
841506Szelenkov@nginx.com    def get_http10(self, *args, **kwargs):
851506Szelenkov@nginx.com        return self.get(*args, http_10=True, **kwargs)
861506Szelenkov@nginx.com
871596Szelenkov@nginx.com    def setup_method(self):
881654Szelenkov@nginx.com        run_process(self.run_server, self.SERVER_PORT, option.temp_dir)
891654Szelenkov@nginx.com        waitforsocket(self.SERVER_PORT)
901506Szelenkov@nginx.com
911596Szelenkov@nginx.com        assert 'success' in self.conf(
921596Szelenkov@nginx.com            {
93*2073Szelenkov@nginx.com                "listeners": {
94*2073Szelenkov@nginx.com                    "*:7080": {"pass": "routes"},
95*2073Szelenkov@nginx.com                },
961596Szelenkov@nginx.com                "routes": [
971596Szelenkov@nginx.com                    {
981596Szelenkov@nginx.com                        "action": {
99*2073Szelenkov@nginx.com                            "proxy": "http://127.0.0.1:" + str(self.SERVER_PORT)
1001506Szelenkov@nginx.com                        }
1011596Szelenkov@nginx.com                    }
1021596Szelenkov@nginx.com                ],
1031596Szelenkov@nginx.com            }
1041596Szelenkov@nginx.com        ), 'proxy initial configuration'
1051506Szelenkov@nginx.com
1061506Szelenkov@nginx.com    def test_proxy_chunked(self):
1071506Szelenkov@nginx.com        for _ in range(10):
1081596Szelenkov@nginx.com            assert self.get_http10(body='\r\n\r\n0\r\n\r\n')['status'] == 200
1091506Szelenkov@nginx.com
1101506Szelenkov@nginx.com    def test_proxy_chunked_body(self):
1111506Szelenkov@nginx.com        part = '0123456789abcdef'
1121506Szelenkov@nginx.com
1131596Szelenkov@nginx.com        assert (
1141506Szelenkov@nginx.com            self.get_http10(body=self.chunks([('1000', part + ' X 256')]))[
1151506Szelenkov@nginx.com                'body'
1161596Szelenkov@nginx.com            ]
1171596Szelenkov@nginx.com            == part * 256
1181506Szelenkov@nginx.com        )
1191596Szelenkov@nginx.com        assert (
1201506Szelenkov@nginx.com            self.get_http10(body=self.chunks([('100000', part + ' X 65536')]))[
1211506Szelenkov@nginx.com                'body'
1221596Szelenkov@nginx.com            ]
1231596Szelenkov@nginx.com            == part * 65536
1241506Szelenkov@nginx.com        )
1251596Szelenkov@nginx.com        assert (
1261506Szelenkov@nginx.com            self.get_http10(
1271506Szelenkov@nginx.com                body=self.chunks([('1000000', part + ' X 1048576')]),
1281506Szelenkov@nginx.com                read_buffer_size=4096 * 4096,
1291596Szelenkov@nginx.com            )['body']
1301596Szelenkov@nginx.com            == part * 1048576
1311506Szelenkov@nginx.com        )
1321506Szelenkov@nginx.com
1331596Szelenkov@nginx.com        assert (
1341506Szelenkov@nginx.com            self.get_http10(
1351506Szelenkov@nginx.com                body=self.chunks(
1361506Szelenkov@nginx.com                    [('1000', part + ' X 256'), ('1000', part + ' X 256')]
1371506Szelenkov@nginx.com                )
1381596Szelenkov@nginx.com            )['body']
1391596Szelenkov@nginx.com            == part * 256 * 2
1401506Szelenkov@nginx.com        )
1411596Szelenkov@nginx.com        assert (
1421506Szelenkov@nginx.com            self.get_http10(
1431506Szelenkov@nginx.com                body=self.chunks(
1441506Szelenkov@nginx.com                    [
1451506Szelenkov@nginx.com                        ('100000', part + ' X 65536'),
1461506Szelenkov@nginx.com                        ('100000', part + ' X 65536'),
1471506Szelenkov@nginx.com                    ]
1481506Szelenkov@nginx.com                )
1491596Szelenkov@nginx.com            )['body']
1501596Szelenkov@nginx.com            == part * 65536 * 2
1511506Szelenkov@nginx.com        )
1521596Szelenkov@nginx.com        assert (
1531506Szelenkov@nginx.com            self.get_http10(
1541506Szelenkov@nginx.com                body=self.chunks(
1551506Szelenkov@nginx.com                    [
1561506Szelenkov@nginx.com                        ('1000000', part + ' X 1048576'),
1571506Szelenkov@nginx.com                        ('1000000', part + ' X 1048576'),
1581506Szelenkov@nginx.com                    ]
1591506Szelenkov@nginx.com                ),
1601506Szelenkov@nginx.com                read_buffer_size=4096 * 4096,
1611596Szelenkov@nginx.com            )['body']
1621596Szelenkov@nginx.com            == part * 1048576 * 2
1631506Szelenkov@nginx.com        )
1641506Szelenkov@nginx.com
1651506Szelenkov@nginx.com    def test_proxy_chunked_fragmented(self):
1661506Szelenkov@nginx.com        part = '0123456789abcdef'
1671506Szelenkov@nginx.com
1681596Szelenkov@nginx.com        assert (
1691506Szelenkov@nginx.com            self.get_http10(
170*2073Szelenkov@nginx.com                body=self.chunks([('1', hex(i % 16)[2:]) for i in range(4096)]),
1711596Szelenkov@nginx.com            )['body']
1721596Szelenkov@nginx.com            == part * 256
1731506Szelenkov@nginx.com        )
1741506Szelenkov@nginx.com
1751506Szelenkov@nginx.com    def test_proxy_chunked_send(self):
1761596Szelenkov@nginx.com        assert self.get_http10(body='\r\n\r\n@0@\r\n\r\n')['status'] == 200
1771596Szelenkov@nginx.com        assert (
1781506Szelenkov@nginx.com            self.get_http10(
1791506Szelenkov@nginx.com                body='\r@\n\r\n2\r@\na@b\r\n2\r\ncd@\r\n0\r@\n\r\n'
1801596Szelenkov@nginx.com            )['body']
1811596Szelenkov@nginx.com            == 'abcd'
1821506Szelenkov@nginx.com        )
1831596Szelenkov@nginx.com        assert (
1841506Szelenkov@nginx.com            self.get_http10(
1851506Szelenkov@nginx.com                body='\r\n\r\n2\r#\na#b\r\n##2\r\n#cd\r\n0\r\n#\r#\n'
1861596Szelenkov@nginx.com            )['body']
1871596Szelenkov@nginx.com            == 'abcd'
1881506Szelenkov@nginx.com        )
1891506Szelenkov@nginx.com
1901506Szelenkov@nginx.com    def test_proxy_chunked_invalid(self):
1911506Szelenkov@nginx.com        def check_invalid(body):
1921596Szelenkov@nginx.com            assert self.get_http10(body=body)['status'] != 200
1931506Szelenkov@nginx.com
1941506Szelenkov@nginx.com        check_invalid('\r\n\r0')
1951506Szelenkov@nginx.com        check_invalid('\r\n\r\n\r0')
1961506Szelenkov@nginx.com        check_invalid('\r\n\r\n\r\n0')
1971506Szelenkov@nginx.com        check_invalid('\r\nContent-Length: 5\r\n\r\n0\r\n\r\n')
1981506Szelenkov@nginx.com        check_invalid('\r\n\r\n1\r\nXX\r\n0\r\n\r\n')
1991506Szelenkov@nginx.com        check_invalid('\r\n\r\n2\r\nX\r\n0\r\n\r\n')
2001506Szelenkov@nginx.com        check_invalid('\r\n\r\nH\r\nXX\r\n0\r\n\r\n')
2011506Szelenkov@nginx.com        check_invalid('\r\n\r\n0\r\nX')
2021506Szelenkov@nginx.com
2031506Szelenkov@nginx.com        resp = self.get_http10(body='\r\n\r\n65#\r\nA X 100')
2041596Szelenkov@nginx.com        assert resp['status'] == 200, 'incomplete chunk status'
2051596Szelenkov@nginx.com        assert resp['body'][-5:] != '0\r\n\r\n', 'incomplete chunk'
2061506Szelenkov@nginx.com
2071506Szelenkov@nginx.com        resp = self.get_http10(body='\r\n\r\n64#\r\nA X 100')
2081596Szelenkov@nginx.com        assert resp['status'] == 200, 'no zero chunk status'
2091596Szelenkov@nginx.com        assert resp['body'][-5:] != '0\r\n\r\n', 'no zero chunk'
2101506Szelenkov@nginx.com
2111596Szelenkov@nginx.com        assert (
212*2073Szelenkov@nginx.com            self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] == 200
2131506Szelenkov@nginx.com        )
2141596Szelenkov@nginx.com        assert (
2151506Szelenkov@nginx.com            self.get_http10(body='\r\n\r\n10000000000000000\r\nA X 100')[
2161506Szelenkov@nginx.com                'status'
2171596Szelenkov@nginx.com            ]
2181596Szelenkov@nginx.com            == 502
2191506Szelenkov@nginx.com        )
2201596Szelenkov@nginx.com        assert (
2211506Szelenkov@nginx.com            len(
2221506Szelenkov@nginx.com                self.get_http10(
2231506Szelenkov@nginx.com                    body='\r\n\r\n1000000\r\nA X 1048576\r\n1000000\r\nA X 100',
2241506Szelenkov@nginx.com                    read_buffer_size=4096 * 4096,
2251506Szelenkov@nginx.com                )['body']
2261596Szelenkov@nginx.com            )
2271596Szelenkov@nginx.com            >= 1048576
2281506Szelenkov@nginx.com        )
2291596Szelenkov@nginx.com        assert (
2301506Szelenkov@nginx.com            len(
2311506Szelenkov@nginx.com                self.get_http10(
2321506Szelenkov@nginx.com                    body='\r\n\r\n1000000\r\nA X 1048576\r\nXXX\r\nA X 100',
2331506Szelenkov@nginx.com                    read_buffer_size=4096 * 4096,
2341506Szelenkov@nginx.com                )['body']
2351596Szelenkov@nginx.com            )
2361596Szelenkov@nginx.com            >= 1048576
2371506Szelenkov@nginx.com        )
238