suggest long URL for new go links if peer exists

If you visit a non-existent go link, we render the home page and pre-
populate the "short" input with the name of the link, and autofocus the
"long" input so that you can simply paste a long URL and submit.

It is common (at least at Tailscale) to create go links that correspond
to the name of a device on the tailnet.  For example, go/who points to
http://who/.  With this change, when you visit a non-existent go link,
we check to see if a peer exists on the tailnet with that name, and if
so we suggest that as the long URL.

Signed-off-by: Will Norris <will@tailscale.com>
This commit is contained in:
Will Norris
2024-03-15 14:42:43 -07:00
committed by Will Norris
parent 0b61ec165e
commit 6c79b503e1
2 changed files with 23 additions and 4 deletions
+19 -3
View File
@@ -257,6 +257,7 @@ type visitData struct {
// homeData is the data used by the homeTmpl template.
type homeData struct {
Short string
Long string
Clicks []visitData
}
@@ -379,7 +380,7 @@ func serveHandler() http.Handler {
})
}
func serveHome(w http.ResponseWriter, short string) {
func serveHome(w http.ResponseWriter, r *http.Request, short string) {
var clicks []visitData
stats.mu.Lock()
@@ -401,8 +402,23 @@ func serveHome(w http.ResponseWriter, short string) {
clicks = clicks[:200]
}
var long string
if short != "" && localClient != nil {
// if a peer exists with the short name, suggest it as the long URL
st, err := localClient.Status(r.Context())
if err == nil {
for _, p := range st.Peer {
if host, _, ok := strings.Cut(p.DNSName, "."); ok && host == short {
long = "http://" + host + "/"
break
}
}
}
}
homeTmpl.Execute(w, homeData{
Short: short,
Long: long,
Clicks: clicks,
})
}
@@ -442,7 +458,7 @@ func serveGo(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
switch r.Method {
case "GET":
serveHome(w, "")
serveHome(w, r, "")
case "POST":
serveSave(w, r)
}
@@ -460,7 +476,7 @@ func serveGo(w http.ResponseWriter, r *http.Request) {
link, err := db.Load(short)
if errors.Is(err, fs.ErrNotExist) {
w.WriteHeader(http.StatusNotFound)
serveHome(w, short)
serveHome(w, r, short)
return
}
if err != nil {
+4 -1
View File
@@ -1,6 +1,9 @@
{{ define "main" }}
<h2 class="text-xl font-bold pb-2">Create a new link</h2>
{{ with .Long }}
<p class="">Did you mean <a class="text-blue-600 hover:underline" href="{{.}}">{{.}}</a> ? Create a go link for it now:</p>
{{ end }}
<form method="POST" action="/" class="flex flex-wrap">
<div class="flex">
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://go/</label>
@@ -8,7 +11,7 @@
class="p-2 my-2 rounded-r-md border-gray-300 placeholder:text-gray-400">
<span class="flex m-2 items-center">&rarr;</span>
</div>
<input name=long required type=text size=40 placeholder="https://destination-url"{{if .Short}} autofocus{{end}} class="p-2 my-2 mr-2 max-w-full rounded-md border-gray-300 placeholder:text-gray-400">
<input name=long required type=text size=40 placeholder="https://destination-url"{{if .Short}} value="{{.Long}}" autofocus{{end}} class="p-2 my-2 mr-2 max-w-full rounded-md border-gray-300 placeholder:text-gray-400">
<button type=submit class="py-2 px-4 my-2 rounded-md bg-blue-500 border-blue-500 text-white hover:bg-blue-600 hover:border-blue-600">Create</button>
</form>
<p class="text-sm text-gray-500"><a class="text-blue-600 hover:underline" href="/.help">Help and advanced options</a></p>