Skip to content

HTTP Server ​

The HTTP gateway is the entrance to the system. It handles REST, WebSockets, and SSE. It is designed for maximum security and transparency.

Security Hardening (Default-On) ​

MicroCoreOS applies strict security policies to protect domains from common web vulnerabilities.

1. Secure Cookies ​

All cookies set via context.set_cookie() have safe defaults:

  • Secure=True: Only sent over HTTPS.
  • HttpOnly=True: Invisible to JavaScript (prevents XSS data theft).
  • SameSite=Lax: Prevents basic cross-site request forgery.

2. CSRF Guard ​

The gateway implements a modern CSRF protection mechanism for mutation methods (POST, PUT, DELETE, PATCH):

  • If authentication is done via Cookies (access_token), the client MUST send the X-Requested-With header.
  • If authentication is done via Bearer Token (Authorization header), no extra guard is needed as it is immune to CSRF.

3. Swagger UI Lock Icon ​

Any endpoint registered with auth_validator gets a documentation-only HTTPBearer dependency attached to it. This is what makes Swagger UI (/docs) show a lock icon on the route and lets you click Authorize once, paste a Bearer token, and have it applied to every "Try it out" call. auto_error=False keeps this dependency purely cosmetic: it never rejects a request on its own — the real check still happens in the request pipeline via the auth_validator you passed to add_endpoint/add_sse_endpoint.

4. Client IP Resolution & Trusted Proxies ​

When running behind load balancers, reverse proxies, or CDNs (e.g. Cloudflare, NGINX, AWS ALB), client IP spoofing via X-Forwarded-For is a critical security vector. MicroCoreOS enforces strict Right-to-Left (R-to-L) IP traversal:

  • HTTP_TRUSTED_PROXIES: Comma-separated list of trusted upstream IP addresses or CIDR ranges (e.g. 10.0.0.0/8,172.16.0.0/12,192.168.1.50).
    • The pipeline checks the immediate peer socket IP. If it is in HTTP_TRUSTED_PROXIES, it parses X-Forwarded-For from right to left, stopping at the first untrusted IP (the real client).
    • If HTTP_TRUSTED_PROXIES is unset, context.client_ip strictly returns the direct peer socket IP, ignoring spoofed headers.
    • Set HTTP_TRUSTED_PROXIES="*" for zero-friction local development (e.g. Vite proxy, Docker dev bridges). A security warning is logged if the server binds to 0.0.0.0 with *.
  • HTTP_CUSTOM_CLIENT_IP_HEADER: Generic header name for edge proxies/CDNs providing an explicit client IP header (e.g. X-Real-IP, True-Client-IP, CF-Connecting-IP). Evaluated only when the immediate peer is a trusted proxy.
  • HTTP_TRUST_CLOUDFLARE=true|false: Convenience flag to trust CF-Connecting-IP when the peer is in Cloudflare IP ranges.

context.client_ip exposes this resolved IP as a pure signal to plugins (for identity-aware rate limiting, geo-fencing, or audit logs) without imposing kernel-level blocking policies.

5. WebSocket Origin Policy (CSWSH Guard) ​

WebSockets are not bound by the browser's Same-Origin Policy during initial handshake. Without origin verification, malicious sites can execute Cross-Site WebSocket Hijacking (CSWSH). MicroCoreOS provides built-in origin policy enforcement:

  • HTTP_WS_ORIGIN_POLICY:
    • "off" (default): Accepts WebSocket connections from any origin.
    • "allowlist": Enforces strict origin matching against HTTP_WS_ORIGINS.
  • HTTP_WS_ORIGINS: Comma-separated canonical origins (e.g. https://example.com,https://app.example.com). Wildcards (*) and null origins are strictly forbidden in allowlist mode.
  • HTTP_WS_ALLOW_MISSING_ORIGIN=true|false: When false (default), non-browser clients or requests lacking an Origin header are rejected. Set to true if mobile or native desktop apps connect without sending an Origin header.

When a connection breaches policy, MicroCoreOS rejects the handshake immediately and closes the socket with WebSocket Close Code 1008 (Policy Violation) before invoking any auth validator or plugin handler.

The Request Pipeline ​

When a request hits the gateway:

  1. Assembly: Path, Query, and Body params are merged into a single data dictionary.
  2. Causality: A unique request_id is assigned (or honored from the X-Request-ID header) and set in current_event_id_var.
  3. Identity: The plugin handler's name is set in current_identity_var for log attribution.
  4. Authentication: If auth_validator was provided to add_endpoint, the token is extracted and validated. On failure, returns HTTP 401. On success, the payload is injected into data["_auth"].
  5. Dispatch: The handler is executed.

INFO

If a request_model is provided, FastAPI validates the request body before this pipeline runs (step 0). Validation errors return HTTP 422 automatically.

Automatic Route Sorting ​

Frameworks often have issues when a parameterized route (like /users/{id}) "shadows" a static route (like /users/me).

The HTTP tool automatically sorts all endpoints before registration:

  • Static paths (no {}) are registered first.
  • Parameterized paths are registered last.

This means you can define your plugins in any order, and /users/me will always work correctly without being intercepted by /users/{id}.

Implementation Patterns ​

REST Endpoints ​

python
async def on_boot(self):
    self.http.add_endpoint(
        path="/profiles/{id}",
        method="GET",
        handler=self.get_profile,
        response_model=ProfileResponse
    )

async def get_profile(self, data: dict, context: HttpContext):
    user_id = data["id"]
    # Logic...
    return {"success": True, "data": {...}}

Response Manipulation (HttpContext) ​

The context object allows controlling the raw HTTP response:

  • context.set_status(201): Change status code.
  • context.set_header("X-App", "Core"): Add custom header.
  • context.set_cookie("access_token", value, max_age=3600): Set a secure cookie (HttpOnly=True, Secure=True, SameSite=Lax by default).
  • context.redirect("/dashboard", status=302): Redirect the browser. The handler's return value is ignored.
  • context.set_binary_response(bytes, "image/png"): Return non-JSON data. The handler's return value is ignored.

Response Contract ​

Every endpoint (unless binary) MUST return a JSON envelope:

  • Success: {"success": True, "data": {...}}
  • Error: {"success": False, "error": "Reason"}

The tool automatically catches unhandled exceptions and returns a consistent 500 Internal server error to the client while logging the real cause server-side — this is the Safe Error Reporting pattern: log technically, respond safely.

Released under the MIT License.