-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This works around golang/go#16142 However, it is fragile because it duplicates some private code from `net.http`, which could theoretically change its behaviour without notice.
- Loading branch information
Showing
3 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package origin | ||
|
||
import ( | ||
"net/url" | ||
"strings" | ||
) | ||
|
||
// From https://golang.org/src/net/http/client.go | ||
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } | ||
|
||
// From https://golang.org/src/net/http/transport.go | ||
var portMap = map[string]string{ | ||
"http": "80", | ||
"https": "443", | ||
} | ||
|
||
// From https://golang.org/src/net/http/transport.go | ||
func canonicalAddr(url *url.URL) string { | ||
addr := url.Host | ||
if !hasPort(addr) { | ||
return addr + ":" + portMap[url.Scheme] | ||
} | ||
return addr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package origin | ||
|
||
import ( | ||
"net" | ||
"net/url" | ||
) | ||
|
||
// Origin holds the explicit definition of an origin, based on the defintion | ||
// in https://tools.ietf.org/html/rfc6454 | ||
type Origin struct { | ||
// HostName is called HostName instead of Host to distinguish it from | ||
// url.URL.Host; this is similar to the a.href.host[name] quirk in Javascript. | ||
HostName string | ||
Scheme string | ||
// A port is actually an integer, so we go against normal Go convention | ||
// and call it "PortString" to be painfully clear. | ||
// TODO: Should we allow this to be empty if the port is unspecified? | ||
PortString string | ||
// TODO: Add a port int? | ||
} | ||
|
||
// New creates an origin based on the origin of the given URL string | ||
func New(u *url.URL) (Origin, error) { | ||
hostName, portString, err := net.SplitHostPort(canonicalAddr(u)) | ||
if err != nil { | ||
return Origin{}, err | ||
} | ||
|
||
return Origin{ | ||
HostName: hostName, | ||
Scheme: u.Scheme, | ||
PortString: portString, | ||
}, nil | ||
} | ||
|
||
// Parse is a convenience function that parses a URL and then calls | ||
// New(). | ||
func Parse(urlString string) (Origin, error) { | ||
u, err := url.Parse(urlString) | ||
if err != nil { | ||
return Origin{}, err | ||
} | ||
|
||
return New(u) | ||
} | ||
|
||
// // NOTE: This currently always includes the port. | ||
// func (o Origin) String() string { | ||
// u := url.URL{ | ||
// Scheme: o.Scheme, | ||
// Host: net.JoinHostPort(o.HostName, o.PortString), | ||
// } | ||
// return u.String() | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package origin | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestParse(t *testing.T) { | ||
|
||
cases := []struct { | ||
url string | ||
wanted Origin | ||
}{ | ||
{"http://localhost:8080", Origin{HostName: "localhost", Scheme: "http", PortString: "8080"}}, | ||
{"http://example.com", Origin{HostName: "example.com", Scheme: "http", PortString: "80"}}, | ||
{"http://example.com/", Origin{HostName: "example.com", Scheme: "http", PortString: "80"}}, | ||
{"http://example.com:80", Origin{HostName: "example.com", Scheme: "http", PortString: "80"}}, | ||
{"http://example.com/path", Origin{HostName: "example.com", Scheme: "http", PortString: "80"}}, | ||
{"https://example.com/#yolo", Origin{HostName: "example.com", Scheme: "https", PortString: "443"}}, | ||
{"https://example.com:443", Origin{HostName: "example.com", Scheme: "https", PortString: "443"}}, | ||
{"https://a.b.example.com", Origin{HostName: "a.b.example.com", Scheme: "https", PortString: "443"}}, | ||
{"https://alice@a.b.example.com:9001/path", Origin{HostName: "a.b.example.com", Scheme: "https", PortString: "9001"}}, | ||
} | ||
|
||
for _, tt := range cases { | ||
o, err := Parse(tt.url) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if !reflect.DeepEqual(o, tt.wanted) { | ||
t.Errorf("Unexpected: %#v", o) | ||
} | ||
} | ||
|
||
} |