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.