summaryrefslogtreecommitdiffstats
path: root/third_party/python/aiohttp/examples
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/aiohttp/examples')
-rwxr-xr-xthird_party/python/aiohttp/examples/background_tasks.py66
-rwxr-xr-xthird_party/python/aiohttp/examples/cli_app.py51
-rwxr-xr-xthird_party/python/aiohttp/examples/client_auth.py23
-rwxr-xr-xthird_party/python/aiohttp/examples/client_json.py22
-rwxr-xr-xthird_party/python/aiohttp/examples/client_ws.py73
-rwxr-xr-xthird_party/python/aiohttp/examples/curl.py35
-rwxr-xr-xthird_party/python/aiohttp/examples/fake_server.py115
-rwxr-xr-xthird_party/python/aiohttp/examples/legacy/crawl.py108
-rwxr-xr-xthird_party/python/aiohttp/examples/legacy/srv.py178
-rwxr-xr-xthird_party/python/aiohttp/examples/legacy/tcp_protocol_parser.py172
-rw-r--r--third_party/python/aiohttp/examples/lowlevel_srv.py26
-rw-r--r--third_party/python/aiohttp/examples/server.crt19
-rw-r--r--third_party/python/aiohttp/examples/server.csr16
-rw-r--r--third_party/python/aiohttp/examples/server.key27
-rw-r--r--third_party/python/aiohttp/examples/server_simple.py31
-rwxr-xr-xthird_party/python/aiohttp/examples/static_files.py9
-rwxr-xr-xthird_party/python/aiohttp/examples/web_classview.py63
-rwxr-xr-xthird_party/python/aiohttp/examples/web_cookies.py45
-rwxr-xr-xthird_party/python/aiohttp/examples/web_rewrite_headers_middleware.py30
-rwxr-xr-xthird_party/python/aiohttp/examples/web_srv.py59
-rw-r--r--third_party/python/aiohttp/examples/web_srv_route_deco.py62
-rw-r--r--third_party/python/aiohttp/examples/web_srv_route_table.py64
-rwxr-xr-xthird_party/python/aiohttp/examples/web_ws.py58
-rw-r--r--third_party/python/aiohttp/examples/websocket.html89
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>&nbsp;|&nbsp;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>