-
Notifications
You must be signed in to change notification settings - Fork 454
Improve headlamp port clashes #4121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Improve headlamp port clashes #4121
Conversation
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: joaquimrocha The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
b28437e to
ea98bad
Compare
b921cb2 to
2b17d29
Compare
1e11684 to
574e504
Compare
574e504 to
b921cb2
Compare
|
Nevermind those commits I added before. That was a branch name confusion. I have added the right commits back. |
| if (err.code === 'EADDRINUSE') { | ||
| resolve(false); | ||
| } else { | ||
| resolve(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like this if is not needed
b921cb2 to
f35248e
Compare
|
rebased against main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like headlamp app runs now with the backend server running in another terminal, but the output for the app start command still shows localhost:4466 as the listen address.
maybe the testing steps could be updated too because I got inconsistent output across different start commands (npm run star sometimes showed 4467 but npm run start consistently shows 4466)
Can you share how you tested?
Are you sure you do not have any instance running when you start the commands? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements dynamic backend port configuration for Headlamp's Electron app to support multiple running instances. It introduces automatic port discovery (trying ports 4466-4565 by default), allows the frontend to dynamically connect to the backend's actual port, and adds user dialogs to handle port conflicts with existing Headlamp processes.
- Adds automatic port selection with fallback when default port 4466 is occupied
- Refactors frontend URL generation to use runtime port configuration via
window.headlampBackendPort - Implements port conflict detection and resolution with user prompts
- Adds internationalization strings for new port-related error dialogs
Reviewed Changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/vite.config.ts | Adds HEADLAMP_PORT environment variable support for configurable backend port in Vite dev proxy |
| frontend/src/lib/k8s/api/v2/webSocket.ts | Replaces static BASE_WS_URL with getBaseWsUrl() function for runtime port resolution |
| frontend/src/lib/k8s/api/v2/fetch.ts | Updates backendFetch to use getAppUrl() directly instead of static BASE_HTTP_URL |
| frontend/src/lib/k8s/api/v1/streamingApi.ts | Replaces static BASE_WS_URL with getBaseWsUrl() function for WebSocket connections |
| frontend/src/lib/k8s/api/v1/constants.ts | Adds deprecation warning for BASE_HTTP_URL constant |
| frontend/src/lib/k8s/api/v1/clusterRequests.ts | Updates clusterRequest to use getAppUrl() directly instead of static constant |
| frontend/src/i18n/locales/*/app.json | Adds translation placeholders for port conflict error messages |
| frontend/src/helpers/getAppUrl.ts | Implements window.headlampBackendPort support and refactors port selection logic |
| app/scripts/start.js | Passes environment variables to frontend process (minor change) |
| app/electron/preload.ts | Adds IPC channels for backend port communication |
| app/electron/main.ts | Implements port discovery, conflict detection, and injects actualPort into window object |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (err.code === 'EADDRINUSE') { | ||
| resolve(false); | ||
| } else { | ||
| resolve(false); | ||
| } |
Copilot
AI
Nov 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The if-else branches have identical logic (both resolve(false)). This can be simplified to just resolve(false) without the conditional check.
| if (err.code === 'EADDRINUSE') { | |
| resolve(false); | |
| } else { | |
| resolve(false); | |
| } | |
| resolve(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a bug. Not sure about the solution suggested.
| } | ||
|
|
||
| // Inject the backend port into the window object | ||
| mainWindow?.webContents.executeJavaScript(`window.headlampBackendPort = ${actualPort};`); |
Copilot
AI
Nov 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Direct string interpolation in executeJavaScript can be vulnerable to injection if actualPort is not properly validated. Although actualPort is a number in this context, it's better to use JSON.stringify or validate that actualPort is indeed a number before injection.
| mainWindow?.webContents.executeJavaScript(`window.headlampBackendPort = ${actualPort};`); | |
| mainWindow?.webContents.executeJavaScript(`window.headlampBackendPort = ${JSON.stringify(actualPort)};`); |
|
|
||
| // Update the environment variable for the frontend | ||
| if (mainWindow) { | ||
| mainWindow.webContents.executeJavaScript(`window.headlampBackendPort = ${actualPort};`); |
Copilot
AI
Nov 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Direct string interpolation in executeJavaScript can be vulnerable to injection if actualPort is not properly validated. Although actualPort is a number in this context, it's better to use JSON.stringify or validate that actualPort is indeed a number before injection.
| mainWindow.webContents.executeJavaScript(`window.headlampBackendPort = ${actualPort};`); | |
| mainWindow.webContents.executeJavaScript(`window.headlampBackendPort = ${JSON.stringify(actualPort)};`); |
| ); | ||
| return headlampOnPort.map(p => p.pid); | ||
| } catch (error) { | ||
| console.error(`Error checking if port ${port} is used by Headlamp:`, error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove "Headlamp"? Because it might be called something else.
(and in other parts of this PR/file too)
|
I closed the copilot notes which were wrong. Reviewed it, except for the main.ts electron stuff in detail. I added a bit of a testing checklist for things I think could be broken. |
Summary
This PR improves the UX when there's already a service using the default port that Headlamp's backend uses.
It also stops showing the dialog when there's already a running headlamp-server process, unless it ran out of ports to try.
Related Issue
Fixes #3447
Steps to Test
Regular conflict:
No ports available because headlamp-server is occupying them:
export HEADLAMP_MAX_PORT_ATTEMPTS=1and run the Healdamp app -> Should show a dialog saying that there are no ports free and offering the user the possibility to terminate the other processes or quit the appNo ports available because another process is occupying them:
python3 -m http.server 4466export HEADLAMP_MAX_PORT_ATTEMPTS=1and run the Healdamp app -> Should show a dialog saying that there are no ports free but not offer the possibility to kill those processes.Testing done
cd app && npm run star