Skip to content

Instantly share code, notes, and snippets.

@svandragt
Created February 20, 2026 14:07
Show Gist options
  • Select an option

  • Save svandragt/949e01096573a583bda7a97751857cff to your computer and use it in GitHub Desktop.

Select an option

Save svandragt/949e01096573a583bda7a97751857cff to your computer and use it in GitHub Desktop.
Ollama Proxy Script
import os
from typing import Dict
import httpx
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
OLLAMA_BASE = os.getenv("OLLAMA_BASE", "http://127.0.0.1:11434")
ALLOWED_ORIGINS = [
"https://workledger.org",
]
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=ALLOWED_ORIGINS,
allow_credentials=False,
allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allow_headers=["*"],
)
client = httpx.AsyncClient(timeout=60.0)
HOP_BY_HOP = {
"connection",
"keep-alive",
"proxy-authenticate",
"proxy-authorization",
"te",
"trailer",
"transfer-encoding",
"upgrade",
}
def _filtered_headers(headers: Dict[str, str]) -> Dict[str, str]:
out: Dict[str, str] = {}
for k, v in headers.items():
lk = k.lower()
if lk in HOP_BY_HOP:
continue
if lk in {"host", "origin", "content-length"}:
continue
out[k] = v
return out
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"])
async def proxy(path: str, request: Request) -> Response:
url = f"{OLLAMA_BASE}/{path}"
body = await request.body()
upstream = await client.request(
method=request.method,
url=url,
params=request.query_params,
content=body if body else None,
headers=_filtered_headers(dict(request.headers)),
)
resp_headers = {k: v for k, v in upstream.headers.items() if k.lower() not in HOP_BY_HOP}
return Response(
content=upstream.content,
status_code=upstream.status_code,
headers=resp_headers,
media_type=upstream.headers.get("content-type"),
)
@svandragt
Copy link
Author

svandragt commented Feb 20, 2026

If you’re seeing Missing CORS origin because the webapp is a different origin from localhost, and Ollama isn’t sending Access-Control-Allow-Origin for it.

Even with CORS fixed, you may also need to address HTTPS→HTTP restrictions and preflight behavior.

The robust solution is usually a local bridge/proxy that explicitly authorizes the webapp and mediates access to Ollama.

Run uv run --with fastapi --with "uvicorn[standard]" --with httpx \ uvicorn ollama_proxy:app --host 127.0.0.1 --port 8008.

Set the Ollama base URL / host to: http://127.0.0.1:8008. Now when it calls: /api/tags it will hit the proxy and get forwarded to: http://127.0.0.1:11434/api/tags

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment