proxy.http.proxy package#

Submodules#

Module contents#

proxy.py#

⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on Network monitoring, controls & Application development, testing, debugging.

copyright
  1. 2013-present by Abhinav Singh and contributors.

license

BSD, see LICENSE for more details.

class proxy.http.proxy.HttpProxyBasePlugin(uid: str, flags: argparse.Namespace, client: proxy.http.connection.HttpClientConnection, event_queue: proxy.core.event.queue.EventQueue, upstream_conn_pool: Optional[UpstreamConnectionPool] = None)[source]#

Bases: proxy.http.descriptors.DescriptorsHandlerMixin, abc.ABC

Base HttpProxyPlugin Plugin class.

Implement various lifecycle event methods to customize behavior.

_abc_impl = <_abc._abc_data object>#
before_upstream_connection(request: proxy.http.parser.parser.HttpParser) Optional[proxy.http.parser.parser.HttpParser][source]#

Handler called just before Proxy upstream connection is established.

Return optionally modified request object. If None is returned, upstream connection won’t be established.

Raise HttpRequestRejected or HttpProtocolException directly to drop the connection.

do_intercept(_request: proxy.http.parser.parser.HttpParser) bool[source]#

By default returns True (only) when necessary flags for TLS interception are passed.

When TLS interception is enabled, plugins can still disable TLS interception by returning False explicitly. This hook will allow you to run proxy instance with TLS interception flags BUT only conditionally enable interception for certain requests.

handle_client_data(raw: memoryview) Optional[memoryview][source]#

Handler called in special scenarios when an upstream server connection is never established.

Essentially, if you return None from within before_upstream_connection, be prepared to handle_client_data and not handle_client_request.

Only called after initial request from client has been received.

Raise HttpRequestRejected to tear down the connection Return None to drop the connection

handle_client_request(request: proxy.http.parser.parser.HttpParser) Optional[proxy.http.parser.parser.HttpParser][source]#

Handler called before dispatching client request to upstream.

Note: For pipelined (keep-alive) connections, this handler can be called multiple times, for each request sent to upstream.

Note: If TLS interception is enabled, this handler can be called multiple times if client exchanges multiple requests over same SSL session.

Return optionally modified request object to dispatch to upstream. Return None to drop the request data, e.g. in case a response has already been queued. Raise HttpRequestRejected or HttpProtocolException directly to tear down the connection with client.

handle_upstream_chunk(chunk: memoryview) Optional[memoryview][source]#

Handler called right after receiving raw response from upstream server.

For HTTPS connections, chunk will be encrypted unless TLS interception is also enabled.

Return None if you don’t want to sent this chunk to the client.

name() str[source]#

A unique name for your plugin.

Defaults to name of the class. This helps plugin developers to directly access a specific plugin by its name.

on_access_log(context: Dict[str, Any]) Optional[Dict[str, Any]][source]#

Use this method to override default access log format (see DEFAULT_HTTP_ACCESS_LOG_FORMAT and DEFAULT_HTTPS_ACCESS_LOG_FORMAT) and to add/update/modify/delete context for next plugin.on_access_log invocation.

This is specially useful if a plugins want to provide extra context in the access log which may not available within other plugins’ context or even in proxy.py core.

Returns Log context or None. If plugin chooses to access log, they ideally must return None to prevent other plugin.on_access_log invocation.

on_upstream_connection_close() None[source]#

Handler called right after upstream connection has been closed.

resolve_dns(host: str, port: int) Tuple[Optional[str], Optional[HostPort]][source]#

Resolve upstream server host to an IP address.

Optionally also override the source address to use for connection with upstream server.

For upstream IP: Return None to use default resolver available to the system. Return IP address as string to use your custom resolver.

For source address: Return None to use default source address Return 2-tuple representing (host, port) to use as source address

class proxy.http.proxy.HttpProxyPlugin(*args: Any, **kwargs: Any)[source]#

Bases: proxy.http.plugin.HttpProtocolHandlerPlugin

HttpProtocolHandler plugin which implements HttpProxy specifications.

_abc_impl = <_abc._abc_data object>#
_close_and_release() bool[source]#
access_log(log_attrs: Dict[str, Any]) None[source]#
connect_upstream() None[source]#
emit_request_complete() None[source]#
emit_response_chunk_received(chunk_size: int) None[source]#
emit_response_complete() None[source]#
emit_response_events(chunk_size: int) None[source]#
emit_response_headers_complete() None[source]#
gen_ca_signed_certificate(cert_file_path: str, certificate: Dict[str, Any]) None[source]#

CA signing key (default) is used for generating a public key for common_name, if one already doesn’t exist. Using generated public key a CSR request is generated, which is then signed by CA key and secret. Again this process only happen if signed certificate doesn’t already exist.

returns signed certificate path.

generate_upstream_certificate(certificate: Dict[str, Any]) str[source]#
static generated_cert_file_path(ca_cert_dir: str, host: str) str[source]#
async get_descriptors() Tuple[List[int], List[int]][source]#

Implementations must return a list of descriptions that they wish to read from and write into.

handle_pipeline_response(raw: memoryview) None[source]#
intercept() Union[socket.socket, bool][source]#
lock = <unlocked _thread.lock object>#
on_client_connection_close() None[source]#

Client connection shutdown has been received, flush has been called, perform any cleanup work here.

on_client_data(raw: memoryview) None[source]#

Called only after original request has been completely received.

on_request_complete() Union[socket.socket, bool][source]#

Called right after client request parser has reached COMPLETE state.

on_response_chunk(chunk: List[memoryview]) List[memoryview][source]#

Handle data chunks as received from the server.

Return optionally modified chunk to return back to client.

static protocols() List[int][source]#
async read_from_descriptors(r: List[int]) bool[source]#

Implementations must now read data over the socket.

wrap_client() bool[source]#
wrap_server() bool[source]#
async write_to_descriptors(w: List[int]) bool[source]#

Implementations must now write/flush data over the socket.

Note that buffer management is in-build into the connection classes. Hence implementations MUST call flush() here, to send any buffered data over the socket.