Skip to content

Commit ae5d8c9

Browse files
committed
pass url.URL rather than string
return a *url.URL value from expandLink rather than a string, and both accept and return a *url.URL value from resolveLink rather than a string. These are both unexported funcs, so this has no changes to the current behavior. It does prevent a few unnecessary conversions back and forth between url.URL and string values, and will make it simpler to retain request query strings. Updates #77 Signed-off-by: Will Norris <[email protected]>
1 parent f00de63 commit ae5d8c9

File tree

2 files changed

+52
-28
lines changed

2 files changed

+52
-28
lines changed

golink.go

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,15 @@ func Run() error {
124124

125125
// if link specified on command line, resolve and exit
126126
if flag.NArg() > 0 {
127-
destination, err := resolveLink(flag.Arg(0))
127+
u, err := url.Parse(flag.Arg(0))
128128
if err != nil {
129129
log.Fatal(err)
130130
}
131-
fmt.Println(destination)
131+
dst, err := resolveLink(u)
132+
if err != nil {
133+
log.Fatal(err)
134+
}
135+
fmt.Println(dst.String())
132136
os.Exit(0)
133137
}
134138

@@ -403,7 +407,7 @@ func serveGo(w http.ResponseWriter, r *http.Request) {
403407
http.Error(w, err.Error(), http.StatusInternalServerError)
404408
return
405409
}
406-
http.Redirect(w, r, target, http.StatusFound)
410+
http.Redirect(w, r, target.String(), http.StatusFound)
407411
}
408412

409413
// acceptHTML returns whether the request can accept a text/html response.
@@ -494,7 +498,7 @@ var expandFuncMap = texttemplate.FuncMap{
494498
//
495499
// If long does not include templates, the default behavior is to append
496500
// env.Path to long.
497-
func expandLink(long string, env expandEnv) (string, error) {
501+
func expandLink(long string, env expandEnv) (*url.URL, error) {
498502
if !strings.Contains(long, "{{") {
499503
// default behavior is to append remaining path to long URL
500504
if strings.HasSuffix(long, "/") {
@@ -505,19 +509,19 @@ func expandLink(long string, env expandEnv) (string, error) {
505509
}
506510
tmpl, err := texttemplate.New("").Funcs(expandFuncMap).Parse(long)
507511
if err != nil {
508-
return "", err
512+
return nil, err
509513
}
510514
buf := new(bytes.Buffer)
511515
if err := tmpl.Execute(buf, env); err != nil {
512-
return "", err
516+
return nil, err
513517
}
514-
long = buf.String()
515518

516-
_, err = url.Parse(long)
519+
u, err := url.Parse(buf.String())
517520
if err != nil {
518-
return "", err
521+
return nil, err
519522
}
520-
return long, nil
523+
524+
return u, nil
521525
}
522526

523527
func devMode() bool { return *dev != "" }
@@ -740,22 +744,23 @@ func restoreLastSnapshot() error {
740744
return bs.Err()
741745
}
742746

743-
func resolveLink(link string) (string, error) {
744-
// if link specified as "go/name", trim "go" prefix.
745-
// Remainder will parse as URL with no scheme or host
746-
link = strings.TrimPrefix(link, *hostname)
747-
u, err := url.Parse(link)
748-
if err != nil {
749-
return "", err
747+
func resolveLink(link *url.URL) (*url.URL, error) {
748+
path := link.Path
749+
750+
// if link was specified as "go/name", it will parse with no scheme or host.
751+
// Trim "go" prefix from beginning of path.
752+
if link.Host == "" {
753+
path = strings.TrimPrefix(path, *hostname)
750754
}
751-
short, remainder, _ := strings.Cut(strings.TrimPrefix(u.RequestURI(), "/"), "/")
755+
756+
short, remainder, _ := strings.Cut(strings.TrimPrefix(path, "/"), "/")
752757
l, err := db.Load(short)
753758
if err != nil {
754-
return "", err
759+
return nil, err
755760
}
756761
dst, err := expandLink(l.Long, expandEnv{Now: time.Now().UTC(), Path: remainder})
757762
if err == nil {
758-
if u, uErr := url.Parse(dst); uErr == nil && (u.Hostname() == "" || u.Hostname() == *hostname) {
763+
if dst.Host == "" || dst.Host == *hostname {
759764
dst, err = resolveLink(dst)
760765
}
761766
}

golink_test.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"golang.org/x/net/xsrftoken"
16+
"tailscale.com/util/must"
1617
)
1718

1819
func init() {
@@ -344,28 +345,45 @@ func TestExpandLink(t *testing.T) {
344345
{
345346
name: "template-with-pathescape-func",
346347
long: "http://host.com/{{PathEscape .Path}}",
347-
remainder: "a/b",
348-
want: "http://host.com/a%2Fb",
348+
remainder: "a/b+c",
349+
want: "http://host.com/a%2Fb+c",
349350
},
350351
{
351352
name: "template-with-queryescape-func",
352353
long: "http://host.com/{{QueryEscape .Path}}",
353-
remainder: "a+b",
354-
want: "http://host.com/a%2Bb",
354+
remainder: "a/b+c",
355+
want: "http://host.com/a%2Fb%2Bc",
355356
},
356357
{
357358
name: "template-with-trimsuffix-func",
358359
long: `http://host.com/{{TrimSuffix .Path "/"}}`,
359360
remainder: "a/",
360361
want: "http://host.com/a",
361362
},
363+
{
364+
name: "relative-link",
365+
long: `rel`,
366+
remainder: "a",
367+
want: "rel/a",
368+
},
369+
{
370+
name: "relative-link-with-slash",
371+
long: `/rel`,
372+
remainder: "a",
373+
want: "/rel/a",
374+
},
375+
362376
}
363377
for _, tt := range tests {
364378
t.Run(tt.name, func(t *testing.T) {
365-
got, err := expandLink(tt.long, expandEnv{Now: tt.now, Path: tt.remainder, user: tt.user})
379+
link, err := expandLink(tt.long, expandEnv{Now: tt.now, Path: tt.remainder, user: tt.user})
366380
if (err != nil) != tt.wantErr {
367381
t.Fatalf("expandLink(%q) returned error %v; want %v", tt.long, err, tt.wantErr)
368382
}
383+
var got string
384+
if link != nil {
385+
got = link.String()
386+
}
369387
if got != tt.want {
370388
t.Errorf("expandLink(%q) = %q; want %q", tt.long, got, tt.want)
371389
}
@@ -431,12 +449,13 @@ func TestResolveLink(t *testing.T) {
431449
for _, tt := range tests {
432450
name := "golink " + tt.link
433451
t.Run(name, func(t *testing.T) {
434-
got, err := resolveLink(tt.link)
452+
u := must.Get(url.Parse(tt.link))
453+
got, err := resolveLink(u)
435454
if err != nil {
436455
t.Error(err)
437456
}
438-
if got != tt.want {
439-
t.Errorf("ResolveLink(%q) = %q; want %q", tt.link, got, tt.want)
457+
if got.String() != tt.want {
458+
t.Errorf("ResolveLink(%q) = %q; want %q", tt.link, got.String(), tt.want)
440459
}
441460
})
442461
}

0 commit comments

Comments
 (0)