import httpx import tractor import trio log = tractor.log.get_console_log( _root_name='my_app', name='server_thingy', ) @tractor.context async def proxy_request( ctx: tractor.Context, address: str, ): log.info( 'Rxed client request\n' f'{address}\n' ) async with httpx.AsyncClient() as client: await ctx.started() # signal the remote task has started its client log.info( 'Opened `httpx` client..' ) resp: httpx.Response = await client.get(address) # do the proxied request, get response. log.info( 'Got response..\n' f'{resp}\n' ) # only breaking this up to clarify that you didn't have to only return a single result you could have opened # a long lived stream to avoid task spawning overhead in this service actor.. but more on that later.. # # NOTEs, cast to `str` here since we can't serialize the # response type for the wire directly, at least no without # a custom `msgspec.Decoder`!! return str(resp) # # ^TODO, various typed msging options: # -[ ] try returning just the `resp` verbatim => should raise # an MTE # -[ ] try defining a custom `Response` msg to proxy the orig # types fields and/or a decoder to serialize it? async def main(): # enable console logging for our custom app's logger tractor.log.get_console_log( level='info', _root_name='my_app', name='server_thingy', ) # since run as a script this will likely be `__main__` # so instead we want to just use our module name.. this_mod: str = 'server' async with tractor.open_root_actor( name='web_proxier', registry_addrs=[('127.0.0.1', 1616)], enable_modules=[this_mod], loglevel='info', ): # just block waiting for a peer actor to connect and open an RPC context using the above # proxy endpoint. log.info( 'proxy server up bby!\n' 'waiting to serve some requests..\n' ) await trio.sleep_forever() if __name__ == '__main__': trio.run(main)