forked from retoor/devplacepy
fix: correct "bugs" to "issues" in routing table and README references across multiple documentation files
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from socketserver import ForkingMixIn
|
||||
from xmlrpc.server import SimpleXMLRPCDispatcher, SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
|
||||
|
||||
from devplacepy.config import XMLRPC_BIND, XMLRPC_PORT
|
||||
from . import bridge
|
||||
from .registry import Method, build_index, method_help, method_signature
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
||||
)
|
||||
logger = logging.getLogger("xmlrpc.server")
|
||||
|
||||
RPC_PATHS = ("/", "/RPC2", "/xmlrpc")
|
||||
|
||||
|
||||
def _auth_from_headers(headers) -> dict[str, str]:
|
||||
auth: dict[str, str] = {}
|
||||
api_key = headers.get("X-API-KEY") or headers.get("x-api-key")
|
||||
authorization = headers.get("Authorization") or headers.get("authorization") or ""
|
||||
if not api_key and authorization.lower().startswith("bearer "):
|
||||
api_key = authorization[7:].strip()
|
||||
if authorization.lower().startswith("basic "):
|
||||
auth["authorization"] = authorization.strip()
|
||||
if api_key:
|
||||
auth["api_key"] = api_key.strip()
|
||||
real_ip = headers.get("X-Real-IP") or headers.get("x-real-ip")
|
||||
if real_ip:
|
||||
auth["real_ip"] = real_ip
|
||||
forwarded = headers.get("X-Forwarded-For") or headers.get("x-forwarded-for")
|
||||
if forwarded:
|
||||
auth["forwarded_for"] = forwarded
|
||||
return auth
|
||||
|
||||
|
||||
class _RequestHandler(SimpleXMLRPCRequestHandler):
|
||||
rpc_paths = RPC_PATHS
|
||||
|
||||
def decode_request_content(self, data):
|
||||
self.server.current_auth = _auth_from_headers(self.headers)
|
||||
return super().decode_request_content(data)
|
||||
|
||||
def log_message(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
|
||||
class BridgeDispatcher(SimpleXMLRPCDispatcher):
|
||||
def system_methodHelp(self, method_name):
|
||||
target = self.index.get(method_name)
|
||||
if target is not None:
|
||||
return method_help(target)
|
||||
return super().system_methodHelp(method_name)
|
||||
|
||||
def system_methodSignature(self, method_name):
|
||||
target = self.index.get(method_name)
|
||||
if target is not None:
|
||||
return method_signature(target)
|
||||
return super().system_methodSignature(method_name)
|
||||
|
||||
|
||||
class ForkingXMLRPCServer(ForkingMixIn, BridgeDispatcher, SimpleXMLRPCServer):
|
||||
allow_reuse_address = True
|
||||
daemon_threads = True
|
||||
|
||||
def __init__(self, addr, index):
|
||||
self.index = index
|
||||
self.current_auth: dict[str, str] = {}
|
||||
SimpleXMLRPCServer.__init__(
|
||||
self,
|
||||
addr,
|
||||
requestHandler=_RequestHandler,
|
||||
allow_none=True,
|
||||
logRequests=False,
|
||||
)
|
||||
|
||||
|
||||
def _make_handler(server: "ForkingXMLRPCServer", method: Method):
|
||||
def handler(*args):
|
||||
params = args[0] if args else {}
|
||||
return bridge.call(method, params, server.current_auth)
|
||||
|
||||
handler.__name__ = method.name
|
||||
handler.__doc__ = method_help(method)
|
||||
return handler
|
||||
|
||||
|
||||
def build_server(host: str, port: int) -> ForkingXMLRPCServer:
|
||||
index = build_index()
|
||||
server = ForkingXMLRPCServer((host, port), index)
|
||||
server.register_introspection_functions()
|
||||
server.register_multicall_functions()
|
||||
for name, method in index.items():
|
||||
server.register_function(_make_handler(server, method), name)
|
||||
logger.info("XML-RPC bridge registered %d methods", len(index))
|
||||
return server
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = build_server(XMLRPC_BIND, XMLRPC_PORT)
|
||||
logger.info("Forking XML-RPC server listening on %s:%d", XMLRPC_BIND, XMLRPC_PORT)
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
logger.info("XML-RPC server interrupted")
|
||||
finally:
|
||||
server.server_close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user