FastAPI integrator for Qelos: middleware that identifies the user and active workspace from the Qelos SDK before your handlers run
Project description
qelos-integrator-fastapi
FastAPI / Starlette integrator for Qelos. It runs as ASGI
middleware so your FastAPI host acts as a same-origin BFF for a managed Qelos
app: you can mount a catch-all /api/{path:path} router that proxies to
Qelos, and every other request gets request.state.qelos populated from
GET /api/me before your handlers run.
Install
pip install qelos-integrator-fastapi qelos-sdk
Requires Python 3.9+. The middleware and proxy use httpx (declared as a
direct dependency) and rely on httpx’s handling of multiple Set-Cookie
response headers (Headers.get_list("set-cookie") or equivalent) when
piping upstream cookies back to the browser.
Configure
from fastapi import FastAPI
from qelos_integrator_fastapi import QelosConfig, QelosIntegratorMiddleware, create_qelos_proxy_router
cfg = QelosConfig(
app_url="https://your-qelos-app.com",
require_auth=False,
skip_paths=["/health"],
)
app = FastAPI()
app.add_middleware(QelosIntegratorMiddleware, config=cfg)
app.include_router(create_qelos_proxy_router(cfg))
Or with the Starlette-friendly alias:
from qelos_integrator_fastapi import qelos_middleware
app.add_middleware(qelos_middleware, app_url="https://your-qelos-app.com")
API proxy
create_qelos_proxy_router returns an APIRouter that matches
/api/{path:path} for GET, POST, PUT, PATCH, DELETE,
OPTIONS, and HEAD. Include it on your app after your own
/api/... routes so explicit handlers stay authoritative; the proxy only
serves paths nothing else matched.
The proxy forwards the inbound Cookie header as-is (the Qelos session
cookie name is opaque), sets upstream Host to the managed-app origin, and
streams the response back. Every upstream Set-Cookie is forwarded with the
Domain= attribute rewritten to the inbound request’s Host (port
stripped) so the browser stores first-party cookies on your FastAPI domain.
Resolving the proxy target
The managed Qelos app URL (QelosConfig.app_url) is the default proxy target.
Environment variables are dev-time overrides when app_url is not
reachable from the machine running FastAPI:
QELOS_PROXY_TARGETQELOS_IPQELOS_API_IPQelosConfig.app_url
Whitespace-only env values are ignored. If nothing resolves, the proxy responds
with 503 and a JSON body with code: QELOS_PROXY_NOT_CONFIGURED.
Opting out
Set disable_proxy=True on QelosConfig when constructing the middleware.
When the proxy is not disabled, /api/ is automatically prepended to
skip_paths (unless already covered by an existing prefix) so inbound
/api/** requests are not processed by the user-resolution middleware. That
avoids double upstream calls to /api/me and cookie-rewrite loops when you use
the catch-all proxy.
WebSocket upgrades are not proxied; the router returns 501 for
Upgrade: websocket.
Middleware
On every request that is not skipped, the middleware:
- Builds a request-scoped
QelosSDK(see below). - Resolves the upstream origin the same way as the proxy
(
QELOS_PROXY_TARGET→QELOS_IP→QELOS_API_IP→app_url). - If neither a proxy target nor
api_tokenis configured, anonymous requests pass through (or 401 whenrequire_authis true). - When a target exists, issues
GET {target}/api/mewith the inboundCookieandAuthorizationheaders forwarded verbatim. For each upstreamSet-Cookie, rewritesDomain=to the inboundHostand appends it to the outgoing ASGI response. - On HTTP 2xx with JSON, that body becomes
request.state.qelos.user. On any other status or transport error,userisNone(and 401 ifrequire_auth). - Loads
sdk.workspaces.get_list()(errors become an empty list). - Sets
workspacefrom your optionalresolve_workspacecallback, or else fromuser["workspace"]as returned by/api/me— not fromworkspaces[0].
request.state.qelos is a QelosRequestContext:
| field | description |
|---|---|
user |
The /api/me JSON object, or None when anonymous. |
workspace |
The active workspace dict, or None. |
workspaces |
List of workspace dicts from the Qelos API. |
sdk |
QelosSDK bound to live Cookie / Authorization on each call. |
SDK behaviour
create_request_sdk(config, request) merges config.sdk_options into
QelosSDKOptions (camelCase keys from Node configs are normalized to
snake_case). If api_token is set, the SDK uses it and skips cookies.
Otherwise an extra_headers hook forwards the current request’s Cookie
and Authorization on every SDK request — no mutable token state and no
client-side refresh logic.
The middleware does not strip
Securefrom rotated cookies. Over plain HTTP, browsers may dropSecurecookies — configure Qelos accordingly or terminate TLS on your FastAPI host.
FastAPI dependencies
from typing import Annotated, Optional
from fastapi import Depends, FastAPI
from qelos_integrator_fastapi import QelosRequestContext, get_qelos, require_user
@app.get("/me")
async def me(qelos: Annotated[Optional[QelosRequestContext], Depends(get_qelos)]):
return {"user": qelos.user if qelos else None}
@app.get("/private")
async def private(qelos: Annotated[QelosRequestContext, Depends(require_user)]):
return qelos.user
Typed user model: get_qelos_user → QelosUser (Pydantic).
Workspace resolution
user["workspace"] is only present when the user has activated a workspace
on the Qelos side. To override selection, pass resolve_workspace to
QelosIntegratorMiddleware / qelos_middleware — a callable
(request, user, workspaces) (sync or async) returning a workspace dict or
None.
API token mode
For service-to-service traffic, set api_token on QelosConfig. The SDK
authenticates with that static token instead of forwarding browser cookies.
User resolution still uses GET /api/me when a proxy target can be resolved
from app_url or the dev override env vars; keep app_url set to your
managed Qelos origin unless you intentionally run in anonymous middleware mode
with token-only SDK calls.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qelos_integrator_fastapi-4.0.1.tar.gz.
File metadata
- Download URL: qelos_integrator_fastapi-4.0.1.tar.gz
- Upload date:
- Size: 16.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4496d48d399f8316506031d4aeeb51f108c062130f374cfdaee4969a5f378350
|
|
| MD5 |
6be609799926b568cf92c4890148153a
|
|
| BLAKE2b-256 |
077e299940e837c93affabf6047bab82e527282066e7b1c90a072e3816daa49c
|
File details
Details for the file qelos_integrator_fastapi-4.0.1-py3-none-any.whl.
File metadata
- Download URL: qelos_integrator_fastapi-4.0.1-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
862384fc57bd6f785643f5eb9fdc260ec210806cd30cd89feaea9306e7e1b92e
|
|
| MD5 |
31e6c0b637afde38a6d36b3d38e63e9c
|
|
| BLAKE2b-256 |
cb081da8ba810c1a2d5a3474e53973ff34bbf8256b7230f48284091661ff8698
|