""" Registration routes for API Gateway - Handles registration-specific endpoints These endpoints don't require a tenant ID and are used during the registration flow """ from fastapi import APIRouter, Request, Response, HTTPException from fastapi.responses import JSONResponse import httpx import logging from typing import Optional from app.core.config import settings from app.core.header_manager import header_manager logger = logging.getLogger(__name__) router = APIRouter() # ================================================================ # REGISTRATION ENDPOINTS - Direct routing to tenant service # These endpoints are called during registration before a tenant exists # ================================================================ @router.post("/registration-payment-setup") async def proxy_registration_payment_setup(request: Request): """Proxy registration payment setup request to tenant service""" return await _proxy_to_tenant_service(request, "/api/v1/tenants/registration-payment-setup") @router.post("/verify-and-complete-registration") async def proxy_verify_and_complete_registration(request: Request): """Proxy verification and registration completion to tenant service""" return await _proxy_to_tenant_service(request, "/api/v1/tenants/verify-and-complete-registration") @router.post("/payment-customers/create") async def proxy_registration_customer_create(request: Request): """Proxy registration customer creation to tenant service""" return await _proxy_to_tenant_service(request, "/api/v1/payment-customers/create") @router.get("/setup-intents/{setup_intent_id}/verify") async def proxy_registration_setup_intent_verify(request: Request, setup_intent_id: str): """Proxy registration setup intent verification to tenant service""" return await _proxy_to_tenant_service(request, f"/api/v1/tenants/setup-intents/{setup_intent_id}/verify") # ================================================================ # PROXY HELPER FUNCTIONS # ================================================================ async def _proxy_to_tenant_service(request: Request, target_path: str): """Generic proxy function with enhanced error handling""" # Handle OPTIONS requests directly for CORS if request.method == "OPTIONS": return Response( status_code=200, headers={ "Access-Control-Allow-Origin": settings.CORS_ORIGINS_LIST, "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Tenant-ID, Stripe-Signature", "Access-Control-Allow-Credentials": "true", "Access-Control-Max-Age": "86400" } ) try: url = f"{settings.TENANT_SERVICE_URL}{target_path}" # Use unified HeaderManager for consistent header forwarding headers = header_manager.get_all_headers_for_proxy(request) # Debug logging logger.info(f"Forwarding registration request to {url}") # Get request body if present body = None if request.method in ["POST", "PUT", "PATCH"]: body = await request.body() # Add query parameters params = dict(request.query_params) timeout_config = httpx.Timeout( connect=30.0, read=60.0, write=30.0, pool=30.0 ) async with httpx.AsyncClient(timeout=timeout_config) as client: response = await client.request( method=request.method, url=url, headers=headers, content=body, params=params ) # Handle different response types if response.headers.get("content-type", "").startswith("application/json"): try: content = response.json() except: content = {"message": "Invalid JSON response from service"} else: content = response.text return JSONResponse( status_code=response.status_code, content=content ) except Exception as e: logger.error(f"Unexpected error proxying registration request to {settings.TENANT_SERVICE_URL}{target_path}: {e}") raise HTTPException( status_code=500, detail="Internal gateway error" )