From 659570915481c87559f0197c9980e8cbac8e2c33 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 19 Oct 2016 14:06:54 -0400 Subject: [PATCH] net/url: make URL implement encoding.BinaryMarshaler, BinaryUnmarshaler This makes it possible to use URLs with gob. Ideally we'd also implement TextMarshaler and TextUnmarshaler, but that would change the JSON encoding of a URL from something like: {"Scheme":"https","Opaque":"","User":null,"Host":"www.google.com","Path":"/x","RawPath":"","ForceQuery":false,"RawQuery":"y=z","Fragment":""} to something like: "https://www.google.com/x?y=z" That'd be nice, but it would break code expecting the old form. Fixes #10964. Change-Id: I83f06bc2bedd2ba8a5d8eef03ea0056d045c258f Reviewed-on: https://go-review.googlesource.com/31467 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/net/url/url.go | 16 ++++++++++++ src/net/url/url_test.go | 55 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/net/url/url.go b/src/net/url/url.go index 525dbeee33..0931296468 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -1025,3 +1025,19 @@ func portOnly(hostport string) string { } return hostport[colon+len(":"):] } + +// Marshaling interface implementations. +// Would like to implement MarshalText/UnmarshalText but that will change the JSON representation of URLs. + +func (u *URL) MarshalBinary() (text []byte, err error) { + return []byte(u.String()), nil +} + +func (u *URL) UnmarshalBinary(text []byte) error { + u1, err := Parse(string(text)) + if err != nil { + return err + } + *u = *u1 + return nil +} diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 344ecdcee4..eebc1112c1 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -5,6 +5,10 @@ package url import ( + "bytes" + encodingPkg "encoding" + "encoding/gob" + "encoding/json" "fmt" "io" "net" @@ -1624,3 +1628,54 @@ func TestURLPort(t *testing.T) { } } } + +var _ encodingPkg.BinaryMarshaler = (*URL)(nil) +var _ encodingPkg.BinaryUnmarshaler = (*URL)(nil) + +func TestJSON(t *testing.T) { + u, err := Parse("https://www.google.com/x?y=z") + if err != nil { + t.Fatal(err) + } + js, err := json.Marshal(u) + if err != nil { + t.Fatal(err) + } + + // If only we could implement TextMarshaler/TextUnmarshaler, + // this would work: + // + // if string(js) != strconv.Quote(u.String()) { + // t.Errorf("json encoding: %s\nwant: %s\n", js, strconv.Quote(u.String())) + // } + + u1 := new(URL) + err = json.Unmarshal(js, u1) + if err != nil { + t.Fatal(err) + } + if u1.String() != u.String() { + t.Errorf("json decoded to: %s\nwant: %s\n", u1, u) + } +} + +func TestGob(t *testing.T) { + u, err := Parse("https://www.google.com/x?y=z") + if err != nil { + t.Fatal(err) + } + var w bytes.Buffer + err = gob.NewEncoder(&w).Encode(u) + if err != nil { + t.Fatal(err) + } + + u1 := new(URL) + err = gob.NewDecoder(&w).Decode(u1) + if err != nil { + t.Fatal(err) + } + if u1.String() != u.String() { + t.Errorf("json decoded to: %s\nwant: %s\n", u1, u) + } +}