Extend defhandler with :path/:method/:csrf, migrate 12 ref endpoints to SX
defhandler now supports keyword options for public route registration: (defhandler name :path "/..." :method :post :csrf false (&key) body) Infrastructure: forms.sx parses options, HandlerDef stores path/method/csrf, register_route_handlers() mounts path-based handlers as app routes. New IO primitives (boundary.sx "Web interop" section): now, sleep, request-form, request-json, request-header, request-content-type. First migration: 12 reference API endpoints from Python f-string SX to declarative .sx handlers in sx/sx/handlers/ref-api.sx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -215,6 +215,56 @@ def create_handler_blueprint(service_name: str) -> Any:
|
||||
return bp
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Public route registration — handlers with :path get mounted as routes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def register_route_handlers(app_or_bp: Any, service_name: str) -> int:
|
||||
"""Register public routes for all handlers with :path defined.
|
||||
|
||||
Returns the number of routes registered.
|
||||
"""
|
||||
from quart import Response, request
|
||||
from shared.browser.app.csrf import csrf_exempt
|
||||
|
||||
handlers = get_all_handlers(service_name)
|
||||
count = 0
|
||||
|
||||
for name, hdef in handlers.items():
|
||||
if not hdef.is_route:
|
||||
continue
|
||||
|
||||
# Capture hdef in closure
|
||||
_hdef = hdef
|
||||
|
||||
async def _route_view(_h=_hdef, **path_kwargs):
|
||||
from shared.sx.helpers import sx_response
|
||||
args = dict(request.args)
|
||||
args.update(path_kwargs)
|
||||
result = await execute_handler(_h, service_name, args=args)
|
||||
return sx_response(result)
|
||||
|
||||
endpoint = f"sx_route_{name}"
|
||||
view_fn = _route_view
|
||||
|
||||
if not _hdef.csrf:
|
||||
view_fn = csrf_exempt(view_fn)
|
||||
|
||||
method = _hdef.method.lower()
|
||||
route_reg = getattr(app_or_bp, method, None)
|
||||
if route_reg is None:
|
||||
logger.warning("Unsupported HTTP method %s for handler %s",
|
||||
_hdef.method, name)
|
||||
continue
|
||||
|
||||
route_reg(_hdef.path, endpoint=endpoint)(view_fn)
|
||||
logger.info("Registered route %s %s → handler:%s",
|
||||
_hdef.method.upper(), _hdef.path, name)
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Direct app mount — replaces per-service fragment blueprint boilerplate
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user