Route browser workspaces by path hash#12
Conversation
The single shared HTTP server only ever knew about one workspace root, so
opening the IDE in a browser always showed whichever window launched first.
Hand the per-window session registry to the HTTP server and resolve a
/{hash}/ URL prefix (a stable hash of the workspace folder path) to the
matching open workspace. A pre-routing middleware strips the prefix and
scopes the request; a bare / lists the open workspaces, and the hosted
frontend prepends its hash to every API call.
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitButler <gitbutler@gitbutler.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the local HTTP server + hosted frontend so browser-served IDE sessions are routed to the correct open workspace using a stable /{hash}/ URL prefix derived from the workspace root path (fixing the prior “first window wins” behavior).
Changes:
- Frontend: prepend the current
/{hash}prefix to hosted API calls so requests stay scoped to the correct workspace. - Backend: add a pre-routing Axum middleware that resolves
/{hash}/...to an open workspace session, strips the prefix, and injects the resolved workspace into request extensions. - Backend: add a
/api/workspacesendpoint and a bare/chooser page (with redirect when only one workspace is open).
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/tauri.ts |
Adds workspacePathPrefix() and uses it to scope hosted HTTP API calls under /{hash}/. |
src/tauri.test.ts |
Adds unit tests covering workspacePathPrefix() behavior for dev vs hosted routing. |
src-tauri/src/lib.rs |
Exposes per-window session state for routing and adds workspace_root_hash() + tests. |
src-tauri/src/http_server.rs |
Implements hash-based workspace resolver middleware, chooser UI, and /api/workspaces; updates handlers to use resolved workspace context. |
src-tauri/Cargo.toml |
Adds tower dependency (util feature) for service helpers in routing/tests. |
src-tauri/Cargo.lock |
Locks in tower dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Code Review
This pull request introduces multi-workspace support to the HTTP server by adding a middleware that resolves and rewrites requests prefixed with a workspace hash to their corresponding workspace session. It also adds a workspace chooser landing page and updates the frontend to include the workspace path prefix in API calls. The review feedback focuses on performance optimizations on the hot path of HTTP requests, specifically recommending the removal of synchronous blocking filesystem I/O in workspace_root_hash and refactoring split_workspace_prefix to return string slices instead of allocating new Strings, along with the necessary updates to the middleware and unit tests.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: GitButler <gitbutler@gitbutler.com>
- Drop per-request canonicalize() from workspace_root_hash; roots are
already canonical at open time, so hash the stored string directly and
soften the doc comment about cross-version stability.
- Return borrowed slices from split_workspace_prefix to avoid allocating
on every request; format the rewritten path only when a rewrite happens.
- Strip a hash-shaped prefix even when it doesn't resolve, so stale
/{hash}/ bookmarks fall back to the shared root and chooser instead of
serving SPA HTML from /{hash}/api/... paths.
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitButler <gitbutler@gitbutler.com>
Borrow the request path and only allocate the candidate hash + rewritten path when a hash-shaped prefix is actually present, so unscoped requests (the hot path) allocate nothing. Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: GitButler <gitbutler@gitbutler.com>
Summary
/{hash}/URL prefix (a stable hash of the workspace folder path) to the matching open workspace./mcp, and Codex paths are unchanged./now lists the open workspaces (single workspace redirects straight in), backed by a new/api/workspacesendpoint. The hosted frontend prepends its hash to every API call.Notes
Router::layerruns after routing in axum, so the URI-rewriting resolver wraps the whole router from the outside to run before route matching. The in-process router test is what caught this.Test plan
cargo test— 134 passing, including a full-router integration test that drives/{hash}/api/...,/{hash}/, and/through the real axum stacknpm test— 275 passing, with aworkspacePathPrefixcasecargo clippyclean,npm run buildsucceeds/{hash}/shows its own tree in a browser