Add a super naive multi-host-capable web-req proxier for @jc211
parent
5c2e972315
commit
61cd95d883
|
@ -0,0 +1,50 @@
|
|||
import tractor
|
||||
import trio
|
||||
|
||||
|
||||
log = tractor.log.get_console_log(
|
||||
_root_name='my_app',
|
||||
name='client',
|
||||
)
|
||||
|
||||
|
||||
async def client_main():
|
||||
|
||||
# enable console logging for our custom app's logger
|
||||
tractor.log.get_console_log(
|
||||
level='info',
|
||||
_root_name='my_app',
|
||||
name='client',
|
||||
)
|
||||
|
||||
# presuming you can get a ref to the target server RPC-ctx func
|
||||
from server import proxy_request
|
||||
|
||||
async with (
|
||||
tractor.open_root_actor(
|
||||
name='web_requester',
|
||||
registry_addrs=[('127.0.0.1', 1616)],
|
||||
enable_modules=[], # since this isn't a service actor
|
||||
),
|
||||
|
||||
# use discovery api to find the server actor on your net
|
||||
# (NOTE, in which case the below registry addr would have to
|
||||
# be the public IP of that host!)
|
||||
tractor.find_actor(
|
||||
name='web_proxier',
|
||||
registry_addrs=[('127.0.0.1', 1616)],
|
||||
) as portal,
|
||||
|
||||
# open an RPC context with the remote actor, thus spawning
|
||||
# a new task implemented as the function defined in the
|
||||
# server code.
|
||||
portal.open_context(
|
||||
proxy_request,
|
||||
address='https://github.com',
|
||||
) as (ctx, first),
|
||||
):
|
||||
resp: dict = await ctx.result()
|
||||
print(resp)
|
||||
|
||||
|
||||
trio.run(client_main)
|
|
@ -0,0 +1,75 @@
|
|||
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)
|
Loading…
Reference in New Issue