def _setUp(self, request: Any, mocker: MockerFixture) -> None: self.mock_fromfd = mocker.patch('socket.fromfd') self.mock_selector = mocker.patch('selectors.DefaultSelector') self.fileno = 10 self._addr = ('127.0.0.1', 54382) self._conn = self.mock_fromfd.return_value self.pac_file = request.param if isinstance(self.pac_file, str): with open(self.pac_file, 'rb') as f: self.expected_response = f.read() else: self.expected_response = PAC_FILE_CONTENT self.flags = FlagParser.initialize( pac_file=self.pac_file, threaded=True, ) self.flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), bytes_(PLUGIN_PAC_FILE), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=self.flags, ) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET / HTTP/1.1', CRLF, ]) mock_selector_for_client_read(self)
async def test_proxy_authentication_failed(self) -> None: self._conn = self.mock_fromfd.return_value mock_selector_for_client_read(self) flags = FlagParser.initialize( auth_code=base64.b64encode(b'user:pass'), threaded=True, ) flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), bytes_(PLUGIN_PROXY_AUTH), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=flags, ) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET http://abhinavsingh.com HTTP/1.1', b'Host: abhinavsingh.com', CRLF, ]) await self.protocol_handler._run_once() self.assertEqual( self.protocol_handler.work.buffer[0], PROXY_AUTH_FAILED_RESPONSE_PKT, )
def test_enable_devtools( self, mock_listener: mock.Mock, mock_executor_pool: mock.Mock, mock_acceptor_pool: mock.Mock, mock_event_manager: mock.Mock, mock_parse_args: mock.Mock, mock_load_plugins: mock.Mock, mock_sleep: mock.Mock, ) -> None: mock_sleep.side_effect = KeyboardInterrupt() mock_args = mock_parse_args.return_value self.mock_default_args(mock_args) mock_args.enable_devtools = True mock_args.local_executor = 0 main(enable_devtools=True, local_executor=0) mock_load_plugins.assert_called() self.assertEqual( mock_load_plugins.call_args_list[0][0][0], [ bytes_(PLUGIN_DEVTOOLS_PROTOCOL), bytes_(PLUGIN_WEB_SERVER), bytes_(PLUGIN_HTTP_PROXY), ], ) mock_parse_args.assert_called_once() # Currently --enable-devtools flag alone doesn't enable eventing core mock_event_manager.assert_not_called() if _env_threadless_compliant(): mock_executor_pool.assert_called_once() mock_executor_pool.return_value.setup.assert_called_once() mock_acceptor_pool.assert_called_once() mock_acceptor_pool.return_value.setup.assert_called_once() mock_listener.return_value.setup.assert_called_once()
def test_modify_post_data_plugin(self, mock_server_conn: mock.Mock) -> None: original = b'{"key": "value"}' modified = b'{"key": "modified"}' self._conn.recv.return_value = build_http_request( b'POST', b'http://httpbin.org/post', headers={ b'Host': b'httpbin.org', b'Content-Type': b'application/x-www-form-urlencoded', b'Content-Length': bytes_(len(original)), }, body=original) self.mock_selector.return_value.select.side_effect = [ [(selectors.SelectorKey(fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ)], ] self.protocol_handler.run_once() mock_server_conn.assert_called_with('httpbin.org', DEFAULT_HTTP_PORT) mock_server_conn.return_value.queue.assert_called_with( build_http_request(b'POST', b'/post', headers={ b'Host': b'httpbin.org', b'Content-Length': bytes_(len(modified)), b'Content-Type': b'application/json', b'Via': b'1.1 %s' % PROXY_AGENT_HEADER_VALUE, }, body=modified))
def _setUp(self, mocker: MockerFixture) -> None: self.mock_fromfd = mocker.patch('socket.fromfd') self.mock_selector = mocker.patch('selectors.DefaultSelector') self.fileno = 10 self._addr = ('127.0.0.1', 54382) self._conn = self.mock_fromfd.return_value # Setup a static directory self.static_server_dir = os.path.join(tempfile.gettempdir(), 'static') self.index_file_path = os.path.join( self.static_server_dir, 'index.html', ) self.html_file_content = b'''<html><head></head><body><h1>Proxy.py Testing</h1></body></html>''' os.makedirs(self.static_server_dir, exist_ok=True) with open(self.index_file_path, 'wb') as f: f.write(self.html_file_content) # flags = FlagParser.initialize( enable_static_server=True, static_server_dir=self.static_server_dir, threaded=True, ) flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=flags, ) self.protocol_handler.initialize()
def test_authenticated_proxy_http_tunnel(self, mock_server_connection: mock.Mock, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: server = mock_server_connection.return_value server.connect.return_value = True server.buffer_size.return_value = 0 self._conn = mock_fromfd.return_value self.mock_selector_for_client_read_read_server_write( mock_selector, server) flags = Proxy.initialize(auth_code=base64.b64encode(b'user:pass')) flags.plugins = Proxy.load_plugins( [bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER)]) self.protocol_handler = HttpProtocolHandler(TcpClientConnection( self._conn, self._addr), flags=flags) self.protocol_handler.initialize() assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'CONNECT localhost:%d HTTP/1.1' % self.http_server_port, b'Host: localhost:%d' % self.http_server_port, b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Proxy-Connection: Keep-Alive', b'Proxy-Authorization: Basic dXNlcjpwYXNz', CRLF ]) self.assert_tunnel_response(mock_server_connection, server) self.protocol_handler.client.flush() self.assert_data_queued_to_server(server) self.protocol_handler.run_once() server.flush.assert_called_once()
def test_default_web_server_returns_404( self, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: self._conn = mock_fromfd.return_value mock_selector.return_value.select.return_value = [( selectors.SelectorKey( fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ), ] flags = Proxy.initialize() flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( TcpClientConnection(self._conn, self._addr), flags=flags) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET /hello HTTP/1.1', CRLF, ]) self.protocol_handler.run_once() self.assertEqual( self.protocol_handler.request.state, httpParserStates.COMPLETE) self.assertEqual( self.protocol_handler.client.buffer[0], HttpWebServerPlugin.DEFAULT_404_RESPONSE)
def test_static_web_server_serves( self, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: # Setup a static directory static_server_dir = os.path.join(tempfile.gettempdir(), 'static') index_file_path = os.path.join(static_server_dir, 'index.html') html_file_content = b'''<html><head></head><body><h1>Proxy.py Testing</h1></body></html>''' os.makedirs(static_server_dir, exist_ok=True) with open(index_file_path, 'wb') as f: f.write(html_file_content) self._conn = mock_fromfd.return_value self._conn.recv.return_value = build_http_request( b'GET', b'/index.html') mock_selector.return_value.select.side_effect = [ [(selectors.SelectorKey( fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ)], [(selectors.SelectorKey( fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_WRITE, data=None), selectors.EVENT_WRITE)], ] flags = Proxy.initialize( enable_static_server=True, static_server_dir=static_server_dir) flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( TcpClientConnection(self._conn, self._addr), flags=flags) self.protocol_handler.initialize() self.protocol_handler.run_once() self.protocol_handler.run_once() self.assertEqual(mock_selector.return_value.select.call_count, 2) self.assertEqual(self._conn.send.call_count, 1) encoded_html_file_content = gzip.compress(html_file_content) self.assertEqual(self._conn.send.call_args[0][0], build_http_response( 200, reason=b'OK', headers={ b'Content-Type': b'text/html', b'Cache-Control': b'max-age=86400', b'Content-Encoding': b'gzip', b'Connection': b'close', b'Content-Length': bytes_(len(encoded_html_file_content)), }, body=encoded_html_file_content ))
def test_valid_ipv6_in_request_line(self) -> None: self.parser.parse( bytes_( 'CONNECT [2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF]:443 HTTP/1.1\r\n', ), ) self.assertTrue(self.parser.is_https_tunnel) self.assertEqual( self.parser.host, bytes_('[2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF]', ), ) self.assertEqual(self.parser.port, 443)
def setUp(self, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: self.fileno = 10 self._addr = ('127.0.0.1', 54382) self._conn = mock_fromfd.return_value self.mock_selector = mock_selector self.flags = Proxy.initialize() self.flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( TcpClientConnection(self._conn, self._addr), flags=self.flags) self.protocol_handler.initialize()
def init_and_make_pac_file_request(self, pac_file: str) -> None: flags = Proxy.initialize(pac_file=pac_file) flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), bytes_(PLUGIN_PAC_FILE), ]) self.protocol_handler = HttpProtocolHandler( TcpClientConnection(self._conn, self._addr), flags=flags) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET / HTTP/1.1', CRLF, ])
async def test_authenticated_proxy_http_get(self) -> None: self._conn = self.mock_fromfd.return_value mock_selector_for_client_read(self) server = self.mock_server_connection.return_value server.connect.return_value = True server.buffer_size.return_value = 0 flags = FlagParser.initialize( auth_code=base64.b64encode(b'user:pass'), threaded=True, ) flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=flags, ) self.protocol_handler.initialize() assert self.http_server_port is not None self._conn.recv.return_value = b'GET http://localhost:%d HTTP/1.1' % self.http_server_port await self.protocol_handler._run_once() self.assertEqual( self.protocol_handler.request.state, httpParserStates.INITIALIZED, ) self._conn.recv.return_value = CRLF await self.protocol_handler._run_once() self.assertEqual( self.protocol_handler.request.state, httpParserStates.LINE_RCVD, ) assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Host: localhost:%d' % self.http_server_port, b'Accept: */*', httpHeaders.PROXY_CONNECTION + b': Keep-Alive', httpHeaders.PROXY_AUTHORIZATION + b': Basic dXNlcjpwYXNz', CRLF, ]) await self.assert_data_queued(server)
def test_proposed_rest_api_plugin(self, mock_server_conn: mock.Mock) -> None: path = b'/v1/users/' self._conn.recv.return_value = build_http_request( b'GET', b'http://%s%s' % (ProposedRestApiPlugin.API_SERVER, path), headers={ b'Host': ProposedRestApiPlugin.API_SERVER, }) self.mock_selector.return_value.select.side_effect = [ [(selectors.SelectorKey(fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ)], ] self.protocol_handler.run_once() mock_server_conn.assert_not_called() self.assertEqual( self.protocol_handler.client.buffer[0].tobytes(), build_http_response( httpStatusCodes.OK, reason=b'OK', headers={b'Content-Type': b'application/json'}, body=bytes_( json.dumps(ProposedRestApiPlugin.REST_API_SPEC[path]))))
def test_http_get(self, mock_server_connection: mock.Mock) -> None: server = mock_server_connection.return_value server.connect.return_value = True server.buffer_size.return_value = 0 self.mock_selector_for_client_read_read_server_write( self.mock_selector, server) # Send request line assert self.http_server_port is not None self._conn.recv.return_value = (b'GET http://localhost:%d HTTP/1.1' % self.http_server_port) + CRLF self.protocol_handler.run_once() self.assertEqual(self.protocol_handler.request.state, httpParserStates.LINE_RCVD) self.assertNotEqual(self.protocol_handler.request.state, httpParserStates.COMPLETE) # Send headers and blank line, thus completing HTTP request assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Host: localhost:%d' % self.http_server_port, b'Accept: */*', b'Proxy-Connection: Keep-Alive', CRLF ]) self.assert_data_queued(mock_server_connection, server) self.protocol_handler.run_once() server.flush.assert_called_once()
def _setUp(self, mocker: MockerFixture) -> None: self.mock_fromfd = mocker.patch('socket.fromfd') self.mock_selector = mocker.patch('selectors.DefaultSelector') self.fileno = 10 self._addr = ('127.0.0.1', 54382) self._conn = self.mock_fromfd.return_value self.flags = FlagParser.initialize(threaded=True) self.flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=self.flags, ) self.protocol_handler.initialize()
def assert_data_queued(self, mock_server_connection: mock.Mock, server: mock.Mock) -> None: self.protocol_handler.run_once() self.assertEqual(self.protocol_handler.request.state, httpParserStates.COMPLETE) mock_server_connection.assert_called_once() server.connect.assert_called_once() server.closed = False assert self.http_server_port is not None pkt = CRLF.join([ b'GET / HTTP/1.1', b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Host: localhost:%d' % self.http_server_port, b'Accept: */*', b'Via: 1.1 proxy.py v%s' % bytes_(__version__), CRLF ]) server.queue.assert_called_once_with(pkt) server.buffer_size.return_value = len(pkt)
def test_unique_plugin_from_bytes(self) -> None: self.flags = Proxy.initialize([], plugins=[ bytes_(PLUGIN_HTTP_PROXY), ]) self.assert_plugins({'HttpProtocolHandlerPlugin': [ HttpProxyPlugin, ]})
def handle_upstream_chunk(self, chunk: memoryview) -> memoryview: self.response.parse(chunk.tobytes()) if self.response.state == httpParserStates.COMPLETE: self.handle_response_data() new_content_length = len(self.response.body) bytes_header_name = b'content-length' self.response.add_header(bytes_header_name, bytes_(new_content_length)) self.client.queue(memoryview(self.response.build_response())) return memoryview(b'')
def test_authenticated_proxy_http_get(self, mock_server_connection: mock.Mock, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: self._conn = mock_fromfd.return_value self.mock_selector_for_client_read(mock_selector) server = mock_server_connection.return_value server.connect.return_value = True server.buffer_size.return_value = 0 flags = Proxy.initialize(auth_code=base64.b64encode(b'user:pass')) flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler(TcpClientConnection( self._conn, self._addr), flags=flags) self.protocol_handler.initialize() assert self.http_server_port is not None self._conn.recv.return_value = b'GET http://localhost:%d HTTP/1.1' % self.http_server_port self.protocol_handler.run_once() self.assertEqual(self.protocol_handler.request.state, httpParserStates.INITIALIZED) self._conn.recv.return_value = CRLF self.protocol_handler.run_once() self.assertEqual(self.protocol_handler.request.state, httpParserStates.LINE_RCVD) assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Host: localhost:%d' % self.http_server_port, b'Accept: */*', b'Proxy-Connection: Keep-Alive', b'Proxy-Authorization: Basic dXNlcjpwYXNz', CRLF ]) self.assert_data_queued(mock_server_connection, server)
def test_proxy_authentication_failed(self, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: self._conn = mock_fromfd.return_value self.mock_selector_for_client_read(mock_selector) flags = Proxy.initialize(auth_code=base64.b64encode(b'user:pass')) flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), bytes_(PLUGIN_PROXY_AUTH), ]) self.protocol_handler = HttpProtocolHandler(TcpClientConnection( self._conn, self._addr), flags=flags) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET http://abhinavsingh.com HTTP/1.1', b'Host: abhinavsingh.com', CRLF ]) self.protocol_handler.run_once() self.assertEqual(self.protocol_handler.client.buffer[0], ProxyAuthenticationFailed.RESPONSE_PKT)
def test_build_response_adds_content_length_header(self) -> None: body = b'Hello world!!!' self.assertEqual( build_http_response(200, reason=b'OK', protocol_version=b'HTTP/1.1', headers={b'key': b'value'}, body=body), CRLF.join([ b'HTTP/1.1 200 OK', b'key: value', b'Content-Length: ' + bytes_(len(body)), CRLF ]) + body)
def test_modify_post_data_plugin(self) -> None: original = b'{"key": "value"}' modified = b'{"key": "modified"}' self.client_ssl_connection.recv.return_value = build_http_request( b'POST', b'/', headers={ b'Host': b'uni.corn', b'Content-Type': b'application/x-www-form-urlencoded', b'Content-Length': bytes_(len(original)), }, body=original) self.protocol_handler.run_once() self.server.queue.assert_called_with( build_http_request(b'POST', b'/', headers={ b'Host': b'uni.corn', b'Content-Length': bytes_(len(modified)), b'Content-Type': b'application/json', }, body=modified))
def test_http_tunnel(self, mock_server_connection: mock.Mock) -> None: server = mock_server_connection.return_value server.connect.return_value = True def has_buffer() -> bool: return cast(bool, server.queue.called) server.has_buffer.side_effect = has_buffer self.mock_selector.return_value.select.side_effect = [ [ (selectors.SelectorKey(fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ), ], [ (selectors.SelectorKey(fileobj=self._conn, fd=self._conn.fileno, events=0, data=None), selectors.EVENT_WRITE), ], [ (selectors.SelectorKey(fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ), ], [ (selectors.SelectorKey(fileobj=server.connection, fd=server.connection.fileno, events=0, data=None), selectors.EVENT_WRITE), ], ] assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'CONNECT localhost:%d HTTP/1.1' % self.http_server_port, b'Host: localhost:%d' % self.http_server_port, b'User-Agent: proxy.py/%s' % bytes_(__version__), b'Proxy-Connection: Keep-Alive', CRLF ]) self.assert_tunnel_response(mock_server_connection, server) # Dispatch tunnel established response to client self.protocol_handler.run_once() self.assert_data_queued_to_server(server) self.protocol_handler.run_once() self.assertEqual(server.queue.call_count, 1) server.flush.assert_called_once()
def test_static_web_server_serves_404( self, mock_fromfd: mock.Mock, mock_selector: mock.Mock) -> None: self._conn = mock_fromfd.return_value self._conn.recv.return_value = build_http_request( b'GET', b'/not-found.html') mock_selector.return_value.select.side_effect = [ [(selectors.SelectorKey( fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_READ, data=None), selectors.EVENT_READ)], [(selectors.SelectorKey( fileobj=self._conn, fd=self._conn.fileno, events=selectors.EVENT_WRITE, data=None), selectors.EVENT_WRITE)], ] flags = Proxy.initialize(enable_static_server=True) flags.plugins = Proxy.load_plugins([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( TcpClientConnection(self._conn, self._addr), flags=flags) self.protocol_handler.initialize() self.protocol_handler.run_once() self.protocol_handler.run_once() self.assertEqual(mock_selector.return_value.select.call_count, 2) self.assertEqual(self._conn.send.call_count, 1) self.assertEqual(self._conn.send.call_args[0][0], HttpWebServerPlugin.DEFAULT_404_RESPONSE)
async def test_authenticated_proxy_http_tunnel(self) -> None: server = self.mock_server_connection.return_value server.connect.return_value = True server.buffer_size.return_value = 0 self._conn = self.mock_fromfd.return_value self.mock_selector_for_client_read_and_server_write(server) flags = FlagParser.initialize( auth_code=base64.b64encode(b'user:pass'), threaded=True, ) flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=flags, ) self.protocol_handler.initialize() assert self.http_server_port is not None self._conn.recv.return_value = CRLF.join([ b'CONNECT localhost:%d HTTP/1.1' % self.http_server_port, b'Host: localhost:%d' % self.http_server_port, b'User-Agent: proxy.py/%s' % bytes_(__version__), httpHeaders.PROXY_CONNECTION + b': Keep-Alive', httpHeaders.PROXY_AUTHORIZATION + b': Basic dXNlcjpwYXNz', CRLF, ]) await self.assert_tunnel_response(server) self.protocol_handler.work.flush() await self.assert_data_queued_to_server(server) await self.protocol_handler._run_once() server.flush.assert_called_once()
def test_entry_point( self, mock_listener_pool: mock.Mock, mock_executor_pool: mock.Mock, mock_acceptor_pool: mock.Mock, mock_event_manager: mock.Mock, mock_initialize: mock.Mock, mock_sleep: mock.Mock, mock_open: mock.Mock, mock_exists: mock.Mock, mock_remove: mock.Mock, ) -> None: pid_file = os.path.join(tempfile.gettempdir(), 'pid') mock_sleep.side_effect = KeyboardInterrupt() mock_initialize.return_value.unix_socket_path = None mock_initialize.return_value.local_executor = 0 mock_initialize.return_value.enable_events = False mock_initialize.return_value.pid_file = pid_file mock_initialize.return_value.port_file = None mock_initialize.return_value.enable_ssh_tunnel = False entry_point() mock_event_manager.assert_not_called() mock_listener_pool.assert_called_once_with( flags=mock_initialize.return_value, ) mock_executor_pool.assert_called_once_with( flags=mock_initialize.return_value, event_queue=None, executor_klass=RemoteFdExecutor, ) mock_acceptor_pool.assert_called_once_with( flags=mock_initialize.return_value, listeners=mock_listener_pool.return_value, executor_queues=mock_executor_pool.return_value.work_queues, executor_pids=mock_executor_pool.return_value.work_pids, executor_locks=mock_executor_pool.return_value.work_locks, event_queue=None, ) mock_acceptor_pool.return_value.setup.assert_called_once() mock_acceptor_pool.return_value.shutdown.assert_called_once() mock_listener_pool.return_value.shutdown.assert_called_once() mock_sleep.assert_called() mock_open.assert_called_with(pid_file, 'wb') mock_open.return_value.__enter__.return_value.write.assert_called_with( bytes_(os.getpid()), ) mock_exists.assert_called_with(pid_file) mock_remove.assert_called_with(pid_file)
async def test_default_web_server_returns_404(self) -> None: self._conn = self.mock_fromfd.return_value self.mock_selector.return_value.select.return_value = [ ( selectors.SelectorKey( fileobj=self._conn.fileno(), fd=self._conn.fileno(), events=selectors.EVENT_READ, data=None, ), selectors.EVENT_READ, ), ] flags = FlagParser.initialize(threaded=True) flags.plugins = Plugins.load([ bytes_(PLUGIN_HTTP_PROXY), bytes_(PLUGIN_WEB_SERVER), ]) self.protocol_handler = HttpProtocolHandler( HttpClientConnection(self._conn, self._addr), flags=flags, ) self.protocol_handler.initialize() self._conn.recv.return_value = CRLF.join([ b'GET /hello HTTP/1.1', CRLF, ]) await self.protocol_handler._run_once() self.assertEqual( self.protocol_handler.request.state, httpParserStates.COMPLETE, ) self.assertEqual( self.protocol_handler.work.buffer[0], NOT_FOUND_RESPONSE_PKT, )
async def test_static_web_server_serves(self) -> None: self._conn.recv.return_value = build_http_request( b'GET', b'/index.html', ) self.mock_selector.return_value.select.side_effect = [ [( selectors.SelectorKey( fileobj=self._conn.fileno(), fd=self._conn.fileno(), events=selectors.EVENT_READ, data=None, ), selectors.EVENT_READ, )], [( selectors.SelectorKey( fileobj=self._conn.fileno(), fd=self._conn.fileno(), events=selectors.EVENT_WRITE, data=None, ), selectors.EVENT_WRITE, )], ] await self.protocol_handler._run_once() await self.protocol_handler._run_once() self.assertEqual(self.mock_selector.return_value.select.call_count, 2) self.assertEqual(self._conn.send.call_count, 1) encoded_html_file_content = gzip.compress(self.html_file_content) # parse response and verify response = HttpParser(httpParserTypes.RESPONSE_PARSER) response.parse(self._conn.send.call_args[0][0]) self.assertEqual(response.code, b'200') self.assertEqual(response.header(b'content-type'), b'text/html') self.assertEqual(response.header(b'cache-control'), b'max-age=86400') self.assertEqual(response.header(b'content-encoding'), b'gzip') self.assertEqual(response.header(b'connection'), b'close') self.assertEqual( response.header(b'content-length'), bytes_(len(encoded_html_file_content)), ) assert response.body self.assertEqual( gzip.decompress(response.body), self.html_file_content, )
def assert_data_queued_to_server(self, server: mock.Mock) -> None: assert self.http_server_port is not None self.assertEqual(self._conn.send.call_args[0][0], HttpProxyPlugin.PROXY_TUNNEL_ESTABLISHED_RESPONSE_PKT) pkt = CRLF.join([ b'GET / HTTP/1.1', b'Host: localhost:%d' % self.http_server_port, b'User-Agent: proxy.py/%s' % bytes_(__version__), CRLF ]) self._conn.recv.return_value = pkt self.protocol_handler.run_once() server.queue.assert_called_once_with(pkt) server.buffer_size.return_value = len(pkt) server.flush.assert_not_called()
def handle_client_request(self, request: HttpParser) -> Optional[HttpParser]: if request.method == httpMethods.GET: path_str = text_(request.path) downloaded = 0 match = re.search('(?:^|\\?|&)downloaded=(\\d+)(?:&|$)', path_str) if match: downloaded = int(match.group(1)) match = re.search('(?:^|\\?|&)uploaded=(\\d+)(?:&|$)', path_str) if match: uploaded = int(downloaded * 1.2 if downloaded > 0 else int(match.group(1)) * 1.2) path_str = path_str[:match.start(1)] + str( uploaded) + path_str[match.end(1):] request.path = bytes_(path_str) return request