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):
|
if ('p' in msg.data) and (type(msg.data['p']) is not str):
|
||||||
raise ValueError("Path of Request must be a string.")
|
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 'm' in msg.data:
|
||||||
if type(msg.data['m']) is not bytes:
|
if type(msg.data['m']) is not bytes:
|
||||||
raise ValueError("Method of Request must be bytes.")
|
raise ValueError("Method of Request must be bytes.")
|
||||||
@@ -207,7 +210,7 @@ class Request(Message):
|
|||||||
|
|
||||||
@path.setter
|
@path.setter
|
||||||
def path(self, path: str):
|
def path(self, path: str):
|
||||||
self.data['p'] = str(path.strip())
|
self.data['p'] = str(path).strip().lower()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def method(self) -> Method:
|
def method(self) -> Method:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import pe.app
|
import pe.app
|
||||||
import packetserver.common
|
import packetserver.common
|
||||||
from packetserver.server.constants import default_server_config
|
from packetserver.server.constants import default_server_config
|
||||||
|
from packetserver.server.bulletin import init_bulletins
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import ax25
|
import ax25
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -13,6 +14,7 @@ from packetserver.server.requests import standard_handlers
|
|||||||
import logging
|
import logging
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
class Server:
|
class Server:
|
||||||
@@ -46,6 +48,7 @@ class Server:
|
|||||||
conn.root.config['blacklist'] = PersistentList()
|
conn.root.config['blacklist'] = PersistentList()
|
||||||
if 'users' not in conn.root():
|
if 'users' not in conn.root():
|
||||||
conn.root.users = OOBTree()
|
conn.root.users = OOBTree()
|
||||||
|
init_bulletins(conn.root())
|
||||||
self.app = pe.app.Application()
|
self.app = pe.app.Application()
|
||||||
packetserver.common.PacketServerConnection.receive_subscribers.append(lambda x: self.server_receiver(x))
|
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))
|
packetserver.common.PacketServerConnection.connection_subscribers.append(lambda x: self.server_connection_bouncer(x))
|
||||||
@@ -83,6 +86,9 @@ class Server:
|
|||||||
logging.debug("running server receiver")
|
logging.debug("running server receiver")
|
||||||
process_incoming_data(conn, self)
|
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):
|
def start(self):
|
||||||
self.app.start(self.pe_server, self.pe_port)
|
self.app.start(self.pe_server, self.pe_port)
|
||||||
self.app.register_callsigns(self.callsign)
|
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 msgpack.exceptions import OutOfData
|
||||||
from packetserver.common import Message, Request, Response, PacketServerConnection
|
from packetserver.common import Message, Request, Response, PacketServerConnection
|
||||||
|
from .bulletin import bulletin_root_handler
|
||||||
import logging
|
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,
|
def handle_root_get(req: Request, conn: PacketServerConnection,
|
||||||
server: 'packetserver.server.Server'):
|
server: 'packetserver.server.Server'):
|
||||||
@@ -22,15 +31,27 @@ def handle_root_get(req: Request, conn: PacketServerConnection,
|
|||||||
'motd': motd
|
'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}")
|
logging.debug(f"sending response: {response}, {response.compression}, {response.payload}")
|
||||||
conn.send_data(response.pack())
|
conn.send_data(response.pack())
|
||||||
logging.debug("response sent successfully")
|
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 = {
|
standard_handlers = {
|
||||||
"": {
|
"": root_root_handler,
|
||||||
"GET": handle_root_get
|
"bulletin": bulletin_root_handler
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def handle_request(req: Request, conn: PacketServerConnection,
|
def handle_request(req: Request, conn: PacketServerConnection,
|
||||||
@@ -40,11 +61,11 @@ def handle_request(req: Request, conn: PacketServerConnection,
|
|||||||
if conn.closing:
|
if conn.closing:
|
||||||
logging.debug("Connection marked as closing. Ignoring it.")
|
logging.debug("Connection marked as closing. Ignoring it.")
|
||||||
return
|
return
|
||||||
if req.path in server.handlers:
|
req_root_path = req.path.split("/")[0]
|
||||||
if req.method.name in server.handlers[req.path]:
|
if req_root_path in server.handlers:
|
||||||
logging.debug(f"found handler for req {req}")
|
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
|
return
|
||||||
logging.warning(f"unhandled request found: {req}")
|
logging.warning(f"unhandled request found: {req}")
|
||||||
response_404 = Response.blank()
|
response_404 = Response.blank()
|
||||||
response_404.status_code = 404
|
response_404.status_code = 404
|
||||||
|
|||||||
Reference in New Issue
Block a user