diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/python/aiohttp/examples | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/python/aiohttp/examples')
24 files changed, 1441 insertions, 0 deletions
diff --git a/third_party/python/aiohttp/examples/background_tasks.py b/third_party/python/aiohttp/examples/background_tasks.py new file mode 100755 index 0000000000..2a1ec12afa --- /dev/null +++ b/third_party/python/aiohttp/examples/background_tasks.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +"""Example of aiohttp.web.Application.on_startup signal handler""" +import asyncio + +import aioredis + +from aiohttp import web + + +async def websocket_handler(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + request.app["websockets"].append(ws) + try: + async for msg in ws: + print(msg) + await asyncio.sleep(1) + finally: + request.app["websockets"].remove(ws) + return ws + + +async def on_shutdown(app): + for ws in app["websockets"]: + await ws.close(code=999, message="Server shutdown") + + +async def listen_to_redis(app): + try: + sub = await aioredis.create_redis(("localhost", 6379), loop=app.loop) + ch, *_ = await sub.subscribe("news") + async for msg in ch.iter(encoding="utf-8"): + # Forward message to all connected websockets: + for ws in app["websockets"]: + await ws.send_str(f"{ch.name}: {msg}") + print(f"message in {ch.name}: {msg}") + except asyncio.CancelledError: + pass + finally: + print("Cancel Redis listener: close connection...") + await sub.unsubscribe(ch.name) + await sub.quit() + print("Redis connection closed.") + + +async def start_background_tasks(app): + app["redis_listener"] = app.loop.create_task(listen_to_redis(app)) + + +async def cleanup_background_tasks(app): + print("cleanup background tasks...") + app["redis_listener"].cancel() + await app["redis_listener"] + + +def init(): + app = web.Application() + app["websockets"] = [] + app.router.add_get("/news", websocket_handler) + app.on_startup.append(start_background_tasks) + app.on_cleanup.append(cleanup_background_tasks) + app.on_shutdown.append(on_shutdown) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/cli_app.py b/third_party/python/aiohttp/examples/cli_app.py new file mode 100755 index 0000000000..9fbd3b7604 --- /dev/null +++ b/third_party/python/aiohttp/examples/cli_app.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +Example of serving an Application using the `aiohttp.web` CLI. + +Serve this app using:: + + $ python -m aiohttp.web -H localhost -P 8080 --repeat 10 cli_app:init \ + > "Hello World" + +Here ``--repeat`` & ``"Hello World"`` are application specific command-line +arguments. `aiohttp.web` only parses & consumes the command-line arguments it +needs (i.e. ``-H``, ``-P`` & ``entry-func``) and passes on any additional +arguments to the `cli_app:init` function for processing. +""" + +from argparse import ArgumentParser + +from aiohttp import web + + +def display_message(req): + args = req.app["args"] + text = "\n".join([args.message] * args.repeat) + return web.Response(text=text) + + +def init(argv): + arg_parser = ArgumentParser( + prog="aiohttp.web ...", description="Application CLI", add_help=False + ) + + # Positional argument + arg_parser.add_argument("message", help="message to print") + + # Optional argument + arg_parser.add_argument( + "--repeat", help="number of times to repeat message", type=int, default="1" + ) + + # Avoid conflict with -h from `aiohttp.web` CLI parser + arg_parser.add_argument( + "--app-help", help="show this message and exit", action="help" + ) + + args = arg_parser.parse_args(argv) + + app = web.Application() + app["args"] = args + app.router.add_get("/", display_message) + + return app diff --git a/third_party/python/aiohttp/examples/client_auth.py b/third_party/python/aiohttp/examples/client_auth.py new file mode 100755 index 0000000000..6513de20e5 --- /dev/null +++ b/third_party/python/aiohttp/examples/client_auth.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import asyncio + +import aiohttp + + +async def fetch(session): + print("Query http://httpbin.org/basic-auth/andrew/password") + async with session.get("http://httpbin.org/basic-auth/andrew/password") as resp: + print(resp.status) + body = await resp.text() + print(body) + + +async def go(loop): + async with aiohttp.ClientSession( + auth=aiohttp.BasicAuth("andrew", "password"), loop=loop + ) as session: + await fetch(session) + + +loop = asyncio.get_event_loop() +loop.run_until_complete(go(loop)) diff --git a/third_party/python/aiohttp/examples/client_json.py b/third_party/python/aiohttp/examples/client_json.py new file mode 100755 index 0000000000..e54edeaddb --- /dev/null +++ b/third_party/python/aiohttp/examples/client_json.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import asyncio + +import aiohttp + + +async def fetch(session): + print("Query http://httpbin.org/get") + async with session.get("http://httpbin.org/get") as resp: + print(resp.status) + data = await resp.json() + print(data) + + +async def go(loop): + async with aiohttp.ClientSession(loop=loop) as session: + await fetch(session) + + +loop = asyncio.get_event_loop() +loop.run_until_complete(go(loop)) +loop.close() diff --git a/third_party/python/aiohttp/examples/client_ws.py b/third_party/python/aiohttp/examples/client_ws.py new file mode 100755 index 0000000000..ec48eccc9a --- /dev/null +++ b/third_party/python/aiohttp/examples/client_ws.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""websocket cmd client for wssrv.py example.""" +import argparse +import asyncio +import signal +import sys + +import aiohttp + + +async def start_client(loop, url): + name = input("Please enter your name: ") + + # input reader + def stdin_callback(): + line = sys.stdin.buffer.readline().decode("utf-8") + if not line: + loop.stop() + else: + ws.send_str(name + ": " + line) + + loop.add_reader(sys.stdin.fileno(), stdin_callback) + + async def dispatch(): + while True: + msg = await ws.receive() + + if msg.type == aiohttp.WSMsgType.TEXT: + print("Text: ", msg.data.strip()) + elif msg.type == aiohttp.WSMsgType.BINARY: + print("Binary: ", msg.data) + elif msg.type == aiohttp.WSMsgType.PING: + ws.pong() + elif msg.type == aiohttp.WSMsgType.PONG: + print("Pong received") + else: + if msg.type == aiohttp.WSMsgType.CLOSE: + await ws.close() + elif msg.type == aiohttp.WSMsgType.ERROR: + print("Error during receive %s" % ws.exception()) + elif msg.type == aiohttp.WSMsgType.CLOSED: + pass + + break + + # send request + async with aiohttp.ws_connect(url, autoclose=False, autoping=False) as ws: + await dispatch() + + +ARGS = argparse.ArgumentParser( + description="websocket console client for wssrv.py example." +) +ARGS.add_argument( + "--host", action="store", dest="host", default="127.0.0.1", help="Host name" +) +ARGS.add_argument( + "--port", action="store", dest="port", default=8080, type=int, help="Port number" +) + +if __name__ == "__main__": + args = ARGS.parse_args() + if ":" in args.host: + args.host, port = args.host.split(":", 1) + args.port = int(port) + + url = f"http://{args.host}:{args.port}" + + loop = asyncio.get_event_loop() + + loop.add_signal_handler(signal.SIGINT, loop.stop) + loop.create_task(start_client(loop, url)) + loop.run_forever() diff --git a/third_party/python/aiohttp/examples/curl.py b/third_party/python/aiohttp/examples/curl.py new file mode 100755 index 0000000000..a39639af34 --- /dev/null +++ b/third_party/python/aiohttp/examples/curl.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import argparse +import asyncio + +import aiohttp + + +async def curl(url): + async with aiohttp.ClientSession() as session: + async with session.request("GET", url) as response: + print(repr(response)) + chunk = await response.content.read() + print("Downloaded: %s" % len(chunk)) + + +if __name__ == "__main__": + ARGS = argparse.ArgumentParser(description="GET url example") + ARGS.add_argument("url", nargs=1, metavar="URL", help="URL to download") + ARGS.add_argument( + "--iocp", + default=False, + action="store_true", + help="Use ProactorEventLoop on Windows", + ) + options = ARGS.parse_args() + + if options.iocp: + from asyncio import events, windows_events + + el = windows_events.ProactorEventLoop() + events.set_event_loop(el) + + loop = asyncio.get_event_loop() + loop.run_until_complete(curl(options.url[0])) diff --git a/third_party/python/aiohttp/examples/fake_server.py b/third_party/python/aiohttp/examples/fake_server.py new file mode 100755 index 0000000000..007d96ba02 --- /dev/null +++ b/third_party/python/aiohttp/examples/fake_server.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +import asyncio +import pathlib +import socket +import ssl + +import aiohttp +from aiohttp import web +from aiohttp.resolver import DefaultResolver +from aiohttp.test_utils import unused_port + + +class FakeResolver: + _LOCAL_HOST = {0: "127.0.0.1", socket.AF_INET: "127.0.0.1", socket.AF_INET6: "::1"} + + def __init__(self, fakes, *, loop): + """fakes -- dns -> port dict""" + self._fakes = fakes + self._resolver = DefaultResolver(loop=loop) + + async def resolve(self, host, port=0, family=socket.AF_INET): + fake_port = self._fakes.get(host) + if fake_port is not None: + return [ + { + "hostname": host, + "host": self._LOCAL_HOST[family], + "port": fake_port, + "family": family, + "proto": 0, + "flags": socket.AI_NUMERICHOST, + } + ] + else: + return await self._resolver.resolve(host, port, family) + + +class FakeFacebook: + def __init__(self, *, loop): + self.loop = loop + self.app = web.Application(loop=loop) + self.app.router.add_routes( + [ + web.get("/v2.7/me", self.on_me), + web.get("/v2.7/me/friends", self.on_my_friends), + ] + ) + self.runner = None + here = pathlib.Path(__file__) + ssl_cert = here.parent / "server.crt" + ssl_key = here.parent / "server.key" + self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + self.ssl_context.load_cert_chain(str(ssl_cert), str(ssl_key)) + + async def start(self): + port = unused_port() + self.runner = web.AppRunner(self.app) + await self.runner.setup() + site = web.TCPSite(self.runner, "127.0.0.1", port, ssl_context=self.ssl_context) + await site.start() + return {"graph.facebook.com": port} + + async def stop(self): + await self.runner.cleanup() + + async def on_me(self, request): + return web.json_response({"name": "John Doe", "id": "12345678901234567"}) + + async def on_my_friends(self, request): + return web.json_response( + { + "data": [ + {"name": "Bill Doe", "id": "233242342342"}, + {"name": "Mary Doe", "id": "2342342343222"}, + {"name": "Alex Smith", "id": "234234234344"}, + ], + "paging": { + "cursors": { + "before": "QVFIUjRtc2c5NEl0ajN", + "after": "QVFIUlpFQWM0TmVuaDRad0dt", + }, + "next": ( + "https://graph.facebook.com/v2.7/12345678901234567/" + "friends?access_token=EAACEdEose0cB" + ), + }, + "summary": {"total_count": 3}, + } + ) + + +async def main(loop): + token = "ER34gsSGGS34XCBKd7u" + + fake_facebook = FakeFacebook(loop=loop) + info = await fake_facebook.start() + resolver = FakeResolver(info, loop=loop) + connector = aiohttp.TCPConnector(loop=loop, resolver=resolver, verify_ssl=False) + + async with aiohttp.ClientSession(connector=connector, loop=loop) as session: + async with session.get( + "https://graph.facebook.com/v2.7/me", params={"access_token": token} + ) as resp: + print(await resp.json()) + + async with session.get( + "https://graph.facebook.com/v2.7/me/friends", params={"access_token": token} + ) as resp: + print(await resp.json()) + + await fake_facebook.stop() + + +loop = asyncio.get_event_loop() +loop.run_until_complete(main(loop)) diff --git a/third_party/python/aiohttp/examples/legacy/crawl.py b/third_party/python/aiohttp/examples/legacy/crawl.py new file mode 100755 index 0000000000..c8029b4854 --- /dev/null +++ b/third_party/python/aiohttp/examples/legacy/crawl.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +import asyncio +import logging +import re +import signal +import sys +import urllib.parse + +import aiohttp + + +class Crawler: + def __init__(self, rooturl, loop, maxtasks=100): + self.rooturl = rooturl + self.loop = loop + self.todo = set() + self.busy = set() + self.done = {} + self.tasks = set() + self.sem = asyncio.Semaphore(maxtasks, loop=loop) + + # connector stores cookies between requests and uses connection pool + self.session = aiohttp.ClientSession(loop=loop) + + async def run(self): + t = asyncio.ensure_future(self.addurls([(self.rooturl, "")]), loop=self.loop) + await asyncio.sleep(1, loop=self.loop) + while self.busy: + await asyncio.sleep(1, loop=self.loop) + + await t + await self.session.close() + self.loop.stop() + + async def addurls(self, urls): + for url, parenturl in urls: + url = urllib.parse.urljoin(parenturl, url) + url, frag = urllib.parse.urldefrag(url) + if ( + url.startswith(self.rooturl) + and url not in self.busy + and url not in self.done + and url not in self.todo + ): + self.todo.add(url) + await self.sem.acquire() + task = asyncio.ensure_future(self.process(url), loop=self.loop) + task.add_done_callback(lambda t: self.sem.release()) + task.add_done_callback(self.tasks.remove) + self.tasks.add(task) + + async def process(self, url): + print("processing:", url) + + self.todo.remove(url) + self.busy.add(url) + try: + resp = await self.session.get(url) + except Exception as exc: + print("...", url, "has error", repr(str(exc))) + self.done[url] = False + else: + if resp.status == 200 and ("text/html" in resp.headers.get("content-type")): + data = (await resp.read()).decode("utf-8", "replace") + urls = re.findall(r'(?i)href=["\']?([^\s"\'<>]+)', data) + asyncio.Task(self.addurls([(u, url) for u in urls])) + + resp.close() + self.done[url] = True + + self.busy.remove(url) + print( + len(self.done), + "completed tasks,", + len(self.tasks), + "still pending, todo", + len(self.todo), + ) + + +def main(): + loop = asyncio.get_event_loop() + + c = Crawler(sys.argv[1], loop) + asyncio.ensure_future(c.run(), loop=loop) + + try: + loop.add_signal_handler(signal.SIGINT, loop.stop) + except RuntimeError: + pass + loop.run_forever() + print("todo:", len(c.todo)) + print("busy:", len(c.busy)) + print("done:", len(c.done), "; ok:", sum(c.done.values())) + print("tasks:", len(c.tasks)) + + +if __name__ == "__main__": + if "--iocp" in sys.argv: + from asyncio import events, windows_events + + sys.argv.remove("--iocp") + logging.info("using iocp") + el = windows_events.ProactorEventLoop() + events.set_event_loop(el) + + main() diff --git a/third_party/python/aiohttp/examples/legacy/srv.py b/third_party/python/aiohttp/examples/legacy/srv.py new file mode 100755 index 0000000000..628b6f332f --- /dev/null +++ b/third_party/python/aiohttp/examples/legacy/srv.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +"""Simple server written using an event loop.""" + +import argparse +import asyncio +import logging +import os +import sys + +import aiohttp +import aiohttp.server + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + + +class HttpRequestHandler(aiohttp.server.ServerHttpProtocol): + async def handle_request(self, message, payload): + print( + "method = {!r}; path = {!r}; version = {!r}".format( + message.method, message.path, message.version + ) + ) + + path = message.path + + if not (path.isprintable() and path.startswith("/")) or "/." in path: + print("bad path", repr(path)) + path = None + else: + path = "." + path + if not os.path.exists(path): + print("no file", repr(path)) + path = None + else: + isdir = os.path.isdir(path) + + if not path: + raise aiohttp.HttpProcessingError(code=404) + + for hdr, val in message.headers.items(): + print(hdr, val) + + if isdir and not path.endswith("/"): + path = path + "/" + raise aiohttp.HttpProcessingError( + code=302, headers=(("URI", path), ("Location", path)) + ) + + response = aiohttp.Response(self.writer, 200, http_version=message.version) + response.add_header("Transfer-Encoding", "chunked") + + # content encoding + accept_encoding = message.headers.get("accept-encoding", "").lower() + if "deflate" in accept_encoding: + response.add_header("Content-Encoding", "deflate") + response.add_compression_filter("deflate") + elif "gzip" in accept_encoding: + response.add_header("Content-Encoding", "gzip") + response.add_compression_filter("gzip") + + response.add_chunking_filter(1025) + + if isdir: + response.add_header("Content-type", "text/html") + response.send_headers() + + response.write(b"<ul>\r\n") + for name in sorted(os.listdir(path)): + if name.isprintable() and not name.startswith("."): + try: + bname = name.encode("ascii") + except UnicodeError: + pass + else: + if os.path.isdir(os.path.join(path, name)): + response.write( + b'<li><a href="' + + bname + + b'/">' + + bname + + b"/</a></li>\r\n" + ) + else: + response.write( + b'<li><a href="' + + bname + + b'">' + + bname + + b"</a></li>\r\n" + ) + response.write(b"</ul>") + else: + response.add_header("Content-type", "text/plain") + response.send_headers() + + try: + with open(path, "rb") as fp: + chunk = fp.read(8192) + while chunk: + response.write(chunk) + chunk = fp.read(8192) + except OSError: + response.write(b"Cannot open") + + await response.write_eof() + if response.keep_alive(): + self.keep_alive(True) + + +ARGS = argparse.ArgumentParser(description="Run simple HTTP server.") +ARGS.add_argument( + "--host", action="store", dest="host", default="127.0.0.1", help="Host name" +) +ARGS.add_argument( + "--port", action="store", dest="port", default=8080, type=int, help="Port number" +) +# make iocp and ssl mutually exclusive because ProactorEventLoop is +# incompatible with SSL +group = ARGS.add_mutually_exclusive_group() +group.add_argument( + "--iocp", action="store_true", dest="iocp", help="Windows IOCP event loop" +) +group.add_argument("--ssl", action="store_true", dest="ssl", help="Run ssl mode.") +ARGS.add_argument("--sslcert", action="store", dest="certfile", help="SSL cert file.") +ARGS.add_argument("--sslkey", action="store", dest="keyfile", help="SSL key file.") + + +def main(): + args = ARGS.parse_args() + + if ":" in args.host: + args.host, port = args.host.split(":", 1) + args.port = int(port) + + if args.iocp: + from asyncio import windows_events + + sys.argv.remove("--iocp") + logging.info("using iocp") + el = windows_events.ProactorEventLoop() + asyncio.set_event_loop(el) + + if args.ssl: + here = os.path.join(os.path.dirname(__file__), "tests") + + if args.certfile: + certfile = args.certfile or os.path.join(here, "sample.crt") + keyfile = args.keyfile or os.path.join(here, "sample.key") + else: + certfile = os.path.join(here, "sample.crt") + keyfile = os.path.join(here, "sample.key") + + sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext.load_cert_chain(certfile, keyfile) + else: + sslcontext = None + + loop = asyncio.get_event_loop() + f = loop.create_server( + lambda: HttpRequestHandler(debug=True, keep_alive=75), + args.host, + args.port, + ssl=sslcontext, + ) + svr = loop.run_until_complete(f) + socks = svr.sockets + print("serving on", socks[0].getsockname()) + try: + loop.run_forever() + except KeyboardInterrupt: + pass + + +if __name__ == "__main__": + main() diff --git a/third_party/python/aiohttp/examples/legacy/tcp_protocol_parser.py b/third_party/python/aiohttp/examples/legacy/tcp_protocol_parser.py new file mode 100755 index 0000000000..ca49db7d8f --- /dev/null +++ b/third_party/python/aiohttp/examples/legacy/tcp_protocol_parser.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +"""Protocol parser example.""" +import argparse +import asyncio +import collections + +import aiohttp + +try: + import signal +except ImportError: + signal = None + + +MSG_TEXT = b"text:" +MSG_PING = b"ping:" +MSG_PONG = b"pong:" +MSG_STOP = b"stop:" + +Message = collections.namedtuple("Message", ("tp", "data")) + + +def my_protocol_parser(out, buf): + """Parser is used with StreamParser for incremental protocol parsing. + Parser is a generator function, but it is not a coroutine. Usually + parsers are implemented as a state machine. + + more details in asyncio/parsers.py + existing parsers: + * HTTP protocol parsers asyncio/http/protocol.py + * websocket parser asyncio/http/websocket.py + """ + while True: + tp = yield from buf.read(5) + if tp in (MSG_PING, MSG_PONG): + # skip line + yield from buf.skipuntil(b"\r\n") + out.feed_data(Message(tp, None)) + elif tp == MSG_STOP: + out.feed_data(Message(tp, None)) + elif tp == MSG_TEXT: + # read text + text = yield from buf.readuntil(b"\r\n") + out.feed_data(Message(tp, text.strip().decode("utf-8"))) + else: + raise ValueError("Unknown protocol prefix.") + + +class MyProtocolWriter: + def __init__(self, transport): + self.transport = transport + + def ping(self): + self.transport.write(b"ping:\r\n") + + def pong(self): + self.transport.write(b"pong:\r\n") + + def stop(self): + self.transport.write(b"stop:\r\n") + + def send_text(self, text): + self.transport.write(f"text:{text.strip()}\r\n".encode("utf-8")) + + +class EchoServer(asyncio.Protocol): + def connection_made(self, transport): + print("Connection made") + self.transport = transport + self.stream = aiohttp.StreamParser() + asyncio.Task(self.dispatch()) + + def data_received(self, data): + self.stream.feed_data(data) + + def eof_received(self): + self.stream.feed_eof() + + def connection_lost(self, exc): + print("Connection lost") + + async def dispatch(self): + reader = self.stream.set_parser(my_protocol_parser) + writer = MyProtocolWriter(self.transport) + + while True: + try: + msg = await reader.read() + except aiohttp.ConnectionError: + # client has been disconnected + break + + print(f"Message received: {msg}") + + if msg.type == MSG_PING: + writer.pong() + elif msg.type == MSG_TEXT: + writer.send_text("Re: " + msg.data) + elif msg.type == MSG_STOP: + self.transport.close() + break + + +async def start_client(loop, host, port): + transport, stream = await loop.create_connection(aiohttp.StreamProtocol, host, port) + reader = stream.reader.set_parser(my_protocol_parser) + writer = MyProtocolWriter(transport) + writer.ping() + + message = "This is the message. It will be echoed." + + while True: + try: + msg = await reader.read() + except aiohttp.ConnectionError: + print("Server has been disconnected.") + break + + print(f"Message received: {msg}") + if msg.type == MSG_PONG: + writer.send_text(message) + print("data sent:", message) + elif msg.type == MSG_TEXT: + writer.stop() + print("stop sent") + break + + transport.close() + + +def start_server(loop, host, port): + f = loop.create_server(EchoServer, host, port) + srv = loop.run_until_complete(f) + x = srv.sockets[0] + print("serving on", x.getsockname()) + loop.run_forever() + + +ARGS = argparse.ArgumentParser(description="Protocol parser example.") +ARGS.add_argument( + "--server", action="store_true", dest="server", default=False, help="Run tcp server" +) +ARGS.add_argument( + "--client", action="store_true", dest="client", default=False, help="Run tcp client" +) +ARGS.add_argument( + "--host", action="store", dest="host", default="127.0.0.1", help="Host name" +) +ARGS.add_argument( + "--port", action="store", dest="port", default=9999, type=int, help="Port number" +) + + +if __name__ == "__main__": + args = ARGS.parse_args() + + if ":" in args.host: + args.host, port = args.host.split(":", 1) + args.port = int(port) + + if (not (args.server or args.client)) or (args.server and args.client): + print("Please specify --server or --client\n") + ARGS.print_help() + else: + loop = asyncio.get_event_loop() + if signal is not None: + loop.add_signal_handler(signal.SIGINT, loop.stop) + + if args.server: + start_server(loop, args.host, args.port) + else: + loop.run_until_complete(start_client(loop, args.host, args.port)) diff --git a/third_party/python/aiohttp/examples/lowlevel_srv.py b/third_party/python/aiohttp/examples/lowlevel_srv.py new file mode 100644 index 0000000000..5a003f40f4 --- /dev/null +++ b/third_party/python/aiohttp/examples/lowlevel_srv.py @@ -0,0 +1,26 @@ +import asyncio + +from aiohttp import web + + +async def handler(request): + return web.Response(text="OK") + + +async def main(loop): + server = web.Server(handler) + await loop.create_server(server, "127.0.0.1", 8080) + print("======= Serving on http://127.0.0.1:8080/ ======") + + # pause here for very long time by serving HTTP requests and + # waiting for keyboard interruption + await asyncio.sleep(100 * 3600) + + +loop = asyncio.get_event_loop() + +try: + loop.run_until_complete(main(loop)) +except KeyboardInterrupt: + pass +loop.close() diff --git a/third_party/python/aiohttp/examples/server.crt b/third_party/python/aiohttp/examples/server.crt new file mode 100644 index 0000000000..708971a376 --- /dev/null +++ b/third_party/python/aiohttp/examples/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDADCCAegCCQCgevpPMuTTLzANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJV +QTEQMA4GA1UECAwHVWtyYWluZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMB4XDTE2MDgwNzIzMTMwOFoXDTI2MDgwNTIzMTMwOFowQjELMAkGA1UE +BhMCVUExEDAOBgNVBAgMB1VrcmFpbmUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp +dHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOUgkn3j +X/sdg6GGueGDHCM+snIUVY3fM6D4jXjyBhnT3TqKG1lJwCGYR11AD+2SJYppU+w4 +QaF6YZwMeZBKy+mVQ9+CrVYyKQE7j9H8XgNEHV9BQzoragT8lia8eC5aOQzUeX8A +xCSSbsnyT/X+S1IKdd0txLOeZOD6pWwJoc3dpDELglk2b1tzhyN2GjQv3aRHj55P +x7127MeZyRXwODFpXrpbnwih4OqkA4EYtmqFbZttGEzMhd4Y5mkbyuRbGM+IE99o +QJMvnIkjAfUo0aKnDrcAIkWCkwLIci9TIG6u3R1P2Tn+HYVntzQZ4BnxanbFNQ5S +9ARd3529EmO3BzUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAXyiw1+YUnTEDI3C/ +vq1Vn9pnwZALVQPiPlTqEGkl/nbq0suMmeZZG7pwrOJp3wr+sGwRAv9sPTro6srf +Vj12wTo4LrTRKEDuS+AUJl0Mut7cPGIUKo+MGeZmmnDjMqcjljN3AO47ef4eWYo5 +XGe4r4NDABEk5auOD/vQW5IiIMdmWsaMJ+0mZNpAV2NhAD/6ia28VvSL/yuaNqDW +TYTUYHWLH08H6M6qrQ7FdoIDyYR5siqBukQzeqlnuq45bQ3ViYttNIkzZN4jbWJV +/MFYLuJQ/fNoalDIC+ec0EIa9NbrfpoocJ8h6HlmWOqkES4QpBSOrkVid64Cdy3P +JgiEWg== +-----END CERTIFICATE----- diff --git a/third_party/python/aiohttp/examples/server.csr b/third_party/python/aiohttp/examples/server.csr new file mode 100644 index 0000000000..1df3087b91 --- /dev/null +++ b/third_party/python/aiohttp/examples/server.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCVUExEDAOBgNVBAgMB1VrcmFpbmUxITAf +BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAOUgkn3jX/sdg6GGueGDHCM+snIUVY3fM6D4jXjyBhnT +3TqKG1lJwCGYR11AD+2SJYppU+w4QaF6YZwMeZBKy+mVQ9+CrVYyKQE7j9H8XgNE +HV9BQzoragT8lia8eC5aOQzUeX8AxCSSbsnyT/X+S1IKdd0txLOeZOD6pWwJoc3d +pDELglk2b1tzhyN2GjQv3aRHj55Px7127MeZyRXwODFpXrpbnwih4OqkA4EYtmqF +bZttGEzMhd4Y5mkbyuRbGM+IE99oQJMvnIkjAfUo0aKnDrcAIkWCkwLIci9TIG6u +3R1P2Tn+HYVntzQZ4BnxanbFNQ5S9ARd3529EmO3BzUCAwEAAaAAMA0GCSqGSIb3 +DQEBCwUAA4IBAQDO/PSd29KgisTdGXhntg7yBEhBAjsDW7uQCrdrPSZtFyN6wUHy +/1yrrWe56ZuW8jpuP5tG0eTZ+0bT2RXIRot8a2Cc3eBhpoe8M3d84yXjKAoHutGE +5IK+TViQdvT3pT3a7pTmjlf8Ojq9tx+U2ckiz8Ccnjd9yM47M9NgMhrS1aBpVZSt +gOD+zzrqMML4xks9id94H7bi9Tgs3AbEJIyDpBpoK6i4OvK7KTidCngCg80qmdTy +bcScLapoy1Ped2BKKuxWdOOlP+mDJatc/pcfBLE13AncQjJgMerS9M5RWCBjmRow +A+aB6fBEU8bOTrqCryfBeTiV6xzyDDcIXtc6 +-----END CERTIFICATE REQUEST----- diff --git a/third_party/python/aiohttp/examples/server.key b/third_party/python/aiohttp/examples/server.key new file mode 100644 index 0000000000..37dae99e67 --- /dev/null +++ b/third_party/python/aiohttp/examples/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA5SCSfeNf+x2DoYa54YMcIz6ychRVjd8zoPiNePIGGdPdOoob +WUnAIZhHXUAP7ZIlimlT7DhBoXphnAx5kErL6ZVD34KtVjIpATuP0fxeA0QdX0FD +OitqBPyWJrx4Llo5DNR5fwDEJJJuyfJP9f5LUgp13S3Es55k4PqlbAmhzd2kMQuC +WTZvW3OHI3YaNC/dpEePnk/HvXbsx5nJFfA4MWleulufCKHg6qQDgRi2aoVtm20Y +TMyF3hjmaRvK5FsYz4gT32hAky+ciSMB9SjRoqcOtwAiRYKTAshyL1Mgbq7dHU/Z +Of4dhWe3NBngGfFqdsU1DlL0BF3fnb0SY7cHNQIDAQABAoIBAG9BJ6B03VADfrzZ +vDwh+3Gpqd/2u6wNqvYIejk123yDATLBiJIMW3x0goJm7tT+V7gjeJqEnmmYEPlC +nWxQxT6AOdq3iw8FgB+XGjhuAAA5/MEZ4VjHZ81QEGBytzBaosT2DqB6cMMJTz5D +qEvb1Brb9WsWJCLLUFRloBkbfDOG9lMvt34ixYTTmqjsVj5WByD5BhzKH51OJ72L +00IYpvrsEOtSev1hNV4199CHPYE90T/YQVooRBiHtTcfN+/KNVJu6Rf/zcaJ3WMS +1l3MBI8HwMimjKKkbddpoMHyFMtSNmS9Yq+4a9w7XZo1F5rt88hYSCtAF8HRAarX +0VBCJmkCgYEA9HenBBnmfDoN857femzoTHdWQQrZQ4YPAKHvKPlcgudizE5tQbs0 +iTpwm+IsecgJS2Rio7zY+P7A5nKFz3N5c0IX3smYo0J2PoakkLAm25KMxFZYBuz4 +MFWVdfByAU7d28BdNfyOVbA2kU2eal9lJ0yPLpMLbH8+bbvw5uBS808CgYEA7++p +ftwib3DvKWMpl6G5eA1C2xprdbE0jm2fSr3LYp/vZ4QN2V6kK2YIlyUqQvhYCnxX +oIP3v2MWDRHKKwJtBWR4+t23PaDaSXS2Ifm0qhRxwSm/oqpAJQXbR7VzxXp4/4FP +1SgkLe51bubc4h+cDngqBLcplCanvj52CqhqzDsCgYAEIhG8zANNjl22BLWaiETV +Jh9bMifCMH4IcLRuaOjbfbX55kmKlvOobkiBGi3OUUd28teIFSVF8GiqfL0uaLFg +9XkZ1yaxe+or3HLjz1aY171xhFQwqcj4aDoCqHIE+6Rclr/8raxqXnRNuJY5DivT +okO5cdr7lpsjl83W2WwNmQKBgCPXi1xWChbXqgJmu8nY8NnMMVaFpdPY+t7j5U3G ++GDtP1gZU/BKwP9yqInblWqXqp82X+isjg/a/2pIZAj0vdB2Z9Qh1sOwCau7cZG1 +uZVGpI+UavojsJ1XOKCHrJmtZ/HTIVfYPT9XRdehSRHGYwuOS8iUi/ODqr8ymXOS +IRINAoGBAMEmhTihgFz6Y8ezRK3QTubguehHZG1zIvtgVhOk+8hRUTSJPI9nBJPC +4gOZsPx4g2oLK6PiudPR79bhxRxPACCMnXkdwZ/8FaIdmvRHsWVs8T80wID0wthI +r5hW4uqi9CcKZrGWH7mx9cVJktspeGUczvKyzNMfCaojwzA/49Z1 +-----END RSA PRIVATE KEY----- diff --git a/third_party/python/aiohttp/examples/server_simple.py b/third_party/python/aiohttp/examples/server_simple.py new file mode 100644 index 0000000000..d464383d26 --- /dev/null +++ b/third_party/python/aiohttp/examples/server_simple.py @@ -0,0 +1,31 @@ +# server_simple.py +from aiohttp import web + + +async def handle(request): + name = request.match_info.get("name", "Anonymous") + text = "Hello, " + name + return web.Response(text=text) + + +async def wshandle(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + + async for msg in ws: + if msg.type == web.WSMsgType.text: + await ws.send_str(f"Hello, {msg.data}") + elif msg.type == web.WSMsgType.binary: + await ws.send_bytes(msg.data) + elif msg.type == web.WSMsgType.close: + break + + return ws + + +app = web.Application() +app.add_routes( + [web.get("/", handle), web.get("/echo", wshandle), web.get("/{name}", handle)] +) + +web.run_app(app) diff --git a/third_party/python/aiohttp/examples/static_files.py b/third_party/python/aiohttp/examples/static_files.py new file mode 100755 index 0000000000..65f6bb9c76 --- /dev/null +++ b/third_party/python/aiohttp/examples/static_files.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +import pathlib + +from aiohttp import web + +app = web.Application() +app.router.add_static("/", pathlib.Path(__file__).parent, show_index=True) + +web.run_app(app) diff --git a/third_party/python/aiohttp/examples/web_classview.py b/third_party/python/aiohttp/examples/web_classview.py new file mode 100755 index 0000000000..0f65f7d7f4 --- /dev/null +++ b/third_party/python/aiohttp/examples/web_classview.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web class based views +""" + + +import functools +import json + +from aiohttp import web + + +class MyView(web.View): + async def get(self): + return web.json_response( + { + "method": "get", + "args": dict(self.request.GET), + "headers": dict(self.request.headers), + }, + dumps=functools.partial(json.dumps, indent=4), + ) + + async def post(self): + data = await self.request.post() + return web.json_response( + { + "method": "post", + "args": dict(self.request.GET), + "data": dict(data), + "headers": dict(self.request.headers), + }, + dumps=functools.partial(json.dumps, indent=4), + ) + + +async def index(request): + txt = """ + <html> + <head> + <title>Class based view example</title> + </head> + <body> + <h1>Class based view example</h1> + <ul> + <li><a href="/">/</a> This page + <li><a href="/get">/get</a> Returns GET data. + <li><a href="/post">/post</a> Returns POST data. + </ul> + </body> + </html> + """ + return web.Response(text=txt, content_type="text/html") + + +def init(): + app = web.Application() + app.router.add_get("/", index) + app.router.add_get("/get", MyView) + app.router.add_post("/post", MyView) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_cookies.py b/third_party/python/aiohttp/examples/web_cookies.py new file mode 100755 index 0000000000..e7a4a595d7 --- /dev/null +++ b/third_party/python/aiohttp/examples/web_cookies.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web basic server with cookies. +""" + +from pprint import pformat + +from aiohttp import web + +tmpl = """\ +<html> + <body> + <a href="/login">Login</a><br/> + <a href="/logout">Logout</a><br/> + <pre>{}</pre> + </body> +</html>""" + + +async def root(request): + resp = web.Response(content_type="text/html") + resp.text = tmpl.format(pformat(request.cookies)) + return resp + + +async def login(request): + resp = web.HTTPFound(location="/") + resp.set_cookie("AUTH", "secret") + return resp + + +async def logout(request): + resp = web.HTTPFound(location="/") + resp.del_cookie("AUTH") + return resp + + +def init(loop): + app = web.Application(loop=loop) + app.router.add_get("/", root) + app.router.add_get("/login", login) + app.router.add_get("/logout", logout) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_rewrite_headers_middleware.py b/third_party/python/aiohttp/examples/web_rewrite_headers_middleware.py new file mode 100755 index 0000000000..20799a3a7c --- /dev/null +++ b/third_party/python/aiohttp/examples/web_rewrite_headers_middleware.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +""" +Example for rewriting response headers by middleware. +""" + +from aiohttp import web + + +async def handler(request): + return web.Response(text="Everything is fine") + + +@web.middleware +async def middleware(request, handler): + try: + response = await handler(request) + except web.HTTPException as exc: + raise exc + if not response.prepared: + response.headers["SERVER"] = "Secured Server Software" + return response + + +def init(): + app = web.Application(middlewares=[middleware]) + app.router.add_get("/", handler) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_srv.py b/third_party/python/aiohttp/examples/web_srv.py new file mode 100755 index 0000000000..b572326a3a --- /dev/null +++ b/third_party/python/aiohttp/examples/web_srv.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web basic server +""" + +import textwrap + +from aiohttp import web + + +async def intro(request): + txt = textwrap.dedent( + """\ + Type {url}/hello/John {url}/simple or {url}/change_body + in browser url bar + """ + ).format(url="127.0.0.1:8080") + binary = txt.encode("utf8") + resp = web.StreamResponse() + resp.content_length = len(binary) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(binary) + return resp + + +async def simple(request): + return web.Response(text="Simple answer") + + +async def change_body(request): + resp = web.Response() + resp.body = b"Body changed" + resp.content_type = "text/plain" + return resp + + +async def hello(request): + resp = web.StreamResponse() + name = request.match_info.get("name", "Anonymous") + answer = ("Hello, " + name).encode("utf8") + resp.content_length = len(answer) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(answer) + await resp.write_eof() + return resp + + +def init(): + app = web.Application() + app.router.add_get("/", intro) + app.router.add_get("/simple", simple) + app.router.add_get("/change_body", change_body) + app.router.add_get("/hello/{name}", hello) + app.router.add_get("/hello", hello) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_srv_route_deco.py b/third_party/python/aiohttp/examples/web_srv_route_deco.py new file mode 100644 index 0000000000..332990362c --- /dev/null +++ b/third_party/python/aiohttp/examples/web_srv_route_deco.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web basic server +with decorator definition for routes +""" + +import textwrap + +from aiohttp import web + +routes = web.RouteTableDef() + + +@routes.get("/") +async def intro(request): + txt = textwrap.dedent( + """\ + Type {url}/hello/John {url}/simple or {url}/change_body + in browser url bar + """ + ).format(url="127.0.0.1:8080") + binary = txt.encode("utf8") + resp = web.StreamResponse() + resp.content_length = len(binary) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(binary) + return resp + + +@routes.get("/simple") +async def simple(request): + return web.Response(text="Simple answer") + + +@routes.get("/change_body") +async def change_body(request): + resp = web.Response() + resp.body = b"Body changed" + resp.content_type = "text/plain" + return resp + + +@routes.get("/hello") +async def hello(request): + resp = web.StreamResponse() + name = request.match_info.get("name", "Anonymous") + answer = ("Hello, " + name).encode("utf8") + resp.content_length = len(answer) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(answer) + await resp.write_eof() + return resp + + +def init(): + app = web.Application() + app.router.add_routes(routes) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_srv_route_table.py b/third_party/python/aiohttp/examples/web_srv_route_table.py new file mode 100644 index 0000000000..f53142adad --- /dev/null +++ b/third_party/python/aiohttp/examples/web_srv_route_table.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web basic server +with table definition for routes +""" + +import textwrap + +from aiohttp import web + + +async def intro(request): + txt = textwrap.dedent( + """\ + Type {url}/hello/John {url}/simple or {url}/change_body + in browser url bar + """ + ).format(url="127.0.0.1:8080") + binary = txt.encode("utf8") + resp = web.StreamResponse() + resp.content_length = len(binary) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(binary) + return resp + + +async def simple(request): + return web.Response(text="Simple answer") + + +async def change_body(request): + resp = web.Response() + resp.body = b"Body changed" + resp.content_type = "text/plain" + return resp + + +async def hello(request): + resp = web.StreamResponse() + name = request.match_info.get("name", "Anonymous") + answer = ("Hello, " + name).encode("utf8") + resp.content_length = len(answer) + resp.content_type = "text/plain" + await resp.prepare(request) + await resp.write(answer) + await resp.write_eof() + return resp + + +def init(): + app = web.Application() + app.router.add_routes( + [ + web.get("/", intro), + web.get("/simple", simple), + web.get("/change_body", change_body), + web.get("/hello/{name}", hello), + web.get("/hello", hello), + ] + ) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/web_ws.py b/third_party/python/aiohttp/examples/web_ws.py new file mode 100755 index 0000000000..970f1506be --- /dev/null +++ b/third_party/python/aiohttp/examples/web_ws.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Example for aiohttp.web websocket server +""" + +import os + +from aiohttp import web + +WS_FILE = os.path.join(os.path.dirname(__file__), "websocket.html") + + +async def wshandler(request): + resp = web.WebSocketResponse() + available = resp.can_prepare(request) + if not available: + with open(WS_FILE, "rb") as fp: + return web.Response(body=fp.read(), content_type="text/html") + + await resp.prepare(request) + + await resp.send_str("Welcome!!!") + + try: + print("Someone joined.") + for ws in request.app["sockets"]: + await ws.send_str("Someone joined") + request.app["sockets"].append(resp) + + async for msg in resp: + if msg.type == web.WSMsgType.TEXT: + for ws in request.app["sockets"]: + if ws is not resp: + await ws.send_str(msg.data) + else: + return resp + return resp + + finally: + request.app["sockets"].remove(resp) + print("Someone disconnected.") + for ws in request.app["sockets"]: + await ws.send_str("Someone disconnected.") + + +async def on_shutdown(app): + for ws in app["sockets"]: + await ws.close() + + +def init(): + app = web.Application() + app["sockets"] = [] + app.router.add_get("/", wshandler) + app.on_shutdown.append(on_shutdown) + return app + + +web.run_app(init()) diff --git a/third_party/python/aiohttp/examples/websocket.html b/third_party/python/aiohttp/examples/websocket.html new file mode 100644 index 0000000000..2ba9ff367d --- /dev/null +++ b/third_party/python/aiohttp/examples/websocket.html @@ -0,0 +1,89 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<html> +<head> +<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"> +</script> + <script language="javascript" type="text/javascript"> + $(function() { + var conn = null; + function log(msg) { + var control = $('#log'); + control.html(control.html() + msg + '<br/>'); + control.scrollTop(control.scrollTop() + 1000); + } + function connect() { + disconnect(); + var wsUri = (window.location.protocol=='https:'&&'wss://'||'ws://')+window.location.host; + conn = new WebSocket(wsUri); + log('Connecting...'); + conn.onopen = function() { + log('Connected.'); + update_ui(); + }; + conn.onmessage = function(e) { + log('Received: ' + e.data); + }; + conn.onclose = function() { + log('Disconnected.'); + conn = null; + update_ui(); + }; + } + function disconnect() { + if (conn != null) { + log('Disconnecting...'); + conn.close(); + conn = null; + update_ui(); + } + } + function update_ui() { + if (conn == null) { + $('#status').text('disconnected'); + $('#connect').html('Connect'); + } else { + $('#status').text('connected (' + conn.protocol + ')'); + $('#connect').html('Disconnect'); + } + } + $('#connect').click(function() { + if (conn == null) { + connect(); + } else { + disconnect(); + } + update_ui(); + return false; + }); + $('#send').click(function() { + var text = $('#text').val(); + log('Sending: ' + text); + conn.send(text); + $('#text').val('').focus(); + return false; + }); + $('#text').keyup(function(e) { + if (e.keyCode === 13) { + $('#send').click(); + return false; + } + }); + }); +</script> +</head> +<body> +<h3>Chat!</h3> +<div> + <button id="connect">Connect</button> | Status: + <span id="status">disconnected</span> +</div> +<div id="log" + style="width:20em;height:15em;overflow:auto;border:1px solid black"> +</div> +<form id="chatform" onsubmit="return false;"> + <input id="text" type="text" /> + <input id="send" type="button" value="Send" /> +</form> +</body> +</html> |