package server import ( "context" "fmt" "net/http" "path/filepath" "strings" "time" "github.com/daniel/cursor-adapter/internal/bridge" ) const sessionHeaderName = "X-Cursor-Session-ID" const workspaceHeaderName = "X-Cursor-Workspace" const exposeHeadersName = "Access-Control-Expose-Headers" // requestContext attaches per-request bridge knobs (currently: workspace // override) read from headers onto ctx. func requestContext(r *http.Request) context.Context { ctx := r.Context() ws := strings.TrimSpace(r.Header.Get(workspaceHeaderName)) if ws != "" && filepath.IsAbs(ws) { ctx = bridge.WithWorkspaceOverride(ctx, ws) } return ctx } func ensureSessionHeader(w http.ResponseWriter, r *http.Request) string { sessionKey := strings.TrimSpace(r.Header.Get(sessionHeaderName)) if sessionKey == "" { sessionKey = fmt.Sprintf("csess_%d", time.Now().UnixNano()) } w.Header().Set(sessionHeaderName, sessionKey) existing := w.Header().Get(exposeHeadersName) if existing == "" { w.Header().Set(exposeHeadersName, sessionHeaderName) } else if !strings.Contains(strings.ToLower(existing), strings.ToLower(sessionHeaderName)) { w.Header().Set(exposeHeadersName, existing+", "+sessionHeaderName) } return sessionKey }