feat(SIP-39): Websocket sidecar app (#11498)

* WIP node.js websocket app

* Load testing

* Multi-stream publish with blocking reads

* Use JWT for auth and channel ID

* Update ws jwt cookie name

* Typescript

* Frontend WebSocket transport support

* ws server ping/pong and GC logic

* ws server unit tests

* GC interval config, debug logging

* Cleanup JWT cookie logic

* Refactor asyncEvents.ts to support non-Redux use cases

* Update tests for refactored asyncEvents

* Add eslint, write READMEs, reorg files

* CI workflow

* Moar Apache license headers

* pylint found something

* adjust GH actions workflow

* Improve documentation & comments

* Prettier

* Add configurable logging via Winston

* Add SSL support for Redis connections

* Fix incompatible logger statements

* Apply suggestions from code review

Co-authored-by: David Aaron Suddjian <1858430+suddjian@users.noreply.github.com>

* rename streamPrefix config

Co-authored-by: David Aaron Suddjian <1858430+suddjian@users.noreply.github.com>
This commit is contained in:
Rob DiCiuccio
2021-04-08 11:12:03 -07:00
committed by GitHub
parent 6a81a7961c
commit 806fb73d25
33 changed files with 17198 additions and 12 deletions

View File

@@ -21,7 +21,7 @@ from typing import Any, Dict, List, Optional, Tuple
import jwt
import redis
from flask import Flask, Request, Response, session
from flask import Flask, request, Request, Response, session
logger = logging.getLogger(__name__)
@@ -111,13 +111,14 @@ class AsyncQueryManager:
def validate_session( # pylint: disable=unused-variable
response: Response,
) -> Response:
reset_token = False
user_id = session["user_id"] if "user_id" in session else None
if "async_channel_id" not in session or "async_user_id" not in session:
reset_token = True
elif user_id != session["async_user_id"]:
reset_token = True
reset_token = (
not request.cookies.get(self._jwt_cookie_name)
or "async_channel_id" not in session
or "async_user_id" not in session
or user_id != session["async_user_id"]
)
if reset_token:
async_channel_id = str(uuid.uuid4())
@@ -132,10 +133,6 @@ class AsyncQueryManager:
value=token,
httponly=True,
secure=self._jwt_cookie_secure,
# max_age=max_age or config.cookie_max_age,
# domain=config.cookie_domain,
# path=config.access_cookie_path,
# samesite=config.cookie_samesite
)
return response
@@ -148,8 +145,8 @@ class AsyncQueryManager:
data = jwt.decode(token, self._jwt_secret, algorithms=["HS256"])
return data
def parse_jwt_from_request(self, request: Request) -> Dict[str, Any]:
token = request.cookies.get(self._jwt_cookie_name)
def parse_jwt_from_request(self, req: Request) -> Dict[str, Any]:
token = req.cookies.get(self._jwt_cookie_name)
if not token:
raise AsyncQueryTokenException("Token not preset")