webpnp/main.py
2020-04-17 02:25:12 +02:00

114 lines
2.7 KiB
Python

import aiohttp.web
import traceback
from model import Model
routes = aiohttp.web.RouteTableDef()
routes.static('/static', 'static')
admintoken = "ae33fd8cc4fdcb1ff50ba42ff48046a7"
CLIENT_REGEX = r'/{client:[a-zA-Z0-9]{16}}'
def get_client(request: aiohttp.web.Request):
client = request.match_info.get("client", None)
model = request.app['model']
if not client:
print('[get_client] client is not set, wtf')
raise aiohttp.web.HTTPBadRequest()
if not model.exists_client(client):
print(f'[get_client] model does not know {client=}')
raise aiohttp.web.HTTPBadRequest()
return client
@routes.get(CLIENT_REGEX)
async def handler(request: aiohttp.web.Request):
# this handler prevents people missing trailing slashes
client = get_client(request)
raise aiohttp.web.HTTPFound(f"/{client}/")
@routes.get(CLIENT_REGEX + '/')
async def handler(request: aiohttp.web.Request):
client = get_client(request)
print(f"{client=} accessed")
return aiohttp.web.FileResponse('ui.html')
@routes.post(CLIENT_REGEX + '/api/{method}')
async def handler(request: aiohttp.web.Request):
client = get_client(request)
method = request.match_info.get('method', None)
model = request.app['model']
data = await request.json()
print(f'{client=} {data=}')
try:
assert method in model.ApiMethod.dict
await model.ApiMethod.dict[method](model, client, **data)
return aiohttp.web.Response(status=200)
except Exception as e:
del e # unused?
traceback.print_exc()
return aiohttp.web.Response(status=400)
@routes.get(CLIENT_REGEX + '/ws')
async def _(request: aiohttp.web.Request):
client = get_client(request)
model = request.app['model']
ws = aiohttp.web.WebSocketResponse(heartbeat=10)
await ws.prepare(request)
print(f'[WS] client {client} connected, {ws=}')
await model.subscribe(client, ws)
async for msg in ws:
print(f'[WS] incoming message from client {client}, {ws=}, {msg=}')
print(f'[WS] client {client} disconnected, {ws=}')
model.unsubscribe(ws)
return ws
@routes.get(f"/api/{admintoken}")
async def handler(request: aiohttp.web.Request):
model = request.app['model']
return aiohttp.web.json_response(model.sessions)
@routes.get('/')
async def handler(request):
del request # unused
return aiohttp.web.FileResponse('index.html')
@routes.get('/newclient')
async def handler(request):
model = request.app['model']
client = model.create_client()
raise aiohttp.web.HTTPFound(f"/{client}/")
if __name__ == '__main__':
app = aiohttp.web.Application()
app.add_routes(routes)
app['model'] = Model()
aiohttp.web.run_app(app, port=42042)
app['model'].save()