-
Notifications
You must be signed in to change notification settings - Fork 22
fix/wss for all #148
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
fix/wss for all #148
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,12 @@ | ||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||
|
|
||||||||||||||||||
| # One-time per machine: installs mkcert CA into the OS trust store and writes | ||||||||||||||||||
| # MKCERT_CAROOT to .env so compose can mount it for cert generation. | ||||||||||||||||||
| # Requires mkcert: brew install mkcert | choco install mkcert | ||||||||||||||||||
|
|
||||||||||||||||||
| command -v mkcert >/dev/null || { echo "mkcert not found"; exit 1; } | ||||||||||||||||||
|
|
||||||||||||||||||
| mkcert -install | ||||||||||||||||||
| echo "MKCERT_CAROOT=$(mkcert -CAROOT)" > "$(dirname "$0")/../.env" | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The 🛡️ Proposed fix — upsert only the MKCERT_CAROOT line-echo "MKCERT_CAROOT=$(mkcert -CAROOT)" > "$(dirname "$0")/../.env"
+ENV_FILE="$(dirname "$0")/../.env"
+CAROOT_LINE="MKCERT_CAROOT=$(mkcert -CAROOT)"
+if [ -f "$ENV_FILE" ] && grep -q '^MKCERT_CAROOT=' "$ENV_FILE"; then
+ sed -i "s|^MKCERT_CAROOT=.*|${CAROOT_LINE}|" "$ENV_FILE"
+else
+ echo "$CAROOT_LINE" >> "$ENV_FILE"
+fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| echo "Done. Run: docker compose --profile testing up -d" | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Completion message doesn't match The script prints 📝 Proposed fix-echo "Done. Run: docker compose --profile testing up -d"
+echo "Done. Run: npm run run-dev-stack"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -476,8 +476,7 @@ export class IRCClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create a new connection promise and store it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const connectionPromise = new Promise<Server>((resolve, reject) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // for local testing and automated tests, if domain is localhost or 127.0.0.1 use ws instead of wss | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let protocol = ["localhost", "127.0.0.1"].includes(host) ? "ws" : "wss"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let protocol: "wss" | "ircs" | "irc" = "wss"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let actualHost = host; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let actualPort = port; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -488,13 +487,19 @@ export class IRCClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol = parsed.scheme; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualHost = parsed.host; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualPort = parsed.port; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (host.startsWith("ws://") || host.startsWith("wss://")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Parse ws/wss URLs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const urlMatch = host.match(/^(wss?):\/\/([^:]+)(?::(\d+))?/); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (host.startsWith("wss://")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Parse wss:// URLs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const urlMatch = host.match(/^wss:\/\/([^:]+)(?::(\d+))?/); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (urlMatch) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol = urlMatch[1] as "ws" | "wss"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualHost = urlMatch[2]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualPort = urlMatch[3] ? Number.parseInt(urlMatch[3], 10) : port; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualHost = urlMatch[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualPort = urlMatch[2] ? Number.parseInt(urlMatch[2], 10) : port; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (host.startsWith("ws://")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Upgrade legacy ws:// to wss:// — unencrypted WebSockets are no longer supported | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const urlMatch = host.match(/^ws:\/\/([^:]+)(?::(\d+))?/); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (urlMatch) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualHost = urlMatch[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actualPort = urlMatch[2] ? Number.parseInt(urlMatch[2], 10) : port; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+490
to
503
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Two related issues in the new
🐛 Proposed fix — robust URL parsing for both branches-} else if (host.startsWith("wss://")) {
- // Parse wss:// URLs
- const urlMatch = host.match(/^wss:\/\/([^:]+)(?::(\d+))?/);
- if (urlMatch) {
- actualHost = urlMatch[1];
- actualPort = urlMatch[2] ? Number.parseInt(urlMatch[2], 10) : port;
- }
-} else if (host.startsWith("ws://")) {
- // Upgrade legacy ws:// to wss:// — unencrypted WebSockets are no longer supported
- const urlMatch = host.match(/^ws:\/\/([^:]+)(?::(\d+))?/);
- if (urlMatch) {
- actualHost = urlMatch[1];
- actualPort = urlMatch[2] ? Number.parseInt(urlMatch[2], 10) : port;
- }
-}
+} else if (host.startsWith("wss://") || host.startsWith("ws://")) {
+ if (host.startsWith("ws://")) {
+ // Upgrade legacy ws:// to wss:// — unencrypted WebSockets are no longer supported
+ console.warn(`[ircClient] Upgrading ws:// to wss:// for: ${host}`);
+ }
+ try {
+ // Use the URL API for robust parsing (handles IPv6, paths, etc.)
+ const parsed = new URL(host.startsWith("ws://") ? host.replace(/^ws:/, "wss:") : host);
+ actualHost = parsed.hostname; // strips brackets from IPv6
+ actualPort = parsed.port ? Number.parseInt(parsed.port, 10) : port;
+ } catch {
+ throw new Error(`Invalid WebSocket URL: ${host}`);
+ }
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.
🧩 Analysis chain
🌐 Web query:
Alpine Linux 3.20 openssl binary included by default💡 Result:
No—Alpine Linux 3.20 does not include the
opensslbinary by default in the minimal root filesystem used for containers (and thus the officialalpine:3.20Docker image). The default mini-rootfs package set isbusybox alpine-baselayout alpine-keys alpine-release apk-tools musl-utils(noopenssl) [1].If you need the
opensslcommand, install it explicitly:The
opensslpackage is available in Alpine 3.20’smainrepo (package nameopenssl) [2].Sources: [1], [2]
Early-exit guard can miss existing keys and always regenerates on fresh images.
The guard tries to use
openssl x509before OpenSSL is installed, so it always fails silently on fresh Alpine containers and regenerates unnecessarily. Additionally, it only checksserver.pem, so a missingserver-key.pemon container reuse could go undetected. Check both files exist before regenerating instead.🔧 Suggested guard that checks both files before regenerating
🤖 Prompt for AI Agents