tidy tunnel script

Kim committed Mar 13, 2026 at 10:00 UTC 159b58b554557c56641daafc4e6b8dda2e034184
2 files changed +34 -77
cmd/portal-tunnel/main.go
+24 -43
@@ -69,15 +69,16 @@ func runExposeCommand(args []string) error {
69 fs := flag.NewFlagSet("expose", flag.ContinueOnError)
70 fs.SetOutput(io.Discard)
71
72 - var relayCSV string
73 - var target string
74 - var name string
75 - var desc string
76 - var tags string
77 - var thumbnail string
78 - var owner string
79 - var hide bool
80 -
72 + var (
73 + relayCSV string
74 + target string
75 + name string
76 + desc string
77 + tags string
78 + thumbnail string
79 + owner string
80 + hide bool
81 + )
82 fs.StringVar(&relayCSV, "relays", "", "Additional Portal relay server API URLs (comma-separated; scheme omitted defaults to https)")
83 fs.BoolVar(&defaultRelays, "default-relays", defaultRelays, "Include public registry relays")
84 fs.StringVar(&name, "name", "", "Public hostname prefix (single DNS label); auto-generated when omitted")
@@ -90,8 +91,7 @@ func runExposeCommand(args []string) error {
91 printExposeUsage(fs.Output())
92 }
93
93 - parseArgs := moveFirstPositionalToEnd(args)
94 - if err := fs.Parse(parseArgs); err != nil {
94 + if err := fs.Parse(args); err != nil {
95 printExposeUsage(os.Stderr)
96 return err
97 }
@@ -103,10 +103,20 @@ func runExposeCommand(args []string) error {
103 target = positionals[0]
104 }
105
106 - target, err = normalizeExposeTarget(target)
107 - if err != nil {
106 + target = strings.TrimSpace(target)
107 + if target == "" {
108 printExposeUsage(os.Stderr)
109 - return err
109 + return errors.New("target is required")
110 + }
111 + if _, err := strconv.Atoi(target); err == nil {
112 + target = net.JoinHostPort("127.0.0.1", target)
113 + } else {
114 + targetAddr, err := utils.NormalizeTargetAddr(target)
115 + if err != nil {
116 + printExposeUsage(os.Stderr)
117 + return fmt.Errorf("invalid target %q: %w", target, err)
118 + }
119 + target = targetAddr
120 }
121
122 if strings.TrimSpace(name) == "" {
@@ -280,35 +290,6 @@ func resolveRelayURLs(ctx context.Context, registryURL string, inputs []string,
290 return utils.NormalizeRelayURLs(inputs)
291 }
292
283 -func moveFirstPositionalToEnd(args []string) []string {
284 - if len(args) == 0 {
285 - return nil
286 - }
287 - first := strings.TrimSpace(args[0])
288 - if first == "" || strings.HasPrefix(first, "-") {
289 - return append([]string(nil), args...)
290 - }
291 - normalized := append([]string(nil), args[1:]...)
292 - return append(normalized, first)
293 -}
294 -
295 -func normalizeExposeTarget(raw string) (string, error) {
296 - raw = strings.TrimSpace(raw)
297 - if raw == "" {
298 - return "", errors.New("target is required")
299 - }
300 -
301 - if _, err := strconv.Atoi(raw); err == nil {
302 - return net.JoinHostPort("127.0.0.1", raw), nil
303 - }
304 -
305 - targetAddr, err := utils.NormalizeTargetAddr(raw)
306 - if err != nil {
307 - return "", fmt.Errorf("invalid target %q: %w", raw, err)
308 - }
309 - return targetAddr, nil
310 -}
311 -
293 func defaultExposeName(target, clientID string) (string, error) {
294 trimmed := strings.TrimSpace(clientID)
295 if trimmed == "" {
cmd/relay-server/tunnel.go
+10 -34
@@ -92,18 +92,6 @@ pick_install_path() {
92 fi
93 fi
94
95 - OLD_IFS="$IFS"
96 - IFS=':'
97 - for DIR in $PATH; do
98 - [ -n "$DIR" ] || continue
99 - if [ -d "$DIR" ] && [ -w "$DIR" ]; then
100 - IFS="$OLD_IFS"
101 - printf '%%s\n' "$DIR/portal"
102 - return 0
103 - fi
104 - done
105 - IFS="$OLD_IFS"
106 -
95 if [ -n "${HOME:-}" ]; then
96 for DIR in "$HOME/.local/bin" "$HOME/bin"; do
97 mkdir -p "$DIR" 2>/dev/null || true
@@ -129,7 +117,7 @@ EOF
117 }
118
119 INSTALL_PATH="$(pick_install_path)" || {
132 - echo "No writable install directory found. Create a writable PATH entry or install manually." >&2
120 + echo "No writable install directory found. Ensure an existing portal install is writable or create \$HOME/.local/bin or \$HOME/bin." >&2
121 exit 1
122 }
123
@@ -152,14 +140,11 @@ echo "Next step:" >&2
140 echo " portal expose 3000" >&2
141 `
142
155 -const installPowerShellTemplatePrefix = `$ErrorActionPreference = "Stop"
143 +const installPowerShellTemplate = `$ErrorActionPreference = "Stop"
144 $BaseUrl = if ($env:BASE_URL) { $env:BASE_URL } else { "%s" }
145 $OriginalSecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol
146 [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
147 $WorkDir = $null
160 -`
161 -
162 -const installPowerShellTemplateSuffix = `
148 try {
149 $Arch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE }
150 if ($Arch -eq "ARM64") {
@@ -280,24 +265,16 @@ func serveInstallBinary(w http.ResponseWriter, r *http.Request) {
265 }
266
267 func installBinaryBySlug(slug string) ([]byte, string, bool) {
283 - filename := installBinaryName(slug)
268 + filename := "portal-" + slug
269 + if strings.HasPrefix(slug, "windows-") {
270 + filename += ".exe"
271 + }
272 if data, err := embeddedDistFS.ReadFile("dist/tunnel/" + filename); err == nil {
273 return data, filename, true
274 }
275 return nil, "", false
276 }
277
290 -func installBinaryName(slug string) string {
291 - if strings.HasPrefix(slug, "windows-") {
292 - return "portal-" + slug + ".exe"
293 - }
294 - return "portal-" + slug
295 -}
296 -
297 -type installerConfig struct {
298 - Relays []string `json:"relays"`
299 -}
300 -
278 func serveInstallScript(w http.ResponseWriter, r *http.Request, portalURL string, isWindows bool) {
279 if r.Method != http.MethodGet && r.Method != http.MethodHead {
280 w.Header().Set("Allow", http.MethodGet+", "+http.MethodHead)
@@ -305,6 +282,9 @@ func serveInstallScript(w http.ResponseWriter, r *http.Request, portalURL string
282 return
283 }
284
285 + type installerConfig struct {
286 + Relays []string `json:"relays"`
287 + }
288 configPayload, err := json.Marshal(installerConfig{
289 Relays: []string{strings.TrimSpace(portalURL)},
290 })
@@ -317,11 +297,7 @@ func serveInstallScript(w http.ResponseWriter, r *http.Request, portalURL string
297 contentType := "text/x-shellscript"
298 filename := "install.sh"
299 if isWindows {
320 - script = fmt.Sprintf(
321 - installPowerShellTemplatePrefix+installPowerShellTemplateSuffix,
322 - portalURL,
323 - string(configPayload),
324 - )
300 + script = fmt.Sprintf(installPowerShellTemplate, portalURL, string(configPayload))
301 contentType = "text/plain; charset=utf-8"
302 filename = "install.ps1"
303 }