zlh-grind/Session_Summaries/2026-03-21_IDE-Proxy-Working.md

97 lines
2.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2026-03-21 Dev IDE proxy working end-to-end
## Summary
After significant debugging, the browser IDE is fully working through the API
proxy. This was a non-trivial integration involving multiple interacting issues
that had to be resolved in sequence.
---
## What Was Fixed
### 1. Token bootstrap — fixed new-tab auth loss
Direct tab navigation loses `Authorization: Bearer` headers.
Solution: `POST /api/dev/:id/ide-token` returns a signed token. Bootstrap
route `GET /api/dev/:id/ide?token=...` validates it, sets an HTTP-only IDE
cookie, then redirects into the live tunnel.
### 2. Bootstrap vs live traffic separation
Routing all traffic through `/api/dev/:id/ide` caused interference with
normal API route behavior.
Solution: split into two paths:
- bootstrap: `/api/dev/:id/ide`
- live tunnel: `/__ide/:id/*`
### 3. Correct upstream port
Original assumption was `6000`. Chrome blocks port 6000 as unsafe.
Agent was updated to expose code-server on `8080`. API proxy updated to target `8080`.
### 4. Host header
code-server expects the browser-facing host preserved through the proxy.
Changed `Host` header from container host to `req.headers.host` (browser
host). Matches official code-server reverse-proxy guidance.
### 5. Origin override removed
Forcing `Origin` to backend target conflicted with browser-facing `Host`.
Changed to pass browser `Origin` through only when present.
### 6. WS target fallback bug — the main fix
HTTP requests were correctly targeting the container. WS requests were
falling back to `127.0.0.1:8080`.
Logs confirmed: `ECONNREFUSED 127.0.0.1:8080`
Root cause: shared proxy WS handling was losing per-request target context.
Fix: disabled WS on the shared `/__ide` HTTP proxy. Handled WebSocket
upgrades only in `attachDevProxyServer(server)`. Built a target-bound WS
proxy instance at upgrade time using the resolved container target. That
eliminated the localhost fallback entirely.
---
## Working Flow
```
1. frontend → POST /api/dev/:id/ide-token
2. API returns /api/dev/:id/ide?token=...
3. frontend opens URL in new tab
4. bootstrap validates token, sets IDE cookie, redirects to /__ide/:id/
5. live traffic proxied through /__ide/:id/*
6. API proxies HTTP + WS to http://<container-ip>:8080
```
---
## Files Involved
- `src/routes/devProxy.js`
- `src/app.js`
- `src/auth/tokens.js`
---
## Current Limitations
- browser still sees API host/IP until portal is behind a proper domain/reverse proxy
- host-based `dev-<vmid>.zlh.dev` routing started but reverted — bootstrap path is canonical
- service workers require HTTPS — extensions may not fully load until portal is behind SSL
---
## Next
- Portal "Open IDE" button implementation
- Portal behind HTTPS/domain (unblocks service workers and extension loading)
- Headscale/Tailscale for local dev access (SSH, VS Code Remote)