Server and Client¶
The hface.server
and hface.client
modules provide ready-to-use server and client implementations.
The modules are a Python alternative to the command-line interface. They offer a high-level facade to the connection layer.
Both the server and the client are asynchronous.
The examples here use asyncio asyncio.run()
, but Trio is supported too (thanks to AnyIO).
ASGI server example¶
hface.server.ASGIServer
can run a server with an ASGI application:
import asyncio
from hface.server import ASGIServer, Endpoint
from hface.server.examples.hello import application
async def main():
server = ASGIServer(application)
server.tls_config.certfile = "certs/cert.pem"
server.tls_config.keyfile = "certs/key.pem"
endpoint = Endpoint("https", "localhost", 5443)
await server.run([endpoint])
if __name__ == "__main__":
asyncio.run(main())
(The example should run as it is. It is available in examples/server.py)
Proxy server example¶
hface.server.ProxyServer
can run an HTTP proxy:
import asyncio
from hface.server import Endpoint, ProxyServer
async def main():
server = ProxyServer()
server.tls_config.certfile = "certs/cert.pem"
server.tls_config.keyfile = "certs/key.pem"
endpoint = Endpoint("https", "localhost", 6443)
await server.run([endpoint])
if __name__ == "__main__":
asyncio.run(main())
(The example should run as it is. It is available in examples/proxy_server.py)
HTTP client example¶
The hface.client.Client
can be used to issue an HTTP request:
import asyncio
from hface.client import Client, Request
async def main():
client = Client()
client.tls_config.cafile = "certs/cacert.pem"
async with client.session() as session:
request = Request("GET", "https://localhost:5443/")
response = await session.dispatch(request)
print(response.status)
print(response.content.decode())
if __name__ == "__main__":
asyncio.run(main())
(The example should run as it is. It is available in examples/client.py)
Async context manager Client.session()
must be entered to get ClientSession
.
The ClientSession.dispatch()
makes HTTP requests.
The use of the context manager ensures that no background tasks are left running (background tasks are needed to maintain HTTP/2 and HTTP/3 connections).
The client has builtin support for HTTP proxies (in the tunneling mode only).
Proxy client example¶
It may be desired to tunnel non-HTTP traffic through an HTTP proxy.
In such cases, it is possible to use directly hface.client.ProxyClient
:
import asyncio
from anyio import EndOfStream
from hface.client import ProxyClient
async def main():
proxy_client = ProxyClient("https://localhost:6443")
proxy_client.tls_config.cafile = "certs/cacert.pem"
async with proxy_client.session() as session:
stream = await session.connect_tcp_tls(("localhost", 5443))
await stream.send(
b"GET / HTTP/1.1\r\n"
b"Host: localhost\r\n"
b"Connection: close\r\n"
b"\r\n"
)
while True:
try:
chunk = await stream.receive()
except EndOfStream:
break
print(chunk.decode(), end="")
if __name__ == "__main__":
asyncio.run(main())
(The example should run as it is. It is available in examples/proxy_client.py)
Async context manager ProxyClient.session()
must be used to get ProxyClientSession
.
This class implements ClientNetworking
, so it can be used to open network connections.
Server API¶
ASGI server class¶
- class hface.server.ASGIServer(app)¶
HTTP server with an ASGI application
- tls_config: ServerTLSConfig¶
TLS certificate for the server.
Empty by default, must be configured to listen at
https://
endpoints.
- protocol: ServerProtocol = 'all'¶
Protocol or protocols to listen at.
- http1_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/1 implementation
- http2_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/2 implementation
- http3_factory: HTTPOverQUICServerFactory¶
Sans-IO HTTP/3 implementation
Proxy server class¶
- class hface.server.ProxyServer¶
- tls_config: ServerTLSConfig¶
TLS certificate for the server.
Empty by default, must be configured to listen at
https://
endpoints.
- protocol: ServerProtocol = 'all'¶
Protocol or protocols to listen at.
- http1_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/1 implementation
- http2_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/2 implementation
- http3_factory: HTTPOverQUICServerFactory¶
Sans-IO HTTP/3 implementation
Server models¶
- class hface.server.Endpoint(scheme, host, port)¶
An endpoing where a server can listen.
- scheme: str¶
Either
"http"
or"https"
.
- host: str¶
A hostname or an IP address
- port: int¶
A port number
- classmethod parse(value)¶
Parse an endpoint from a string.
- Parameters
value (str) – string value
- Returns
a new instance
- Return type
- property tls: bool¶
Whether to use TLS
- property address: Tuple[str, int]¶
A tuple with a host and a port
- class hface.server.ServerProtocol(value)¶
Specifies for what connections a server should listen.
- ALL = 'all'¶
Listen for all HTTP versions.
- TCP = 'tcp'¶
Listen for HTTP/1 and HTTP/2 connections.
- HTTP1 = 'http1'¶
Listen for HTTP/1 connections only.
- HTTP2 = 'http2'¶
Listen for HTTP/2 connections only.
- HTTP3 = 'http3'¶
Listen for HTTP/3 connections only.
Client API¶
Client class¶
- class hface.client.Client¶
An HTTP client
Supports HTTP/1, HTTP/2, and HTTP/3. Optionally tunnels traffic through an HTTP proxy.
Client instances have no state. The
Client.session()
method must be used to openClientSession
to make HTTP requests.- tls_config: ClientTLSConfig¶
TLS configuration for the client.
- protocol: ClientProtocol = 'tcp'¶
A protocol used to open connections.
- proxy_protocol: ClientProtocol = 'tcp'¶
A protocol used to open connections to the proxy server (if set)
- http1_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/1 implementation
- http2_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/2 implementation
- http3_factory: HTTPOverQUICClientFactory¶
Sans-IO HTTP/3 implementation
- async with session()¶
Start a new client session.
- Return type
- class hface.client.ClientSession(*, http_opener, task_group)¶
Active client session that can be used to issue HTTP requests.
Maintains a pool of HTTP connections that can be used to
dispatch()
request.Use a
Client
to create instances of this class.- Parameters
http_opener (HTTPOpener) – Defines how to open new connections.
task_group (TaskGroup) – AnyIO task group for maintaining HTTP connections.
- await aclose()¶
Close all connections.
Proxy class¶
- class hface.client.ProxyClient(origin)¶
A client that tunnels traffic through HTTP proxies
This client sends CONNECT requests to an HTTP proxy to establish tunnels. The established tunnels can be used to transfer any TCP traffic, it is not limited to HTTP.
Supports HTTP/1, HTTP/2, and HTTP/3 proxies in the tunneling mode.
Instances of this class have no state, the
session()
must be used to establishProxyClientSession
.- Parameters
origin (Origin) – Proxy server to use
- tls_config: ClientTLSConfig¶
TLS configuration for the client.
- protocol: ClientProtocol = 'tcp'¶
A protocol used to open connections.
- http1_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/1 implementation
- http2_factory: HTTPOverTCPFactory¶
Sans-IO HTTP/2 implementation
- http3_factory: HTTPOverQUICClientFactory¶
Sans-IO HTTP/3 implementation
- async with session()¶
Establish a new session with the proxy.
- Return type
- class hface.client.ProxyClientSession(origin, *, http_opener, task_group)¶
An active session with an HTTP proxy.
Maintains pool of connections to the proxy (for HTTP/2 and HTTP/3 proxies the pool will not have more than one connection).
This class implements
ClientNetworking
, so it can be used to open new HTTP connections.Use a
ProxyClient
to create instances of this class.- Parameters
origin (Origin) – Proxy server
http_opener (HTTPOpener) – Defines how to open new connections.
task_group (anyio.abc.TaskGroup) – AnyIO task group for maintaining HTTP connections.
- await aclose()¶
Close all connections.
- await connect_tcp(address)¶
Create a TCP-like stream connected to the given address.
- Return type
Client models¶
- class hface.client.Request(method, url, *, headers=None, content=None)¶
HTTP request
- Parameters
method (str) – HTTP method
url (URL) – URL (either a string or an isntance)
headers (Sequence[Tuple[bytes, bytes]]) – HTTP headers (will be normalized to lowecase)
content (bytes) – Request body to send
- method: str¶
HTTP method
- headers: Sequence[Tuple[bytes, bytes]]¶
HTTP headers
- content: bytes¶
Request body to send
- property protocol_headers: Sequence[Tuple[bytes, bytes]]¶
HTTP headers including the pseudo one.
- property pseudo_headers: Sequence[Tuple[bytes, bytes]]¶
Pseudo headers (
":method"
,":scheme"
,":authority"
,":path"
)
- class hface.client.Response(status=200, *, headers=None, content=b'')¶
HTTP response
- Parameters
status (int) – HTTP status
headers (Sequence[Tuple[bytes, bytes]]) – HTTP headers
content (bytes) – Received HTTP body
- status: int¶
HTTP status
- headers: Sequence[Tuple[bytes, bytes]]¶
HTTP headers
- content: bytes¶
Received HTTP body
- property protocol_headers: Sequence[Tuple[bytes, bytes]]¶
HTTP headers including the pseudo one.
- property pseudo_headers: Sequence[Tuple[bytes, bytes]]¶
Pseudo headers (
":status"
)
- class hface.client.ClientProtocol(value)¶
Specifies for how to open connections to the server.
- TCP = 'tcp'¶
Open TCP connections, use ALPN to choose beteween HTTP/1 and HTTP/2
- HTTP1 = 'http1'¶
Open HTTP/1 connections
- HTTP2 = 'http2'¶
Open HTTP/2 connections
- HTTP3 = 'http3'¶
Open HTTP/3 connections. Use QUIC instead of TCP.
- class hface.client.URL(scheme, host, port, path='/')¶
- scheme: str¶
Either
"http"
or"https"
.
- host: str¶
A hostname or an IP address
- port: int¶
A port number
- path: str¶
Path compoment
- classmethod parse(value, default_scheme='http')¶
Parse an URL from a string.
- Parameters
value (str) – string value
default_scheme (str) – default scheme
- Returns
a new instance
- Return type
- property authority: str¶
Authority part of this URL (host + port if non-default)
- class hface.client.Origin(scheme, host, port)¶
HTTP origin server.
- scheme: str¶
Either
"http"
or"https"
.
- host: str¶
A hostname or an IP address
- port: int¶
A port number
- classmethod parse(value, *, default_scheme='http')¶
Parse an origin from a string.
- Parameters
value (str) – string value
default_scheme (str) – default scheme
- Returns
a new instance
- Return type
- property tls: bool¶
Whether to use TLS
- property address: Tuple[str, int]¶
A tuple with a host and a port