diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index b18883f2d..e54a24b3f 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -15,6 +15,7 @@ import ( "html/template" "io/ioutil" "log" + "net" "net/http" "net/http/cgi" "net/url" @@ -94,10 +95,20 @@ func runWeb(ctx context.Context, args []string) error { } return nil } - log.Printf("web server running on: %s\n", webArgs.listen) + + log.Printf("web server running on: %s", urlOfListenAddr(webArgs.listen)) return http.ListenAndServe(webArgs.listen, http.HandlerFunc(webHandler)) } +// urlOfListenAddr parses a given listen address into a formatted URL +func urlOfListenAddr(addr string) string { + host, port, _ := net.SplitHostPort(addr) + if host == "" { + host = "127.0.0.1" + } + return fmt.Sprintf("http://%s", net.JoinHostPort(host, port)) +} + // authorize returns the name of the user accessing the web UI after verifying // whether the user has access to the web UI. The function will write the // error to the provided http.ResponseWriter. diff --git a/cmd/tailscale/cli/web_test.go b/cmd/tailscale/cli/web_test.go new file mode 100644 index 000000000..04e2b1762 --- /dev/null +++ b/cmd/tailscale/cli/web_test.go @@ -0,0 +1,42 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cli + +import "testing" + +func TestUrlOfListenAddr(t *testing.T) { + t.Parallel() + + testTable := map[string]struct { + addr string + expected string + }{ + "TestLocalhost": { + addr: "localhost:8088", + expected: "http://localhost:8088", + }, + "TestNoHost": { + addr: ":8088", + expected: "http://127.0.0.1:8088", + }, + "TestExplicitHost": { + addr: "127.0.0.2:8088", + expected: "http://127.0.0.2:8088", + }, + "TestIPv6": { + addr: "[::1]:8088", + expected: "http://[::1]:8088", + }, + } + + for name, test := range testTable { + t.Run(name, func(t *testing.T) { + url := urlOfListenAddr(test.addr) + if url != test.expected { + t.Errorf("expected url: '%s', got: '%s'", test.expected, url) + } + }) + } +}