From 24ae540ea5fc9772bcac7ca4dc125d02e57af492 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 14 Sep 2021 11:34:57 -0400 Subject: [PATCH] a lot of changes --- .../izzylib/http_server/application.py | 2 +- http_server/izzylib/http_server/config.py | 5 +++++ .../izzylib/http_server/error_handlers.py | 3 +++ .../izzylib/http_server/frontend/base.haml | 6 +++--- http_server/izzylib/http_server/middleware.py | 10 +++++++++- http_server/izzylib/http_server/misc.py | 10 ++++++++++ http_server/izzylib/http_server/request.py | 1 + http_server/izzylib/http_server/response.py | 4 ++-- .../izzylib/http_requests_client/client.py | 9 +++++---- .../izzylib/http_requests_client/signature.py | 20 ++++++++++++++----- 10 files changed, 54 insertions(+), 16 deletions(-) diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index 3e08bcd..7c140b8 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -87,7 +87,7 @@ class Application(sanic.Sanic): def add_middleware(self, middleware): mw = middleware(self) - self.register_middleware(mw.handler, mw.attach) + self.register_middleware(mw, mw.attach) def get_menu_item(self, name): diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py index e6e508a..e7297fd 100644 --- a/http_server/izzylib/http_server/config.py +++ b/http_server/izzylib/http_server/config.py @@ -14,9 +14,11 @@ class UserLevel(IntEnum): AUTH = 1000 +# Note: sub-classing the Request class breaks things for some reason class Config(DotDict): defaults = dict( name = 'IzzyLib Http Server', + title = None, version = '0.0.1', git_repo = 'https://git.barkshark.xyz/izaliamae/izzylib', listen = 'localhost', @@ -50,6 +52,9 @@ class Config(DotDict): if kwargs.get('host') and not kwargs.get('web_host'): self.web_host = self.host + if self.name and not self.title: + self.title = self.name + def __setitem__(self, key, value): if key not in self.defaults.keys(): diff --git a/http_server/izzylib/http_server/error_handlers.py b/http_server/izzylib/http_server/error_handlers.py index 932993d..e82172b 100644 --- a/http_server/izzylib/http_server/error_handlers.py +++ b/http_server/izzylib/http_server/error_handlers.py @@ -30,6 +30,9 @@ class GenericError: traceback.print_exc() try: + if 'json' in request.headers.get('accept', ''): + return response.json(msg, status=status) + return response.error(msg, status, pprint=True) except Exception as e: diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml index 47831c4..e173cc4 100644 --- a/http_server/izzylib/http_server/frontend/base.haml +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -1,7 +1,7 @@ %html %head - %title << {{cfg.name}}: {{page}} + %title << {{cfg.title}}: {{page}} %link(rel='stylesheet' type='text/css' href='/framework/style.css') %link(rel='manifest' href='/framework/manifest.json') %meta(charset='UTF-8') @@ -13,10 +13,10 @@ #header.flex-container -if menu_left #btn.section - .page-title.section -> %a.title(href='/') << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.title}} -else - .page-title.section -> %a.title(href='/') << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.title}} #btn.section -if message diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py index 8555d87..e081a2f 100644 --- a/http_server/izzylib/http_server/middleware.py +++ b/http_server/izzylib/http_server/middleware.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta, timezone from izzylib import izzylog as logging, logging as applog from . import start_time +from .response import Response cache_types = [ @@ -42,7 +43,14 @@ class MiddlewareBase: self.cfg = app.cfg - async def handler(self, request): + async def __call__(self, request, response=None): + if not response: + response = Response(self.app, request) + + return await self.handler(request, response) + + + async def handler(self, request, response): pass diff --git a/http_server/izzylib/http_server/misc.py b/http_server/izzylib/http_server/misc.py index b1f000c..2051570 100644 --- a/http_server/izzylib/http_server/misc.py +++ b/http_server/izzylib/http_server/misc.py @@ -1,3 +1,5 @@ +import json + from izzylib import LowerDotDict @@ -29,3 +31,11 @@ class Headers(LowerDotDict): def getall(self, key, default=[]): return self.get(key.lower(), default) + + + def to_json(self, indent=None): + return json.dumps(self.to_dict(), indent=indent) + + + def to_dict(self): + return {k: self.getone(k) for k in self} diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index 8ebab4d..f8f5dd3 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -1,6 +1,7 @@ import sanic from izzylib import DotDict +from urllib.parse import parse_qsl from .misc import Headers diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py index 31ab18b..cad9de4 100644 --- a/http_server/izzylib/http_server/response.py +++ b/http_server/izzylib/http_server/response.py @@ -62,11 +62,11 @@ class Response: def __str__(self): - return self.body + return str(self.body) def __bytes__(self): - return self.body.encode('utf-8') + return self.body if isinstance(self.body, bytes) else self.body.encode('utf-8') def __repr__(self): diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py index 4eea6a8..c7ada17 100644 --- a/requests_client/izzylib/http_requests_client/client.py +++ b/requests_client/izzylib/http_requests_client/client.py @@ -11,7 +11,7 @@ from izzylib.exceptions import HttpFileDownloadedError from ssl import SSLCertVerificationError from urllib.parse import urlparse -from .signature import sign_request +from .signature import sign_request, set_client Client = None @@ -111,7 +111,7 @@ class HttpRequestsClient(object): class HttpRequestsRequest(object): - def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + def __init__(self, client, url, data=b'', headers={}, query={}, method='get'): parsed = urlparse(url) self.args = [url] self.kwargs = DotDict({'params': query}) @@ -119,6 +119,7 @@ class HttpRequestsRequest(object): self.client = client self.path = parsed.path self.host = parsed.netloc + self.body = data new_headers = client.headers.copy() new_headers.update(headers) @@ -129,7 +130,6 @@ class HttpRequestsRequest(object): parsed_headers['user-agent'] = client.agent self.kwargs['headers'] = DotDict(new_headers) - self.kwargs['data'] = data if client.proxy.enabled: self.kwargs['proxies'] = DotDict({self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'}) @@ -142,7 +142,7 @@ class HttpRequestsRequest(object): @body.setter def body(self, data): - self.kwargs.data = data + self.kwargs.data = data.encode('utf-8') if isinstance(data, str) else data @property @@ -224,3 +224,4 @@ class HttpRequestsResponse(object): def set_requests_client(client=None): global Client Client = client or RequestsClient() + set_client(Client) diff --git a/requests_client/izzylib/http_requests_client/signature.py b/requests_client/izzylib/http_requests_client/signature.py index 98a6b55..452d0c0 100644 --- a/requests_client/izzylib/http_requests_client/signature.py +++ b/requests_client/izzylib/http_requests_client/signature.py @@ -6,6 +6,7 @@ from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from base64 import b64decode, b64encode +from datetime import datetime from functools import lru_cache from izzylib import DefaultDotDict, DotDict from izzylib import izzylog as logging @@ -13,6 +14,15 @@ from tldextract import extract from urllib.parse import urlparse +Client = None + + +def set_client(client): + global Client + + Client = client + + @lru_cache(maxsize=512) def fetch_actor(url): if not Client: @@ -126,6 +136,7 @@ def parse_signature(signature: str): sig.headers = sig.headers.split() sig.domain = urlparse(sig.keyid).netloc sig.top_domain = '.'.join(extract(sig.domain)[1:]) + sig.actor = sig.keyid.split('#')[0] return sig @@ -152,7 +163,6 @@ def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body if not actor: actor = fetch_actor(signature.keyid) - print(actor) ## Add digest header to missing headers list if it doesn't exist if method.lower() == 'post' and not digest: @@ -181,9 +191,7 @@ async def verify_request(request, actor: dict=None): actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification ''' - body = (await request.body) if request.body else None - headers = {k.lower(): v[0] for k,v in request.headers.items()} - return verify_headers(headers, request.method, request.path, actor, body) + return verify_headers(request.Headers.to_dict(), request.method, request.path, actor, request.body) @@ -223,6 +231,8 @@ def sign_pkcs_headers(key: str, headers: dict, sig=None): def sign_request(request, privkey, keyid): + assert isinstance(request.body, bytes) + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') request.add_header('host', request.host) request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) @@ -230,7 +240,7 @@ def sign_request(request, privkey, keyid): if request.body: body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) + request.add_header('content-length', str(len(request.body))) sig = { 'keyId': keyid,