updated path handling so that only root paths get registered with the server. root handler functions can delegate however they want to.
This commit is contained in:
@@ -193,6 +193,9 @@ class Request(Message):
|
||||
if ('p' in msg.data) and (type(msg.data['p']) is not str):
|
||||
raise ValueError("Path of Request must be a string.")
|
||||
|
||||
if 'p' in self.data:
|
||||
self.data['p'] = str(self.data['p']).strip().lower()
|
||||
|
||||
if 'm' in msg.data:
|
||||
if type(msg.data['m']) is not bytes:
|
||||
raise ValueError("Method of Request must be bytes.")
|
||||
@@ -207,7 +210,7 @@ class Request(Message):
|
||||
|
||||
@path.setter
|
||||
def path(self, path: str):
|
||||
self.data['p'] = str(path.strip())
|
||||
self.data['p'] = str(path).strip().lower()
|
||||
|
||||
@property
|
||||
def method(self) -> Method:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pe.app
|
||||
import packetserver.common
|
||||
from packetserver.server.constants import default_server_config
|
||||
from packetserver.server.bulletin import init_bulletins
|
||||
from copy import deepcopy
|
||||
import ax25
|
||||
from pathlib import Path
|
||||
@@ -13,6 +14,7 @@ from packetserver.server.requests import standard_handlers
|
||||
import logging
|
||||
import signal
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class Server:
|
||||
@@ -46,6 +48,7 @@ class Server:
|
||||
conn.root.config['blacklist'] = PersistentList()
|
||||
if 'users' not in conn.root():
|
||||
conn.root.users = OOBTree()
|
||||
init_bulletins(conn.root())
|
||||
self.app = pe.app.Application()
|
||||
packetserver.common.PacketServerConnection.receive_subscribers.append(lambda x: self.server_receiver(x))
|
||||
packetserver.common.PacketServerConnection.connection_subscribers.append(lambda x: self.server_connection_bouncer(x))
|
||||
@@ -83,6 +86,9 @@ class Server:
|
||||
logging.debug("running server receiver")
|
||||
process_incoming_data(conn, self)
|
||||
|
||||
def register_path_handler(self, path_root: str, fn: Callable):
|
||||
self.handlers[path_root.strip().lower()] = fn
|
||||
|
||||
def start(self):
|
||||
self.app.start(self.pe_server, self.pe_port)
|
||||
self.app.register_callsigns(self.callsign)
|
||||
|
||||
101
src/packetserver/server/bulletin.py
Normal file
101
src/packetserver/server/bulletin.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import persistent
|
||||
import persistent.list
|
||||
from persistent.mapping import PersistentMapping
|
||||
import datetime
|
||||
from typing import Self,Union,Optional
|
||||
from packetserver.common import PacketServerConnection, Request, Response, Message
|
||||
from packetserver.server import Server
|
||||
from packetserver.server.requests import send_404
|
||||
import ZODB
|
||||
import logging
|
||||
|
||||
def init_bulletins(root: PersistentMapping):
|
||||
if 'bulletins' not in root:
|
||||
root['bulletins'] = persistent.list.PersistentList()
|
||||
if 'bulletin_counter' not in root:
|
||||
root['bulletin_counter'] = 0
|
||||
|
||||
def get_new_bulletin_id(root: PersistentMapping) -> int:
|
||||
if 'bulletin_counter' not in root:
|
||||
root['bulletin_counter'] = 1
|
||||
return 0
|
||||
else:
|
||||
current = root['bulletin_counter']
|
||||
root['bulletin_counter'] = current + 1
|
||||
return current
|
||||
|
||||
class Bulletin(persistent.Persistent):
|
||||
@classmethod
|
||||
def get_bulletin_by_id(cls, bid: int, db_root: PersistentMapping) -> Optional[Self]:
|
||||
for bull in db_root['bulletins']:
|
||||
if bull.id == bid:
|
||||
return bull
|
||||
return None
|
||||
|
||||
def __init__(self, author: str, subject: str, text: str):
|
||||
self.author = author
|
||||
self.subject = subject
|
||||
self.body = text
|
||||
self.created_at = None
|
||||
self.updated_at = None
|
||||
self.id = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, bulletin_dict: dict) -> Self:
|
||||
return Bulletin(bulletin_dict['author'], bulletin_dict['subject'], bulletin_dict['body'])
|
||||
|
||||
def write_new(self, db_root: PersistentMapping):
|
||||
if self.id is None:
|
||||
self.id = get_new_bulletin_id(db_root)
|
||||
self.created_at = datetime.datetime.now(datetime.UTC)
|
||||
self.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
db_root['bulletins'].append(self)
|
||||
|
||||
def update_subject(self, new_text: str):
|
||||
self.subject = new_text
|
||||
self.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
def update_body(self, new_text: str):
|
||||
self.body = new_text
|
||||
self.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"author": self.author,
|
||||
"subject": self.subject,
|
||||
"body": self.body,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"updated_at": self.updated_at.isoformat()
|
||||
}
|
||||
|
||||
def handle_bulletin_get(req: Request, conn: PacketServerConnection, server: Server):
|
||||
response = Response.blank()
|
||||
with server.db.transaction() as db:
|
||||
pass
|
||||
return response
|
||||
|
||||
def handle_bulletin_post(req: Request, conn: PacketServerConnection, server: Server):
|
||||
response = Response.blank()
|
||||
with server.db.transaction() as db:
|
||||
pass
|
||||
return response
|
||||
|
||||
def handle_bulletin_update(req: Request, conn: PacketServerConnection, server: Server):
|
||||
response = Response.blank()
|
||||
with server.db.transaction() as db:
|
||||
pass
|
||||
return response
|
||||
|
||||
def handle_bulletin_delete(req: Request, conn: PacketServerConnection, server: Server):
|
||||
response = Response.blank()
|
||||
with server.db.transaction() as db:
|
||||
pass
|
||||
return response
|
||||
|
||||
def bulletin_root_handler(req: Request, conn: PacketServerConnection, server: Server):
|
||||
logging.debug(f"{req} being processed by bulletin_root_handler")
|
||||
if req.method is Request.Method.GET:
|
||||
handle_bulletin_get(req, conn, server)
|
||||
else:
|
||||
send_404(conn)
|
||||
@@ -2,7 +2,16 @@
|
||||
|
||||
from msgpack.exceptions import OutOfData
|
||||
from packetserver.common import Message, Request, Response, PacketServerConnection
|
||||
from .bulletin import bulletin_root_handler
|
||||
import logging
|
||||
from typing import Union
|
||||
|
||||
def send_404(conn: PacketServerConnection, payload: Union[bytes, bytearray, str, dict] = ""):
|
||||
response_404 = Response.blank()
|
||||
response_404.status_code = 404
|
||||
response_404.payload = payload
|
||||
if conn.state.name == "CONNECTED":
|
||||
conn.send_data(response_404.pack())
|
||||
|
||||
def handle_root_get(req: Request, conn: PacketServerConnection,
|
||||
server: 'packetserver.server.Server'):
|
||||
@@ -22,15 +31,27 @@ def handle_root_get(req: Request, conn: PacketServerConnection,
|
||||
'motd': motd
|
||||
}
|
||||
|
||||
if conn.state.name == "CONNECTED":
|
||||
if conn.state.name == "CONNECTED" and not conn.closing:
|
||||
logging.debug(f"sending response: {response}, {response.compression}, {response.payload}")
|
||||
conn.send_data(response.pack())
|
||||
logging.debug("response sent successfully")
|
||||
|
||||
def root_root_handler(req: Request, conn: PacketServerConnection,
|
||||
server: 'packetserver.server.Server'):
|
||||
logging.debug(f"{req} got to root_root_handler")
|
||||
if req.method is Request.Method.GET:
|
||||
handle_root_get(req, conn, server)
|
||||
else:
|
||||
logging.warning(f"unhandled request found: {req}")
|
||||
response_404 = Response.blank()
|
||||
response_404.status_code = 404
|
||||
if (conn.state.name == "CONNECTED") and not conn.closing:
|
||||
conn.send_data(response_404.pack())
|
||||
logging.debug(f"Sent 404 in response to {req}")
|
||||
|
||||
standard_handlers = {
|
||||
"": {
|
||||
"GET": handle_root_get
|
||||
}
|
||||
"": root_root_handler,
|
||||
"bulletin": bulletin_root_handler
|
||||
}
|
||||
|
||||
def handle_request(req: Request, conn: PacketServerConnection,
|
||||
@@ -40,10 +61,10 @@ def handle_request(req: Request, conn: PacketServerConnection,
|
||||
if conn.closing:
|
||||
logging.debug("Connection marked as closing. Ignoring it.")
|
||||
return
|
||||
if req.path in server.handlers:
|
||||
if req.method.name in server.handlers[req.path]:
|
||||
req_root_path = req.path.split("/")[0]
|
||||
if req_root_path in server.handlers:
|
||||
logging.debug(f"found handler for req {req}")
|
||||
server.handlers[req.path][req.method.name](req, conn, server)
|
||||
server.handlers[req_root_path](req, conn, server)
|
||||
return
|
||||
logging.warning(f"unhandled request found: {req}")
|
||||
response_404 = Response.blank()
|
||||
|
||||
Reference in New Issue
Block a user