Production Trailing Slash Redirect
A small FastAPI trailing-slash redirect became visible only after the app moved behind real HTTPS and Railway's proxy.
Production Trailing Slash Redirect
Problem
During the first production smoke test on summry.xyz, Google sign-in worked, but submitting a YouTube URL failed with a browser mixed-content error.
The request started correctly over HTTPS:
POST https://<api-domain>/chat
But the API returned a 307 Temporary Redirect with this location:
http://<api-domain>/chat/
The browser blocked the follow-up request because the page was loaded over HTTPS and the redirect attempted to downgrade the API call to HTTP.
Context
FastAPI uses Starlette routing underneath. Starlette redirects between slash and non-slash paths by default when a matching route exists.
Summry's backend route is registered as:
router = APIRouter(prefix="/chat")
@router.post("/")
def create_chat(...):
...
That means the canonical route is:
/chat/
The frontend was calling:
/chat
Locally this was harmless because the redirect stayed inside local HTTP:
http://localhost:3000 -> http://localhost:8000/chat -> http://localhost:8000/chat/
Production made the issue visible because the HTTPS request passed through Railway's edge and the generated redirect location used http://.
Implementation
The frontend now calls the canonical backend path directly:
/chat/
This avoids the redirect completely instead of relying on proxy-aware redirect behavior.
Tradeoffs
This is a small, direct fix. It keeps the backend route shape and generated OpenAPI path unchanged.
The tradeoff is that the frontend has to be precise about trailing slashes. That is acceptable here because the generated API schema already exposes /chat/, and matching the backend contract is cleaner than changing global router behavior during launch stabilization.
Lessons Learned
Localhost can hide production-only redirect issues because local development does not exercise the same HTTPS, proxy, and browser mixed-content rules.
The actual bug was not "the API is down" or "CORS is broken." It was a route mismatch that only became user-visible when a redirect crossed a secure production boundary.
For production validation, network tab details matter:
- original request URL
- response status
- redirect
Location - request scheme after redirects
- final browser security error
Next Steps
Keep an eye out for other slash mismatches between frontend calls and FastAPI routes. If these become frequent, consider standardizing route definitions or generated-client usage so frontend paths come directly from the OpenAPI contract.