aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net')
-rw-r--r--libgo/go/net/dnsclient_unix.go6
-rw-r--r--libgo/go/net/doc.go59
-rw-r--r--libgo/go/net/fd.go55
-rw-r--r--libgo/go/net/fd_windows.go46
-rw-r--r--libgo/go/net/http/cgi/host.go2
-rw-r--r--libgo/go/net/http/cgi/host_test.go2
-rw-r--r--libgo/go/net/http/client.go19
-rw-r--r--libgo/go/net/http/client_test.go87
-rw-r--r--libgo/go/net/http/doc.go3
-rw-r--r--libgo/go/net/http/fs_test.go12
-rw-r--r--libgo/go/net/http/httputil/dump.go25
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go5
-rw-r--r--libgo/go/net/http/readrequest_test.go30
-rw-r--r--libgo/go/net/http/request.go22
-rw-r--r--libgo/go/net/http/requestwrite_test.go16
-rw-r--r--libgo/go/net/http/serve_test.go22
-rw-r--r--libgo/go/net/http/server.go15
-rw-r--r--libgo/go/net/http/transport.go7
-rw-r--r--libgo/go/net/ipraw_test.go3
-rw-r--r--libgo/go/net/iprawsock_plan9.go33
-rw-r--r--libgo/go/net/iprawsock_posix.go25
-rw-r--r--libgo/go/net/ipsock_plan9.go22
-rw-r--r--libgo/go/net/ipsock_posix.go4
-rw-r--r--libgo/go/net/lookup_plan9.go38
-rw-r--r--libgo/go/net/lookup_unix.go38
-rw-r--r--libgo/go/net/lookup_windows.go25
-rw-r--r--libgo/go/net/net.go65
-rw-r--r--libgo/go/net/pipe.go13
-rw-r--r--libgo/go/net/sendfile_linux.go9
-rw-r--r--libgo/go/net/server_test.go9
-rw-r--r--libgo/go/net/smtp/auth.go3
-rw-r--r--libgo/go/net/sock.go14
-rw-r--r--libgo/go/net/sockopt.go15
-rw-r--r--libgo/go/net/sockopt_bsd.go5
-rw-r--r--libgo/go/net/sockopt_linux.go5
-rw-r--r--libgo/go/net/sockopt_windows.go2
-rw-r--r--libgo/go/net/tcpsock_plan9.go16
-rw-r--r--libgo/go/net/tcpsock_posix.go26
-rw-r--r--libgo/go/net/timeout_test.go48
-rw-r--r--libgo/go/net/udpsock_plan9.go20
-rw-r--r--libgo/go/net/udpsock_posix.go23
-rw-r--r--libgo/go/net/unicast_test.go30
-rw-r--r--libgo/go/net/unixsock_plan9.go13
-rw-r--r--libgo/go/net/unixsock_posix.go60
-rw-r--r--libgo/go/net/url/url.go347
-rw-r--r--libgo/go/net/url/url_test.go354
46 files changed, 891 insertions, 807 deletions
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index 07e72cc..18c3936 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -45,7 +45,11 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error
return nil, err
}
- c.SetReadTimeout(int64(cfg.timeout) * 1e9) // nanoseconds
+ if cfg.timeout == 0 {
+ c.SetReadDeadline(time.Time{})
+ } else {
+ c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
+ }
buf := make([]byte, 2000) // More than enough.
n, err = c.Read(buf)
diff --git a/libgo/go/net/doc.go b/libgo/go/net/doc.go
new file mode 100644
index 0000000..3a44e52
--- /dev/null
+++ b/libgo/go/net/doc.go
@@ -0,0 +1,59 @@
+// Copyright 2012 The Go 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 net
+
+// LookupHost looks up the given host using the local resolver.
+// It returns an array of that host's addresses.
+func LookupHost(host string) (addrs []string, err error) {
+ return lookupHost(host)
+}
+
+// LookupIP looks up host using the local resolver.
+// It returns an array of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) (addrs []IP, err error) {
+ return lookupIP(host)
+}
+
+// LookupPort looks up the port for the given network and service.
+func LookupPort(network, service string) (port int, err error) {
+ return lookupPort(network, service)
+}
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err error) {
+ return lookupCNAME(name)
+}
+
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name. The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name. To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
+func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+ return lookupSRV(service, proto, name)
+}
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) (mx []*MX, err error) {
+ return lookupMX(name)
+}
+
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err error) {
+ return lookupTXT(name)
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func LookupAddr(addr string) (name []string, err error) {
+ return lookupAddr(addr)
+}
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index 3dec9f4..7ecd135 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -24,7 +24,7 @@ type netFD struct {
// immutable until Close
sysfd int
family int
- proto int
+ sotype int
sysfile *os.File
cr chan bool
cw chan bool
@@ -33,12 +33,10 @@ type netFD struct {
raddr Addr
// owned by client
- rdeadline_delta int64
- rdeadline int64
- rio sync.Mutex
- wdeadline_delta int64
- wdeadline int64
- wio sync.Mutex
+ rdeadline int64
+ rio sync.Mutex
+ wdeadline int64
+ wio sync.Mutex
// owned by fd wait server
ncr, ncw int
@@ -276,7 +274,7 @@ func startServer() {
pollserver = p
}
-func newFD(fd, family, proto int, net string) (f *netFD, err error) {
+func newFD(fd, family, sotype int, net string) (f *netFD, err error) {
onceStartServer.Do(startServer)
if e := syscall.SetNonblock(fd, true); e != nil {
return nil, e
@@ -284,7 +282,7 @@ func newFD(fd, family, proto int, net string) (f *netFD, err error) {
f = &netFD{
sysfd: fd,
family: family,
- proto: proto,
+ sotype: sotype,
net: net,
}
f.cr = make(chan bool, 1)
@@ -388,11 +386,6 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
if fd.sysfile == nil {
return 0, os.EINVAL
}
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, err = syscall.Read(fd.sysfile.Fd(), p)
if err == syscall.EAGAIN {
@@ -404,7 +397,7 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
}
if err != nil {
n = 0
- } else if n == 0 && err == nil && fd.proto != syscall.SOCK_DGRAM {
+ } else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM {
err = io.EOF
}
break
@@ -423,11 +416,6 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
if err == syscall.EAGAIN {
@@ -456,11 +444,6 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
if err == syscall.EAGAIN {
@@ -493,11 +476,6 @@ func (fd *netFD) Write(p []byte) (n int, err error) {
if fd.sysfile == nil {
return 0, os.EINVAL
}
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
nn := 0
for {
@@ -539,11 +517,6 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
for {
err = syscall.Sendto(fd.sysfd, p, 0, sa)
if err == syscall.EAGAIN {
@@ -571,11 +544,6 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
for {
err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
if err == syscall.EAGAIN {
@@ -603,11 +571,6 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
// See ../syscall/exec.go for description of ForkLock.
// It is okay to hold the lock across syscall.Accept
@@ -636,7 +599,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
- if nfd, err = newFD(s, fd.family, fd.proto, fd.net); err != nil {
+ if nfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
syscall.Close(s)
return nil, err
}
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index 7bffd1c..6e37b4e 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -150,12 +150,13 @@ func (s *ioSrv) ProcessRemoteIO() {
}
// ExecIO executes a single io operation. It either executes it
-// inline, or, if timeouts are employed, passes the request onto
+// inline, or, if a deadline is employed, passes the request onto
// a special goroutine and waits for completion or cancels request.
-func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
+// deadline is unix nanos.
+func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (n int, err error) {
var e error
o := oi.Op()
- if deadline_delta > 0 {
+ if deadline != 0 {
// Send request to a special dedicated thread,
// so it can stop the io with CancelIO later.
s.submchan <- oi
@@ -172,12 +173,17 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, e}
}
// Wait for our request to complete.
- // TODO(rsc): This should stop the timer.
var r ioResult
- if deadline_delta > 0 {
+ if deadline != 0 {
+ dt := deadline - time.Now().UnixNano()
+ if dt < 1 {
+ dt = 1
+ }
+ timer := time.NewTimer(time.Duration(dt) * time.Nanosecond)
+ defer timer.Stop()
select {
case r = <-o.resultc:
- case <-time.After(time.Duration(deadline_delta) * time.Nanosecond):
+ case <-timer.C:
s.canchan <- oi
<-o.errnoc
r = <-o.resultc
@@ -224,7 +230,7 @@ type netFD struct {
// immutable until Close
sysfd syscall.Handle
family int
- proto int
+ sotype int
net string
laddr Addr
raddr Addr
@@ -232,19 +238,17 @@ type netFD struct {
errnoc [2]chan error // read/write submit or cancel operation errors
// owned by client
- rdeadline_delta int64
- rdeadline int64
- rio sync.Mutex
- wdeadline_delta int64
- wdeadline int64
- wio sync.Mutex
+ rdeadline int64
+ rio sync.Mutex
+ wdeadline int64
+ wio sync.Mutex
}
-func allocFD(fd syscall.Handle, family, proto int, net string) (f *netFD) {
+func allocFD(fd syscall.Handle, family, sotype int, net string) (f *netFD) {
f = &netFD{
sysfd: fd,
family: family,
- proto: proto,
+ sotype: sotype,
net: net,
}
runtime.SetFinalizer(f, (*netFD).Close)
@@ -357,7 +361,7 @@ func (fd *netFD) Read(buf []byte) (n int, err error) {
}
var o readOp
o.Init(fd, buf, 'r')
- n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+ n, err = iosrv.ExecIO(&o, fd.rdeadline)
if err == nil && n == 0 {
err = io.EOF
}
@@ -398,7 +402,7 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
var o readFromOp
o.Init(fd, buf, 'r')
o.rsan = int32(unsafe.Sizeof(o.rsa))
- n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+ n, err = iosrv.ExecIO(&o, fd.rdeadline)
if err != nil {
return 0, nil, err
}
@@ -434,7 +438,7 @@ func (fd *netFD) Write(buf []byte) (n int, err error) {
}
var o writeOp
o.Init(fd, buf, 'w')
- return iosrv.ExecIO(&o, fd.wdeadline_delta)
+ return iosrv.ExecIO(&o, fd.wdeadline)
}
// WriteTo to network.
@@ -470,7 +474,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err error) {
var o writeToOp
o.Init(fd, buf, 'w')
o.sa = sa
- return iosrv.ExecIO(&o, fd.wdeadline_delta)
+ return iosrv.ExecIO(&o, fd.wdeadline)
}
// Accept new network connections.
@@ -502,7 +506,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
// Get new socket.
// See ../syscall/exec.go for description of ForkLock.
syscall.ForkLock.RLock()
- s, e := syscall.Socket(fd.family, fd.proto, 0)
+ s, e := syscall.Socket(fd.family, fd.sotype, 0)
if e != nil {
syscall.ForkLock.RUnlock()
return nil, e
@@ -542,7 +546,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
lsa, _ := lrsa.Sockaddr()
rsa, _ := rrsa.Sockaddr()
- nfd = allocFD(s, fd.family, fd.proto, fd.net)
+ nfd = allocFD(s, fd.family, fd.sotype, fd.net)
nfd.setAddr(toAddr(lsa), toAddr(rsa))
return nfd, nil
}
diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go
index 615d366..73a9b6e 100644
--- a/libgo/go/net/http/cgi/host.go
+++ b/libgo/go/net/http/cgi/host.go
@@ -124,7 +124,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
"GATEWAY_INTERFACE=CGI/1.1",
"REQUEST_METHOD=" + req.Method,
"QUERY_STRING=" + req.URL.RawQuery,
- "REQUEST_URI=" + req.URL.RawPath,
+ "REQUEST_URI=" + req.URL.RequestURI(),
"PATH_INFO=" + pathInfo,
"SCRIPT_NAME=" + root,
"SCRIPT_FILENAME=" + h.Path,
diff --git a/libgo/go/net/http/cgi/host_test.go b/libgo/go/net/http/cgi/host_test.go
index 849cb00..b8dbdb4 100644
--- a/libgo/go/net/http/cgi/host_test.go
+++ b/libgo/go/net/http/cgi/host_test.go
@@ -364,7 +364,7 @@ func TestCopyError(t *testing.T) {
conn.Close()
tries := 0
- for tries < 15 && childRunning() {
+ for tries < 25 && childRunning() {
time.Sleep(50 * time.Millisecond * time.Duration(tries))
tries++
}
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index a4f8f19..1d70672 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -24,11 +24,13 @@ import (
// The Client's Transport typically has internal state (cached
// TCP connections), so Clients should be reused instead of created as
// needed. Clients are safe for concurrent use by multiple goroutines.
-//
-// Client is not yet very configurable.
type Client struct {
- Transport RoundTripper // if nil, DefaultTransport is used
+ // Transport specifies the mechanism by which individual
+ // HTTP requests are made.
+ // If nil, DefaultTransport is used.
+ Transport RoundTripper
+ // CheckRedirect specifies the policy for handling redirects.
// If CheckRedirect is not nil, the client calls it before
// following an HTTP redirect. The arguments req and via
// are the upcoming request and the requests made already,
@@ -121,9 +123,8 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
req.Header = make(Header)
}
- info := req.URL.RawUserinfo
- if len(info) > 0 {
- req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info)))
+ if u := req.URL.User; u != nil {
+ req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
}
return t.RoundTrip(req)
}
@@ -213,11 +214,11 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
break
}
}
- for _, cookie := range jar.Cookies(req.URL) {
- req.AddCookie(cookie)
- }
}
+ for _, cookie := range jar.Cookies(req.URL) {
+ req.AddCookie(cookie)
+ }
urlStr = req.URL.String()
if r, err = send(req, c.Transport); err != nil {
break
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index 57a9dd9..c746110 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -18,6 +18,7 @@ import (
"net/url"
"strconv"
"strings"
+ "sync"
"testing"
)
@@ -236,6 +237,92 @@ func TestRedirects(t *testing.T) {
}
}
+var expectedCookies = []*Cookie{
+ &Cookie{Name: "ChocolateChip", Value: "tasty"},
+ &Cookie{Name: "First", Value: "Hit"},
+ &Cookie{Name: "Second", Value: "Hit"},
+}
+
+var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+ for _, cookie := range r.Cookies() {
+ SetCookie(w, cookie)
+ }
+ if r.URL.Path == "/" {
+ SetCookie(w, expectedCookies[1])
+ Redirect(w, r, "/second", StatusMovedPermanently)
+ } else {
+ SetCookie(w, expectedCookies[2])
+ w.Write([]byte("hello"))
+ }
+})
+
+// Just enough correctness for our redirect tests. Uses the URL.Host as the
+// scope of all cookies.
+type TestJar struct {
+ m sync.Mutex
+ perURL map[string][]*Cookie
+}
+
+func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) {
+ j.m.Lock()
+ defer j.m.Unlock()
+ j.perURL[u.Host] = cookies
+}
+
+func (j *TestJar) Cookies(u *url.URL) []*Cookie {
+ j.m.Lock()
+ defer j.m.Unlock()
+ return j.perURL[u.Host]
+}
+
+func TestRedirectCookiesOnRequest(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(echoCookiesRedirectHandler)
+ defer ts.Close()
+ c := &Client{}
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.AddCookie(expectedCookies[0])
+ // TODO: Uncomment when an implementation of a RFC6265 cookie jar lands.
+ _ = c
+ // resp, _ := c.Do(req)
+ // matchReturnedCookies(t, expectedCookies, resp.Cookies())
+
+ req, _ = NewRequest("GET", ts.URL, nil)
+ // resp, _ = c.Do(req)
+ // matchReturnedCookies(t, expectedCookies[1:], resp.Cookies())
+}
+
+func TestRedirectCookiesJar(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(echoCookiesRedirectHandler)
+ defer ts.Close()
+ c := &Client{}
+ c.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+ u, _ := url.Parse(ts.URL)
+ c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
+ resp, _ := c.Get(ts.URL)
+ matchReturnedCookies(t, expectedCookies, resp.Cookies())
+}
+
+func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
+ t.Logf("Received cookies: %v", given)
+ if len(given) != len(expected) {
+ t.Errorf("Expected %d cookies, got %d", len(expected), len(given))
+ }
+ for _, ec := range expected {
+ foundC := false
+ for _, c := range given {
+ if ec.Name == c.Name && ec.Value == c.Value {
+ foundC = true
+ break
+ }
+ }
+ if !foundC {
+ t.Errorf("Missing cookie %v", ec)
+ }
+ }
+}
+
func TestStreamingGet(t *testing.T) {
say := make(chan string)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
diff --git a/libgo/go/net/http/doc.go b/libgo/go/net/http/doc.go
index 2dbcf8d..8962ed3 100644
--- a/libgo/go/net/http/doc.go
+++ b/libgo/go/net/http/doc.go
@@ -34,7 +34,8 @@ settings, create a Client:
resp, err := client.Get("http://example.com")
// ...
- req := http.NewRequest("GET", "http://example.com", nil)
+ req, err := http.NewRequest("GET", "http://example.com", nil)
+ // ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
// ...
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index 976ee75..85cad3e 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -224,16 +224,15 @@ func TestEmptyDirOpenCWD(t *testing.T) {
func TestServeFileContentType(t *testing.T) {
const ctype = "icecream/chocolate"
- override := false
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- if override {
+ if r.FormValue("override") == "1" {
w.Header().Set("Content-Type", ctype)
}
ServeFile(w, r, "testdata/file")
}))
defer ts.Close()
- get := func(want string) {
- resp, err := Get(ts.URL)
+ get := func(override, want string) {
+ resp, err := Get(ts.URL + "?override=" + override)
if err != nil {
t.Fatal(err)
}
@@ -241,9 +240,8 @@ func TestServeFileContentType(t *testing.T) {
t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
}
}
- get("text/plain; charset=utf-8")
- override = true
- get(ctype)
+ get("0", "text/plain; charset=utf-8")
+ get("1", ctype)
}
func TestServeFileMimeType(t *testing.T) {
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go
index 31696ae..b8a98ee 100644
--- a/libgo/go/net/http/httputil/dump.go
+++ b/libgo/go/net/http/httputil/dump.go
@@ -13,6 +13,7 @@ import (
"net"
"net/http"
"strings"
+ "time"
)
// One of the copies, say from b to r2, could be avoided by using a more
@@ -36,12 +37,12 @@ type dumpConn struct {
io.Reader
}
-func (c *dumpConn) Close() error { return nil }
-func (c *dumpConn) LocalAddr() net.Addr { return nil }
-func (c *dumpConn) RemoteAddr() net.Addr { return nil }
-func (c *dumpConn) SetTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetReadTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetWriteTimeout(nsec int64) error { return nil }
+func (c *dumpConn) Close() error { return nil }
+func (c *dumpConn) LocalAddr() net.Addr { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
// DumpRequestOut is like DumpRequest but includes
// headers that the standard http.Transport adds,
@@ -124,16 +125,8 @@ func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
var b bytes.Buffer
- urlStr := req.URL.Raw
- if urlStr == "" {
- urlStr = valueOrDefault(req.URL.EncodedPath(), "/")
- if req.URL.RawQuery != "" {
- urlStr += "?" + req.URL.RawQuery
- }
- }
-
- fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"), urlStr,
- req.ProtoMajor, req.ProtoMinor)
+ fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
+ req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
host := req.Host
if host == "" && req.URL != nil {
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 1dc83e7..1072e2e 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -59,11 +59,6 @@ func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
- if q := req.URL.RawQuery; q != "" {
- req.URL.RawPath = req.URL.Path + "?" + q
- } else {
- req.URL.RawPath = req.URL.Path
- }
req.URL.RawQuery = target.RawQuery
}
return &ReverseProxy{Director: director}
diff --git a/libgo/go/net/http/readrequest_test.go b/libgo/go/net/http/readrequest_test.go
index ad7e3c0..da3e405 100644
--- a/libgo/go/net/http/readrequest_test.go
+++ b/libgo/go/net/http/readrequest_test.go
@@ -44,15 +44,9 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "http://www.techcrunch.com/",
- Scheme: "http",
- RawPath: "/",
- RawAuthority: "www.techcrunch.com",
- RawUserinfo: "",
- Host: "www.techcrunch.com",
- Path: "/",
- RawQuery: "",
- Fragment: "",
+ Scheme: "http",
+ Host: "www.techcrunch.com",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -86,9 +80,7 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "/",
- Path: "/",
- RawPath: "/",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -113,15 +105,7 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "//user@host/is/actually/a/path/",
- Scheme: "",
- RawPath: "//user@host/is/actually/a/path/",
- RawAuthority: "",
- RawUserinfo: "",
- Host: "",
- Path: "//user@host/is/actually/a/path/",
- RawQuery: "",
- Fragment: "",
+ Path: "//user@host/is/actually/a/path/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -170,9 +154,7 @@ var reqTests = []reqTest{
&Request{
Method: "POST",
URL: &url.URL{
- Raw: "/",
- Path: "/",
- RawPath: "/",
+ Path: "/",
},
TransferEncoding: []string{"chunked"},
Proto: "HTTP/1.1",
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 2603010..5a4e739 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -302,26 +302,14 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
host = req.URL.Host
}
- urlStr := req.URL.RawPath
- if strings.HasPrefix(urlStr, "?") {
- urlStr = "/" + urlStr // Issue 2344
- }
- if urlStr == "" {
- urlStr = valueOrDefault(req.URL.RawPath, valueOrDefault(req.URL.EncodedPath(), "/"))
- if req.URL.RawQuery != "" {
- urlStr += "?" + req.URL.RawQuery
- }
- if usingProxy {
- if urlStr == "" || urlStr[0] != '/' {
- urlStr = "/" + urlStr
- }
- urlStr = req.URL.Scheme + "://" + host + urlStr
- }
+ ruri := req.URL.RequestURI()
+ if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
+ ruri = req.URL.Scheme + "://" + host + ruri
}
- // TODO(bradfitz): escape at least newlines in urlStr?
+ // TODO(bradfitz): escape at least newlines in ruri?
bw := bufio.NewWriter(w)
- fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr)
+ fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
// Header lines
fmt.Fprintf(bw, "Host: %s\r\n", host)
diff --git a/libgo/go/net/http/requestwrite_test.go b/libgo/go/net/http/requestwrite_test.go
index 8081589..fc3186f 100644
--- a/libgo/go/net/http/requestwrite_test.go
+++ b/libgo/go/net/http/requestwrite_test.go
@@ -32,15 +32,9 @@ var reqWriteTests = []reqWriteTest{
Req: Request{
Method: "GET",
URL: &url.URL{
- Raw: "http://www.techcrunch.com/",
- Scheme: "http",
- RawPath: "http://www.techcrunch.com/",
- RawAuthority: "www.techcrunch.com",
- RawUserinfo: "",
- Host: "www.techcrunch.com",
- Path: "/",
- RawQuery: "",
- Fragment: "",
+ Scheme: "http",
+ Host: "www.techcrunch.com",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -60,7 +54,7 @@ var reqWriteTests = []reqWriteTest{
Form: map[string][]string{},
},
- WantWrite: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+ WantWrite: "GET / HTTP/1.1\r\n" +
"Host: www.techcrunch.com\r\n" +
"User-Agent: Fake\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
@@ -198,7 +192,7 @@ var reqWriteTests = []reqWriteTest{
"\r\n" +
"abcdef",
- WantProxy: "POST / HTTP/1.1\r\n" +
+ WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Content-Length: 6\r\n" +
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index 24e6b50..147c216 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -84,15 +84,15 @@ func (c *testConn) RemoteAddr() net.Addr {
return dummyAddr("remote-addr")
}
-func (c *testConn) SetTimeout(nsec int64) error {
+func (c *testConn) SetDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetReadTimeout(nsec int64) error {
+func (c *testConn) SetReadDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetWriteTimeout(nsec int64) error {
+func (c *testConn) SetWriteDeadline(t time.Time) error {
return nil
}
@@ -642,7 +642,7 @@ func TestServerExpect(t *testing.T) {
// Note using r.FormValue("readbody") because for POST
// requests that would read from r.Body, which we only
// conditionally want to do.
- if strings.Contains(r.URL.RawPath, "readbody=true") {
+ if strings.Contains(r.URL.RawQuery, "readbody=true") {
ioutil.ReadAll(r.Body)
w.Write([]byte("Hi"))
} else {
@@ -904,17 +904,13 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
panic("intentional death for testing")
}))
defer ts.Close()
- _, err := Get(ts.URL)
- if err == nil {
- t.Logf("expected an error")
- }
// Do a blocking read on the log output pipe so its logging
// doesn't bleed into the next test. But wait only 5 seconds
// for it.
- done := make(chan bool)
+ done := make(chan bool, 1)
go func() {
- buf := make([]byte, 1024)
+ buf := make([]byte, 4<<10)
_, err := pr.Read(buf)
pr.Close()
if err != nil {
@@ -922,6 +918,12 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
}
done <- true
}()
+
+ _, err := Get(ts.URL)
+ if err == nil {
+ t.Logf("expected an error")
+ }
+
select {
case <-done:
return
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index fa90095..bad3bcb 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -569,14 +569,15 @@ func (c *conn) serve() {
if err == nil {
return
}
- if c.rwc != nil { // may be nil if connection hijacked
- c.rwc.Close()
- }
var buf bytes.Buffer
fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
buf.Write(debug.Stack())
log.Print(buf.String())
+
+ if c.rwc != nil { // may be nil if connection hijacked
+ c.rwc.Close()
+ }
}()
if tlsConn, ok := c.rwc.(*tls.Conn); ok {
@@ -954,8 +955,8 @@ func Serve(l net.Listener, handler Handler) error {
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
Handler Handler // handler to invoke, http.DefaultServeMux if nil
- ReadTimeout time.Duration // the net.Conn.SetReadTimeout value for new connections
- WriteTimeout time.Duration // the net.Conn.SetWriteTimeout value for new connections
+ ReadTimeout time.Duration // maximum duration before timing out read of the request
+ WriteTimeout time.Duration // maximum duration before timing out write of the response
MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0
}
@@ -989,10 +990,10 @@ func (srv *Server) Serve(l net.Listener) error {
return e
}
if srv.ReadTimeout != 0 {
- rw.SetReadTimeout(srv.ReadTimeout.Nanoseconds())
+ rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
}
if srv.WriteTimeout != 0 {
- rw.SetWriteTimeout(srv.WriteTimeout.Nanoseconds())
+ rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
}
c, err := srv.newConn(rw)
if err != nil {
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 33ad328..1b9ad1b 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -229,9 +229,8 @@ func (cm *connectMethod) proxyAuth() string {
if cm.proxyURL == nil {
return ""
}
- proxyInfo := cm.proxyURL.RawUserinfo
- if proxyInfo != "" {
- return "Basic " + base64.URLEncoding.EncodeToString([]byte(proxyInfo))
+ if u := cm.proxyURL.User; u != nil {
+ return "Basic " + base64.URLEncoding.EncodeToString([]byte(u.String()))
}
return ""
}
@@ -332,7 +331,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
case cm.targetScheme == "https":
connectReq := &Request{
Method: "CONNECT",
- URL: &url.URL{RawPath: cm.targetAddr},
+ URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
Header: make(Header),
}
diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go
index 67a4049..c74bfcd 100644
--- a/libgo/go/net/ipraw_test.go
+++ b/libgo/go/net/ipraw_test.go
@@ -12,6 +12,7 @@ import (
"flag"
"os"
"testing"
+ "time"
)
const ICMP_ECHO_REQUEST = 8
@@ -101,7 +102,7 @@ func TestICMP(t *testing.T) {
t.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr, n, err)
}
- c.SetTimeout(100e6)
+ c.SetDeadline(time.Now().Add(100 * time.Millisecond))
resp := make([]byte, 1024)
for {
n, from, err := c.ReadFrom(resp)
diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go
index 3fd9dce..58df607 100644
--- a/libgo/go/net/iprawsock_plan9.go
+++ b/libgo/go/net/iprawsock_plan9.go
@@ -8,12 +8,28 @@ package net
import (
"os"
+ "time"
)
// IPConn is the implementation of the Conn and PacketConn
// interfaces for IP network connections.
type IPConn bool
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *IPConn) SetDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *IPConn) SetReadDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *IPConn) SetWriteDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
// Implementation of the Conn interface - see Conn for documentation.
// Read implements the net.Conn Read method.
@@ -41,21 +57,6 @@ func (c *IPConn) RemoteAddr() Addr {
return nil
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) error {
- return os.EPLAN9
-}
-
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) error {
- return os.EPLAN9
-}
-
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) error {
- return os.EPLAN9
-}
-
// IP-specific methods.
// ReadFrom implements the net.PacketConn ReadFrom method.
@@ -68,7 +69,7 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToIP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
return 0, os.EPLAN9
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index 103c4f6..e4f755b 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -12,6 +12,7 @@ import (
"errors"
"os"
"syscall"
+ "time"
)
func sockaddrToIP(sa syscall.Sockaddr) Addr {
@@ -97,28 +98,28 @@ func (c *IPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *IPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *IPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *IPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -146,8 +147,8 @@ func (c *IPConn) SetWriteBuffer(bytes int) error {
// that was on the packet.
//
// ReadFromIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetTimeout and
-// SetReadTimeout.
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -182,7 +183,7 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToIP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
if !c.ok() {
diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go
index 42fb408..09d8d6b 100644
--- a/libgo/go/net/ipsock_plan9.go
+++ b/libgo/go/net/ipsock_plan9.go
@@ -10,6 +10,7 @@ import (
"errors"
"io"
"os"
+ "time"
)
// probeIPv6Stack returns two boolean values. If the first boolean value is
@@ -156,27 +157,18 @@ func (c *plan9Conn) RemoteAddr() Addr {
return c.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *plan9Conn) SetTimeout(nsec int64) error {
- if !c.ok() {
- return os.EINVAL
- }
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *plan9Conn) SetDeadline(t time.Time) error {
return os.EPLAN9
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *plan9Conn) SetReadTimeout(nsec int64) error {
- if !c.ok() {
- return os.EINVAL
- }
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *plan9Conn) SetReadDeadline(t time.Time) error {
return os.EPLAN9
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *plan9Conn) SetWriteTimeout(nsec int64) error {
- if !c.ok() {
- return os.EINVAL
- }
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *plan9Conn) SetWriteDeadline(t time.Time) error {
return os.EPLAN9
}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index 45fe0d9..3a059f5 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -101,7 +101,7 @@ type sockaddr interface {
family() int
}
-func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+func internetSocket(net string, laddr, raddr sockaddr, sotype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
var oserr error
var la, ra syscall.Sockaddr
family := favoriteAddrFamily(net, raddr, laddr, mode)
@@ -115,7 +115,7 @@ func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode
goto Error
}
}
- fd, oserr = socket(net, family, socktype, proto, la, ra, toAddr)
+ fd, oserr = socket(net, family, sotype, proto, la, ra, toAddr)
if oserr != nil {
goto Error
}
diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go
index 027794a..645aa6d 100644
--- a/libgo/go/net/lookup_plan9.go
+++ b/libgo/go/net/lookup_plan9.go
@@ -69,9 +69,7 @@ func queryDNS(addr string, typ string) (res []string, err error) {
return query("/net/dns", addr+" "+typ, 1024)
}
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err error) {
+func lookupHost(host string) (addrs []string, err error) {
// Use /net/cs insead of /net/dns because cs knows about
// host names in local network (e.g. from /lib/ndb/local)
lines, err := queryCS("tcp", host, "1")
@@ -95,9 +93,7 @@ func LookupHost(host string) (addrs []string, err error) {
return
}
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (ips []IP, err error) {
+func lookupIP(host string) (ips []IP, err error) {
addrs, err := LookupHost(host)
if err != nil {
return
@@ -110,8 +106,7 @@ func LookupIP(host string) (ips []IP, err error) {
return
}
-// LookupPort looks up the port for the given network and service.
-func LookupPort(network, service string) (port int, err error) {
+func lookupPort(network, service string) (port int, err error) {
switch network {
case "tcp4", "tcp6":
network = "tcp"
@@ -140,11 +135,7 @@ func LookupPort(network, service string) (port int, err error) {
return 0, unknownPortError
}
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err error) {
+func lookupCNAME(name string) (cname string, err error) {
lines, err := queryDNS(name, "cname")
if err != nil {
return
@@ -157,16 +148,7 @@ func LookupCNAME(name string) (cname string, err error) {
return "", errors.New("net: bad response from ndb/dns")
}
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name. The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name. To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
var target string
if service == "" && proto == "" {
target = name
@@ -195,8 +177,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
return
}
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mx []*MX, err error) {
+func lookupMX(name string) (mx []*MX, err error) {
lines, err := queryDNS(name, "mx")
if err != nil {
return
@@ -214,8 +195,7 @@ func LookupMX(name string) (mx []*MX, err error) {
return
}
-// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txt []string, err error) {
+func lookupTXT(name string) (txt []string, err error) {
lines, err := queryDNS(name, "txt")
if err != nil {
return
@@ -228,9 +208,7 @@ func LookupTXT(name string) (txt []string, err error) {
return
}
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-func LookupAddr(addr string) (name []string, err error) {
+func lookupAddr(addr string) (name []string, err error) {
arpa, err := reverseaddr(addr)
if err != nil {
return
diff --git a/libgo/go/net/lookup_unix.go b/libgo/go/net/lookup_unix.go
index 5c47547..d500a12 100644
--- a/libgo/go/net/lookup_unix.go
+++ b/libgo/go/net/lookup_unix.go
@@ -52,9 +52,7 @@ func lookupProtocol(name string) (proto int, err error) {
return
}
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err error) {
+func lookupHost(host string) (addrs []string, err error) {
addrs, err, ok := cgoLookupHost(host)
if !ok {
addrs, err = goLookupHost(host)
@@ -62,9 +60,7 @@ func LookupHost(host string) (addrs []string, err error) {
return
}
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (addrs []IP, err error) {
+func lookupIP(host string) (addrs []IP, err error) {
addrs, err, ok := cgoLookupIP(host)
if !ok {
addrs, err = goLookupIP(host)
@@ -72,8 +68,7 @@ func LookupIP(host string) (addrs []IP, err error) {
return
}
-// LookupPort looks up the port for the given network and service.
-func LookupPort(network, service string) (port int, err error) {
+func lookupPort(network, service string) (port int, err error) {
port, err, ok := cgoLookupPort(network, service)
if !ok {
port, err = goLookupPort(network, service)
@@ -81,11 +76,7 @@ func LookupPort(network, service string) (port int, err error) {
return
}
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err error) {
+func lookupCNAME(name string) (cname string, err error) {
cname, err, ok := cgoLookupCNAME(name)
if !ok {
cname, err = goLookupCNAME(name)
@@ -93,16 +84,7 @@ func LookupCNAME(name string) (cname string, err error) {
return
}
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name. The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name. To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
var target string
if service == "" && proto == "" {
target = name
@@ -123,8 +105,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
return
}
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mx []*MX, err error) {
+func lookupMX(name string) (mx []*MX, err error) {
_, records, err := lookup(name, dnsTypeMX)
if err != nil {
return
@@ -138,8 +119,7 @@ func LookupMX(name string) (mx []*MX, err error) {
return
}
-// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txt []string, err error) {
+func lookupTXT(name string) (txt []string, err error) {
_, records, err := lookup(name, dnsTypeTXT)
if err != nil {
return
@@ -151,9 +131,7 @@ func LookupTXT(name string) (txt []string, err error) {
return
}
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-func LookupAddr(addr string) (name []string, err error) {
+func lookupAddr(addr string) (name []string, err error) {
name = lookupStaticAddr(addr)
if len(name) > 0 {
return
diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go
index 51afbd4..dfe2ff6 100644
--- a/libgo/go/net/lookup_windows.go
+++ b/libgo/go/net/lookup_windows.go
@@ -28,7 +28,7 @@ func lookupProtocol(name string) (proto int, err error) {
return int(p.Proto), nil
}
-func LookupHost(name string) (addrs []string, err error) {
+func lookupHost(name string) (addrs []string, err error) {
ips, err := LookupIP(name)
if err != nil {
return
@@ -40,7 +40,7 @@ func LookupHost(name string) (addrs []string, err error) {
return
}
-func LookupIP(name string) (addrs []IP, err error) {
+func lookupIP(name string) (addrs []IP, err error) {
hostentLock.Lock()
defer hostentLock.Unlock()
h, e := syscall.GetHostByName(name)
@@ -61,7 +61,7 @@ func LookupIP(name string) (addrs []IP, err error) {
return addrs, nil
}
-func LookupPort(network, service string) (port int, err error) {
+func lookupPort(network, service string) (port int, err error) {
switch network {
case "tcp4", "tcp6":
network = "tcp"
@@ -77,7 +77,7 @@ func LookupPort(network, service string) (port int, err error) {
return int(syscall.Ntohs(s.Port)), nil
}
-func LookupCNAME(name string) (cname string, err error) {
+func lookupCNAME(name string) (cname string, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
if e != nil {
@@ -91,16 +91,7 @@ func LookupCNAME(name string) (cname string, err error) {
return
}
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name. The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name. To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
var target string
if service == "" && proto == "" {
target = name
@@ -122,7 +113,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
return name, addrs, nil
}
-func LookupMX(name string) (mx []*MX, err error) {
+func lookupMX(name string) (mx []*MX, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
if e != nil {
@@ -138,7 +129,7 @@ func LookupMX(name string) (mx []*MX, err error) {
return mx, nil
}
-func LookupTXT(name string) (txt []string, err error) {
+func lookupTXT(name string) (txt []string, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
if e != nil {
@@ -156,7 +147,7 @@ func LookupTXT(name string) (txt []string, err error) {
return
}
-func LookupAddr(addr string) (name []string, err error) {
+func lookupAddr(addr string) (name []string, err error) {
arpa, err := reverseaddr(addr)
if err != nil {
return nil, err
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index b236dfd..609fee2 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -9,7 +9,10 @@ package net
// TODO(rsc):
// support for raw ethernet sockets
-import "errors"
+import (
+ "errors"
+ "time"
+)
// Addr represents a network end point address.
type Addr interface {
@@ -21,12 +24,12 @@ type Addr interface {
type Conn interface {
// Read reads data from the connection.
// Read can be made to time out and return a net.Error with Timeout() == true
- // after a fixed time limit; see SetTimeout and SetReadTimeout.
+ // after a fixed time limit; see SetDeadline and SetReadDeadline.
Read(b []byte) (n int, err error)
// Write writes data to the connection.
// Write can be made to time out and return a net.Error with Timeout() == true
- // after a fixed time limit; see SetTimeout and SetWriteTimeout.
+ // after a fixed time limit; see SetDeadline and SetWriteDeadline.
Write(b []byte) (n int, err error)
// Close closes the connection.
@@ -38,21 +41,23 @@ type Conn interface {
// RemoteAddr returns the remote network address.
RemoteAddr() Addr
- // SetTimeout sets the read and write deadlines associated
+ // SetDeadline sets the read and write deadlines associated
// with the connection.
- SetTimeout(nsec int64) error
-
- // SetReadTimeout sets the time (in nanoseconds) that
- // Read will wait for data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
- SetReadTimeout(nsec int64) error
-
- // SetWriteTimeout sets the time (in nanoseconds) that
- // Write will wait to send its data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
+ SetDeadline(t time.Time) error
+
+ // SetReadDeadline sets the deadline for all Read calls to return.
+ // If the deadline is reached, Read will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Read will not time out.
+ SetReadDeadline(t time.Time) error
+
+ // SetWriteDeadline sets the deadline for all Write calls to return.
+ // If the deadline is reached, Write will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Write will not time out.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
- SetWriteTimeout(nsec int64) error
+ SetWriteDeadline(t time.Time) error
}
// An Error represents a network error.
@@ -70,13 +75,13 @@ type PacketConn interface {
// was on the packet.
// ReadFrom can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
- // see SetTimeout and SetReadTimeout.
+ // see SetDeadline and SetReadDeadline.
ReadFrom(b []byte) (n int, addr Addr, err error)
// WriteTo writes a packet with payload b to addr.
// WriteTo can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
- // see SetTimeout and SetWriteTimeout.
+ // see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
WriteTo(b []byte, addr Addr) (n int, err error)
@@ -86,21 +91,23 @@ type PacketConn interface {
// LocalAddr returns the local network address.
LocalAddr() Addr
- // SetTimeout sets the read and write deadlines associated
+ // SetDeadline sets the read and write deadlines associated
// with the connection.
- SetTimeout(nsec int64) error
-
- // SetReadTimeout sets the time (in nanoseconds) that
- // Read will wait for data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
- SetReadTimeout(nsec int64) error
-
- // SetWriteTimeout sets the time (in nanoseconds) that
- // Write will wait to send its data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
+ SetDeadline(t time.Time) error
+
+ // SetReadDeadline sets the deadline for all Read calls to return.
+ // If the deadline is reached, Read will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Read will not time out.
+ SetReadDeadline(t time.Time) error
+
+ // SetWriteDeadline sets the deadline for all Write calls to return.
+ // If the deadline is reached, Write will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Write will not time out.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
- SetWriteTimeout(nsec int64) error
+ SetWriteDeadline(t time.Time) error
}
// A Listener is a generic network listener for stream-oriented protocols.
diff --git a/libgo/go/net/pipe.go b/libgo/go/net/pipe.go
index 0ce7ccb..f1a2eca 100644
--- a/libgo/go/net/pipe.go
+++ b/libgo/go/net/pipe.go
@@ -7,6 +7,7 @@ package net
import (
"errors"
"io"
+ "time"
)
// Pipe creates a synchronous, in-memory, full duplex
@@ -53,14 +54,14 @@ func (p *pipe) RemoteAddr() Addr {
return pipeAddr(0)
}
-func (p *pipe) SetTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
-func (p *pipe) SetReadTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetReadDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
-func (p *pipe) SetWriteTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetWriteDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
diff --git a/libgo/go/net/sendfile_linux.go b/libgo/go/net/sendfile_linux.go
index 350abe4..e9ab066 100644
--- a/libgo/go/net/sendfile_linux.go
+++ b/libgo/go/net/sendfile_linux.go
@@ -40,15 +40,6 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
defer c.wio.Unlock()
c.incref()
defer c.decref()
- if c.wdeadline_delta > 0 {
- // This is a little odd that we're setting the timeout
- // for the entire file but Write has the same issue
- // (if one slurps the whole file into memory and
- // do one large Write). At least they're consistent.
- c.wdeadline = pollserver.Now() + c.wdeadline_delta
- } else {
- c.wdeadline = 0
- }
dst := c.sysfd
src := f.Fd()
diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go
index 5475d38..b0b546b 100644
--- a/libgo/go/net/server_test.go
+++ b/libgo/go/net/server_test.go
@@ -11,6 +11,7 @@ import (
"runtime"
"strings"
"testing"
+ "time"
)
// Do not test empty datagrams by default.
@@ -63,7 +64,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
if err != nil {
t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
}
- fd.SetReadTimeout(1e9) // 1s
+ fd.SetReadDeadline(time.Now().Add(1 * time.Second))
var b []byte
if !isEmpty {
@@ -91,7 +92,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
}
func doTest(t *testing.T, network, listenaddr, dialaddr string) {
- t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr)
+ t.Logf("Test %q %q %q", network, listenaddr, dialaddr)
switch listenaddr {
case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
if testing.Short() || avoidMacFirewall {
@@ -169,10 +170,10 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done
t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
}
listening <- c.LocalAddr().String()
- c.SetReadTimeout(10e6) // 10ms
var buf [1000]byte
Run:
for {
+ c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
n, addr, err := c.ReadFrom(buf[0:])
if e, ok := err.(Error); ok && e.Timeout() {
select {
@@ -194,7 +195,7 @@ Run:
}
func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
- t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
+ t.Logf("TestPacket %q %q %q", network, listenaddr, dialaddr)
listening := make(chan string)
done := make(chan int)
if network == "udp" {
diff --git a/libgo/go/net/smtp/auth.go b/libgo/go/net/smtp/auth.go
index 6f0cde0..d401e3c 100644
--- a/libgo/go/net/smtp/auth.go
+++ b/libgo/go/net/smtp/auth.go
@@ -6,6 +6,7 @@ package smtp
import (
"crypto/hmac"
+ "crypto/md5"
"errors"
"fmt"
)
@@ -88,7 +89,7 @@ func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) {
func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
- d := hmac.NewMD5([]byte(a.secret))
+ d := hmac.New(md5.New, []byte(a.secret))
d.Write(fromServer)
s := make([]byte, 0, d.Size())
return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index 881c922..2f3210b 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -17,10 +17,10 @@ import (
var listenerBacklog = maxListenerBacklog()
// Generic socket creation.
-func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
// See ../syscall/exec.go for description of ForkLock.
syscall.ForkLock.RLock()
- s, e := syscall.Socket(f, p, t)
+ s, err := syscall.Socket(f, t, p)
if err != nil {
syscall.ForkLock.RUnlock()
return nil, err
@@ -28,17 +28,17 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
- setDefaultSockopts(s, f, p)
+ setDefaultSockopts(s, f, t)
if la != nil {
- e = syscall.Bind(s, la)
- if e != nil {
+ err = syscall.Bind(s, la)
+ if err != nil {
closesocket(s)
- return nil, e
+ return nil, err
}
}
- if fd, err = newFD(s, f, p, net); err != nil {
+ if fd, err = newFD(s, f, t, net); err != nil {
closesocket(s)
return nil, err
}
diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt.go
index 7fa1052..59f9af5 100644
--- a/libgo/go/net/sockopt.go
+++ b/libgo/go/net/sockopt.go
@@ -12,6 +12,7 @@ import (
"bytes"
"os"
"syscall"
+ "time"
)
// Boolean to int.
@@ -115,21 +116,21 @@ func setWriteBuffer(fd *netFD, bytes int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
}
-func setReadTimeout(fd *netFD, nsec int64) error {
- fd.rdeadline_delta = nsec
+func setReadDeadline(fd *netFD, t time.Time) error {
+ fd.rdeadline = t.UnixNano()
return nil
}
-func setWriteTimeout(fd *netFD, nsec int64) error {
- fd.wdeadline_delta = nsec
+func setWriteDeadline(fd *netFD, t time.Time) error {
+ fd.wdeadline = t.UnixNano()
return nil
}
-func setTimeout(fd *netFD, nsec int64) error {
- if e := setReadTimeout(fd, nsec); e != nil {
+func setDeadline(fd *netFD, t time.Time) error {
+ if e := setReadDeadline(fd, t); e != nil {
return e
}
- return setWriteTimeout(fd, nsec)
+ return setWriteDeadline(fd, t)
}
func setReuseAddr(fd *netFD, reuse bool) error {
diff --git a/libgo/go/net/sockopt_bsd.go b/libgo/go/net/sockopt_bsd.go
index e99fb41..2093e08 100644
--- a/libgo/go/net/sockopt_bsd.go
+++ b/libgo/go/net/sockopt_bsd.go
@@ -12,14 +12,15 @@ import (
"syscall"
)
-func setDefaultSockopts(s, f, p int) {
+func setDefaultSockopts(s, f, t int) {
switch f {
case syscall.AF_INET6:
// Allow both IP versions even if the OS default is otherwise.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
}
- if f == syscall.AF_UNIX || p == syscall.IPPROTO_TCP {
+ if f == syscall.AF_UNIX ||
+ (f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
// Allow reuse of recently-used addresses.
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
diff --git a/libgo/go/net/sockopt_linux.go b/libgo/go/net/sockopt_linux.go
index 5158384..9dbb4e5 100644
--- a/libgo/go/net/sockopt_linux.go
+++ b/libgo/go/net/sockopt_linux.go
@@ -10,14 +10,15 @@ import (
"syscall"
)
-func setDefaultSockopts(s, f, p int) {
+func setDefaultSockopts(s, f, t int) {
switch f {
case syscall.AF_INET6:
// Allow both IP versions even if the OS default is otherwise.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
}
- if f == syscall.AF_UNIX || p == syscall.IPPROTO_TCP {
+ if f == syscall.AF_UNIX ||
+ (f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
// Allow reuse of recently-used addresses.
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
}
diff --git a/libgo/go/net/sockopt_windows.go b/libgo/go/net/sockopt_windows.go
index 485c14a..a7b5606 100644
--- a/libgo/go/net/sockopt_windows.go
+++ b/libgo/go/net/sockopt_windows.go
@@ -10,7 +10,7 @@ import (
"syscall"
)
-func setDefaultSockopts(s syscall.Handle, f, p int) {
+func setDefaultSockopts(s syscall.Handle, f, t int) {
switch f {
case syscall.AF_INET6:
// Allow both IP versions even if the OS default is otherwise.
diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go
index 69fae03..288ec05 100644
--- a/libgo/go/net/tcpsock_plan9.go
+++ b/libgo/go/net/tcpsock_plan9.go
@@ -8,6 +8,7 @@ package net
import (
"os"
+ "time"
)
// TCPConn is an implementation of the Conn interface
@@ -16,6 +17,21 @@ type TCPConn struct {
plan9Conn
}
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *TCPConn) SetDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *TCPConn) SetReadDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *TCPConn) SetWriteDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
// CloseRead shuts down the reading side of the TCP connection.
// Most callers should just use Close.
func (c *TCPConn) CloseRead() error {
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index a492e61..91816fa 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -12,6 +12,7 @@ import (
"io"
"os"
"syscall"
+ "time"
)
// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
@@ -134,28 +135,28 @@ func (c *TCPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *TCPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *TCPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *TCPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *TCPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *TCPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *TCPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -294,12 +295,13 @@ func (l *TCPListener) Close() error {
// Addr returns the listener's network address, a *TCPAddr.
func (l *TCPListener) Addr() Addr { return l.fd.laddr }
-// SetTimeout sets the deadline associated with the listener
-func (l *TCPListener) SetTimeout(nsec int64) error {
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
if l == nil || l.fd == nil {
return os.EINVAL
}
- return setTimeout(l.fd, nsec)
+ return setDeadline(l.fd, t)
}
// File returns a copy of the underlying os.File, set to blocking mode.
diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go
index f6e5238..11db012 100644
--- a/libgo/go/net/timeout_test.go
+++ b/libgo/go/net/timeout_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"runtime"
"testing"
"time"
@@ -17,26 +18,41 @@ func testTimeout(t *testing.T, network, addr string, readFrom bool) {
return
}
defer fd.Close()
- t0 := time.Now()
- fd.SetReadTimeout(1e8) // 100ms
- var b [100]byte
- var n int
- var err1 error
- if readFrom {
- n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
- } else {
- n, err1 = fd.Read(b[0:])
- }
- t1 := time.Now()
what := "Read"
if readFrom {
what = "ReadFrom"
}
- if n != 0 || err1 == nil || !err1.(Error).Timeout() {
- t.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
- }
- if dt := t1.Sub(t0); dt < 50*time.Millisecond || dt > 150*time.Millisecond {
- t.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+
+ errc := make(chan error, 1)
+ go func() {
+ t0 := time.Now()
+ fd.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+ var b [100]byte
+ var n int
+ var err1 error
+ if readFrom {
+ n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
+ } else {
+ n, err1 = fd.Read(b[0:])
+ }
+ t1 := time.Now()
+ if n != 0 || err1 == nil || !err1.(Error).Timeout() {
+ errc <- fmt.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
+ return
+ }
+ if dt := t1.Sub(t0); dt < 50*time.Millisecond || dt > 250*time.Millisecond {
+ errc <- fmt.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+ return
+ }
+ errc <- nil
+ }()
+ select {
+ case err := <-errc:
+ if err != nil {
+ t.Error(err)
+ }
+ case <-time.After(1 * time.Second):
+ t.Errorf("%s on %s %s took over 1 second, expected 0.1s", what, network, addr)
}
}
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index 60dec81..246c9ad 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -9,6 +9,7 @@ package net
import (
"errors"
"os"
+ "time"
)
// UDPConn is the implementation of the Conn and PacketConn
@@ -17,6 +18,21 @@ type UDPConn struct {
plan9Conn
}
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UDPConn) SetDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UDPConn) SetReadDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UDPConn) SetWriteDeadline(t time.Time) error {
+ return os.EPLAN9
+}
+
// UDP-specific methods.
// ReadFromUDP reads a UDP packet from c, copying the payload into b.
@@ -24,7 +40,7 @@ type UDPConn struct {
// that was on the packet.
//
// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -62,7 +78,7 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToUDP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
if !c.ok() {
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index d0bdb14..0b5bc16 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -11,6 +11,7 @@ package net
import (
"os"
"syscall"
+ "time"
)
func sockaddrToUDP(sa syscall.Sockaddr) Addr {
@@ -98,28 +99,28 @@ func (c *UDPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UDPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UDPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UDPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UDPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UDPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UDPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -147,7 +148,7 @@ func (c *UDPConn) SetWriteBuffer(bytes int) error {
// that was on the packet.
//
// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -175,7 +176,7 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToUDP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
if !c.ok() {
diff --git a/libgo/go/net/unicast_test.go b/libgo/go/net/unicast_test.go
index 6ed6f59..297276d 100644
--- a/libgo/go/net/unicast_test.go
+++ b/libgo/go/net/unicast_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "io"
"runtime"
"testing"
)
@@ -15,10 +16,12 @@ var unicastTests = []struct {
ipv6 bool
packet bool
}{
- {"tcp4", "127.0.0.1:0", false, false},
- {"tcp6", "[::1]:0", true, false},
- {"udp4", "127.0.0.1:0", false, true},
- {"udp6", "[::1]:0", true, true},
+ {net: "tcp4", laddr: "127.0.0.1:0"},
+ {net: "tcp4", laddr: "previous"},
+ {net: "tcp6", laddr: "[::1]:0", ipv6: true},
+ {net: "tcp6", laddr: "previous", ipv6: true},
+ {net: "udp4", laddr: "127.0.0.1:0", packet: true},
+ {net: "udp6", laddr: "[::1]:0", ipv6: true, packet: true},
}
func TestUnicastTCPAndUDP(t *testing.T) {
@@ -26,24 +29,32 @@ func TestUnicastTCPAndUDP(t *testing.T) {
return
}
+ prevladdr := ""
for _, tt := range unicastTests {
if tt.ipv6 && !supportsIPv6 {
continue
}
- var fd *netFD
+ var (
+ fd *netFD
+ closer io.Closer
+ )
if !tt.packet {
- c, err := Listen(tt.net, tt.laddr)
+ if tt.laddr == "previous" {
+ tt.laddr = prevladdr
+ }
+ l, err := Listen(tt.net, tt.laddr)
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
- defer c.Close()
- fd = c.(*TCPListener).fd
+ prevladdr = l.Addr().String()
+ closer = l
+ fd = l.(*TCPListener).fd
} else {
c, err := ListenPacket(tt.net, tt.laddr)
if err != nil {
t.Fatalf("ListenPacket failed: %v", err)
}
- defer c.Close()
+ closer = c
fd = c.(*UDPConn).fd
}
if !tt.ipv6 {
@@ -51,6 +62,7 @@ func TestUnicastTCPAndUDP(t *testing.T) {
} else {
testIPv6UnicastSocketOptions(t, fd)
}
+ closer.Close()
}
}
diff --git a/libgo/go/net/unixsock_plan9.go b/libgo/go/net/unixsock_plan9.go
index ac502d1..e8087d0 100644
--- a/libgo/go/net/unixsock_plan9.go
+++ b/libgo/go/net/unixsock_plan9.go
@@ -8,6 +8,7 @@ package net
import (
"os"
+ "time"
)
// UnixConn is an implementation of the Conn interface
@@ -44,18 +45,18 @@ func (c *UnixConn) RemoteAddr() Addr {
return nil
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UnixConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UnixConn) SetDeadline(t time.Time) error {
return os.EPLAN9
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UnixConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UnixConn) SetReadDeadline(t time.Time) error {
return os.EPLAN9
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UnixConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UnixConn) SetWriteDeadline(t time.Time) error {
return os.EPLAN9
}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 00ee016..5b8b2e4 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -11,19 +11,20 @@ package net
import (
"os"
"syscall"
+ "time"
)
func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err error) {
- var proto int
+ var sotype int
switch net {
default:
return nil, UnknownNetworkError(net)
case "unix":
- proto = syscall.SOCK_STREAM
+ sotype = syscall.SOCK_STREAM
case "unixgram":
- proto = syscall.SOCK_DGRAM
+ sotype = syscall.SOCK_DGRAM
case "unixpacket":
- proto = syscall.SOCK_SEQPACKET
+ sotype = syscall.SOCK_SEQPACKET
}
var la, ra syscall.Sockaddr
@@ -37,7 +38,7 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
}
if raddr != nil {
ra = &syscall.SockaddrUnix{Name: raddr.Name}
- } else if proto != syscall.SOCK_DGRAM || laddr == nil {
+ } else if sotype != syscall.SOCK_DGRAM || laddr == nil {
return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
}
@@ -52,13 +53,13 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
}
f := sockaddrToUnix
- if proto == syscall.SOCK_DGRAM {
+ if sotype == syscall.SOCK_DGRAM {
f = sockaddrToUnixgram
- } else if proto == syscall.SOCK_SEQPACKET {
+ } else if sotype == syscall.SOCK_SEQPACKET {
f = sockaddrToUnixpacket
}
- fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
+ fd, oserr := socket(net, syscall.AF_UNIX, sotype, 0, la, ra, f)
if oserr != nil {
goto Error
}
@@ -93,8 +94,8 @@ func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
return nil
}
-func protoToNet(proto int) string {
- switch proto {
+func sotypeToNet(sotype int) string {
+ switch sotype {
case syscall.SOCK_STREAM:
return "unix"
case syscall.SOCK_SEQPACKET:
@@ -102,7 +103,7 @@ func protoToNet(proto int) string {
case syscall.SOCK_DGRAM:
return "unixgram"
default:
- panic("protoToNet unknown protocol")
+ panic("sotypeToNet unknown socket type")
}
return ""
}
@@ -164,28 +165,28 @@ func (c *UnixConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UnixConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UnixConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UnixConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UnixConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UnixConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UnixConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -212,7 +213,7 @@ func (c *UnixConn) SetWriteBuffer(bytes int) error {
//
// ReadFromUnix can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetReadTimeout.
+// see SetDeadline and SetReadDeadline.
func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -220,7 +221,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
n, sa, err := c.fd.ReadFrom(b)
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
- addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
+ addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
}
return
}
@@ -238,13 +239,13 @@ func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToUnix can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
if !c.ok() {
return 0, os.EINVAL
}
- if addr.Net != protoToNet(c.fd.proto) {
+ if addr.Net != sotypeToNet(c.fd.sotype) {
return 0, os.EAFNOSUPPORT
}
sa := &syscall.SockaddrUnix{Name: addr.Name}
@@ -270,7 +271,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
- addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
+ addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
}
return
}
@@ -280,7 +281,7 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
return 0, 0, os.EINVAL
}
if addr != nil {
- if addr.Net != protoToNet(c.fd.proto) {
+ if addr.Net != sotypeToNet(c.fd.sotype) {
return 0, 0, os.EAFNOSUPPORT
}
sa := &syscall.SockaddrUnix{Name: addr.Name}
@@ -386,12 +387,13 @@ func (l *UnixListener) Close() error {
// Addr returns the listener's network address.
func (l *UnixListener) Addr() Addr { return l.fd.laddr }
-// SetTimeout sets the deadline associated wuth the listener
-func (l *UnixListener) SetTimeout(nsec int64) (err error) {
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) (err error) {
if l == nil || l.fd == nil {
return os.EINVAL
}
- return setTimeout(l.fd, nsec)
+ return setDeadline(l.fd, t)
}
// File returns a copy of the underlying os.File, set to blocking mode.
diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go
index 11fa189..0068e98 100644
--- a/libgo/go/net/url/url.go
+++ b/libgo/go/net/url/url.go
@@ -52,7 +52,6 @@ const (
encodeUserPassword
encodeQueryComponent
encodeFragment
- encodeOpaque
)
type EscapeError string
@@ -69,6 +68,7 @@ func shouldEscape(c byte, mode encoding) bool {
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
return false
}
+ // TODO: Update the character sets after RFC 3986.
switch c {
case '-', '_', '.', '!', '~', '*', '\'', '(', ')': // §2.3 Unreserved characters (mark)
return false
@@ -78,12 +78,10 @@ func shouldEscape(c byte, mode encoding) bool {
// the reserved characters to appear unescaped.
switch mode {
case encodePath: // §3.3
- // The RFC allows : @ & = + $ , but saves / ; for assigning
- // meaning to individual path segments. This package
+ // The RFC allows : @ & = + $ but saves / ; , for assigning
+ // meaning to individual path segments. This package
// only manipulates the path as a whole, so we allow those
- // last two as well. Clients that need to distinguish between
- // `/foo;y=z/bar` and `/foo%3by=z/bar` will have to re-decode RawPath.
- // That leaves only ? to escape.
+ // last two as well. That leaves only ? to escape.
return c == '?'
case encodeUserPassword: // §3.2.2
@@ -99,12 +97,6 @@ func shouldEscape(c byte, mode encoding) bool {
// The RFC text is silent but the grammar allows
// everything, so escape nothing.
return false
-
- case encodeOpaque: // §3 opaque_part
- // The RFC allows opaque_part to use all characters
- // except that the leading / must be escaped.
- // (We implement that case in String.)
- return false
}
}
@@ -217,64 +209,73 @@ func escape(s string, mode encoding) string {
return string(t)
}
-// UnescapeUserinfo parses the RawUserinfo field of a URL
-// as the form user or user:password and unescapes and returns
-// the two halves.
+// A URL represents a parsed URL (technically, a URI reference).
+// The general form represented is:
//
-// This functionality should only be used with legacy web sites.
-// RFC 2396 warns that interpreting Userinfo this way
-// ``is NOT RECOMMENDED, because the passing of authentication
-// information in clear text (such as URI) has proven to be a
-// security risk in almost every case where it has been used.''
-func UnescapeUserinfo(rawUserinfo string) (user, password string, err error) {
- u, p := split(rawUserinfo, ':', true)
- if user, err = unescape(u, encodeUserPassword); err != nil {
- return "", "", err
- }
- if password, err = unescape(p, encodeUserPassword); err != nil {
- return "", "", err
- }
- return
+// scheme://[userinfo@]host/path[?query][#fragment]
+//
+// URLs that do not start with a slash after the scheme are interpreted as:
+//
+// scheme:opaque[?query][#fragment]
+//
+type URL struct {
+ Scheme string
+ Opaque string // encoded opaque data
+ User *Userinfo // username and password information
+ Host string
+ Path string
+ RawQuery string // encoded query values, without '?'
+ Fragment string // fragment for references, without '#'
}
-// EscapeUserinfo combines user and password in the form
-// user:password (or just user if password is empty) and then
-// escapes it for use as the URL.RawUserinfo field.
-//
+// User returns a Userinfo containing the provided username
+// and no password set.
+func User(username string) *Userinfo {
+ return &Userinfo{username, "", false}
+}
+
+// UserPassword returns a Userinfo containing the provided username
+// and password.
// This functionality should only be used with legacy web sites.
// RFC 2396 warns that interpreting Userinfo this way
// ``is NOT RECOMMENDED, because the passing of authentication
// information in clear text (such as URI) has proven to be a
// security risk in almost every case where it has been used.''
-func EscapeUserinfo(user, password string) string {
- raw := escape(user, encodeUserPassword)
- if password != "" {
- raw += ":" + escape(password, encodeUserPassword)
+func UserPassword(username, password string) *Userinfo {
+ return &Userinfo{username, password, true}
+}
+
+// The Userinfo type is an immutable encapsulation of username and
+// password details for a URL. An existing Userinfo value is guaranteed
+// to have a username set (potentially empty, as allowed by RFC 2396),
+// and optionally a password.
+type Userinfo struct {
+ username string
+ password string
+ passwordSet bool
+}
+
+// Username returns the username.
+func (u *Userinfo) Username() string {
+ return u.username
+}
+
+// Password returns the password in case it is set, and whether it is set.
+func (u *Userinfo) Password() (string, bool) {
+ if u.passwordSet {
+ return u.password, true
}
- return raw
+ return "", false
}
-// A URL represents a parsed URL (technically, a URI reference).
-// The general form represented is:
-// scheme://[userinfo@]host/path[?query][#fragment]
-// The Raw, RawAuthority, RawPath, and RawQuery fields are in "wire format"
-// (special characters must be hex-escaped if not meant to have special meaning).
-// All other fields are logical values; '+' or '%' represent themselves.
-//
-// The various Raw values are supplied in wire format because
-// clients typically have to split them into pieces before further
-// decoding.
-type URL struct {
- Raw string // the original string
- Scheme string // scheme
- RawAuthority string // [userinfo@]host
- RawUserinfo string // userinfo
- Host string // host
- RawPath string // /path[?query][#fragment]
- Path string // /path
- OpaquePath bool // path is opaque (unrooted when scheme is present)
- RawQuery string // query
- Fragment string // fragment
+// String returns the encoded userinfo information in the standard form
+// of "username[:password]".
+func (u *Userinfo) String() string {
+ s := escape(u.username, encodeUserPassword)
+ if u.passwordSet {
+ s += ":" + escape(u.password, encodeUserPassword)
+ }
+ return s
}
// Maybe rawurl is of the form scheme:path.
@@ -341,136 +342,112 @@ func ParseRequest(rawurl string) (url *URL, err error) {
// in which case only absolute URLs or path-absolute relative URLs are allowed.
// If viaRequest is false, all forms of relative URLs are allowed.
func parse(rawurl string, viaRequest bool) (url *URL, err error) {
- var (
- leadingSlash bool
- path string
- )
+ var rest string
if rawurl == "" {
err = errors.New("empty url")
goto Error
}
url = new(URL)
- url.Raw = rawurl
// Split off possible leading "http:", "mailto:", etc.
// Cannot contain escaped characters.
- if url.Scheme, path, err = getscheme(rawurl); err != nil {
+ if url.Scheme, rest, err = getscheme(rawurl); err != nil {
goto Error
}
- leadingSlash = strings.HasPrefix(path, "/")
- if url.Scheme != "" && !leadingSlash {
- // RFC 2396:
- // Absolute URI (has scheme) with non-rooted path
- // is uninterpreted. It doesn't even have a ?query.
- // This is the case that handles mailto:name@example.com.
- url.RawPath = path
+ rest, url.RawQuery = split(rest, '?', true)
- if url.Path, err = unescape(path, encodeOpaque); err != nil {
- goto Error
+ if !strings.HasPrefix(rest, "/") {
+ if url.Scheme != "" {
+ // We consider rootless paths per RFC 3986 as opaque.
+ url.Opaque = rest
+ return url, nil
}
- url.OpaquePath = true
- } else {
- if viaRequest && !leadingSlash {
+ if viaRequest {
err = errors.New("invalid URI for request")
goto Error
}
+ }
- // Split off query before parsing path further.
- url.RawPath = path
- path, query := split(path, '?', false)
- if len(query) > 1 {
- url.RawQuery = query[1:]
- }
-
- // Maybe path is //authority/path
- if (url.Scheme != "" || !viaRequest) &&
- strings.HasPrefix(path, "//") && !strings.HasPrefix(path, "///") {
- url.RawAuthority, path = split(path[2:], '/', false)
- url.RawPath = url.RawPath[2+len(url.RawAuthority):]
- }
-
- // Split authority into userinfo@host.
- // If there's no @, split's default is wrong. Check explicitly.
- var rawHost string
- if strings.Index(url.RawAuthority, "@") < 0 {
- rawHost = url.RawAuthority
- } else {
- url.RawUserinfo, rawHost = split(url.RawAuthority, '@', true)
- }
-
- // We leave RawAuthority only in raw form because clients
- // of common protocols should be using Userinfo and Host
- // instead. Clients that wish to use RawAuthority will have to
- // interpret it themselves: RFC 2396 does not define the meaning.
-
- if strings.Contains(rawHost, "%") {
- // Host cannot contain escaped characters.
- err = errors.New("hexadecimal escape in host")
+ if (url.Scheme != "" || !viaRequest) && strings.HasPrefix(rest, "//") && !strings.HasPrefix(rest, "///") {
+ var authority string
+ authority, rest = split(rest[2:], '/', false)
+ url.User, url.Host, err = parseAuthority(authority)
+ if err != nil {
goto Error
}
- url.Host = rawHost
-
- if url.Path, err = unescape(path, encodePath); err != nil {
+ if strings.Contains(url.Host, "%") {
+ err = errors.New("hexadecimal escape in host")
goto Error
}
}
+ if url.Path, err = unescape(rest, encodePath); err != nil {
+ goto Error
+ }
return url, nil
Error:
return nil, &Error{"parse", rawurl, err}
+}
+func parseAuthority(authority string) (user *Userinfo, host string, err error) {
+ if strings.Index(authority, "@") < 0 {
+ host = authority
+ return
+ }
+ userinfo, host := split(authority, '@', true)
+ if strings.Index(userinfo, ":") < 0 {
+ if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
+ return
+ }
+ user = User(userinfo)
+ } else {
+ username, password := split(userinfo, ':', true)
+ if username, err = unescape(username, encodeUserPassword); err != nil {
+ return
+ }
+ if password, err = unescape(password, encodeUserPassword); err != nil {
+ return
+ }
+ user = UserPassword(username, password)
+ }
+ return
}
// ParseWithReference is like Parse but allows a trailing #fragment.
func ParseWithReference(rawurlref string) (url *URL, err error) {
- // Cut off #frag.
- rawurl, frag := split(rawurlref, '#', false)
+ // Cut off #frag
+ rawurl, frag := split(rawurlref, '#', true)
if url, err = Parse(rawurl); err != nil {
return nil, err
}
- url.Raw += frag
- url.RawPath += frag
- if len(frag) > 1 {
- frag = frag[1:]
- if url.Fragment, err = unescape(frag, encodeFragment); err != nil {
- return nil, &Error{"parse", rawurl, err}
- }
+ if frag == "" {
+ return url, nil
+ }
+ if url.Fragment, err = unescape(frag, encodeFragment); err != nil {
+ return nil, &Error{"parse", rawurlref, err}
}
return url, nil
}
// String reassembles url into a valid URL string.
-//
-// There are redundant fields stored in the URL structure:
-// the String method consults Scheme, Path, Host, RawUserinfo,
-// RawQuery, and Fragment, but not Raw, RawPath or RawAuthority.
func (url *URL) String() string {
+ // TODO: Rewrite to use bytes.Buffer
result := ""
if url.Scheme != "" {
result += url.Scheme + ":"
}
- if url.Host != "" || url.RawUserinfo != "" {
- result += "//"
- if url.RawUserinfo != "" {
- // hide the password, if any
- info := url.RawUserinfo
- if i := strings.Index(info, ":"); i >= 0 {
- info = info[0:i] + ":******"
+ if url.Opaque != "" {
+ result += url.Opaque
+ } else {
+ if url.Host != "" || url.User != nil {
+ result += "//"
+ if u := url.User; u != nil {
+ result += u.String() + "@"
}
- result += info + "@"
- }
- result += url.Host
- }
- if url.OpaquePath {
- path := url.Path
- if strings.HasPrefix(path, "/") {
- result += "%2f"
- path = path[1:]
+ result += url.Host
}
- result += escape(path, encodeOpaque)
- } else {
result += escape(url.Path, encodePath)
}
if url.RawQuery != "" {
@@ -630,47 +607,38 @@ func (base *URL) Parse(ref string) (*URL, error) {
// base or reference. If ref is an absolute URL, then ResolveReference
// ignores base and returns a copy of ref.
func (base *URL) ResolveReference(ref *URL) *URL {
- url := new(URL)
- switch {
- case ref.IsAbs():
- *url = *ref
- default:
- // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- *url = *base
- if ref.RawAuthority != "" {
- // The "net_path" case.
- url.RawAuthority = ref.RawAuthority
- url.Host = ref.Host
- url.RawUserinfo = ref.RawUserinfo
- }
- switch {
- case url.OpaquePath:
- url.Path = ref.Path
- url.RawPath = ref.RawPath
- url.RawQuery = ref.RawQuery
- case strings.HasPrefix(ref.Path, "/"):
- // The "abs_path" case.
- url.Path = ref.Path
- url.RawPath = ref.RawPath
- url.RawQuery = ref.RawQuery
- default:
- // The "rel_path" case.
- path := resolvePath(base.Path, ref.Path)
- if !strings.HasPrefix(path, "/") {
- path = "/" + path
- }
- url.Path = path
- url.RawPath = url.Path
- url.RawQuery = ref.RawQuery
- if ref.RawQuery != "" {
- url.RawPath += "?" + url.RawQuery
- }
+ if ref.IsAbs() {
+ url := *ref
+ return &url
+ }
+ // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+ url := *base
+ url.RawQuery = ref.RawQuery
+ url.Fragment = ref.Fragment
+ if ref.Opaque != "" {
+ url.Opaque = ref.Opaque
+ url.User = nil
+ url.Host = ""
+ url.Path = ""
+ return &url
+ }
+ if ref.Host != "" || ref.User != nil {
+ // The "net_path" case.
+ url.Host = ref.Host
+ url.User = ref.User
+ }
+ if strings.HasPrefix(ref.Path, "/") {
+ // The "abs_path" case.
+ url.Path = ref.Path
+ } else {
+ // The "rel_path" case.
+ path := resolvePath(base.Path, ref.Path)
+ if !strings.HasPrefix(path, "/") {
+ path = "/" + path
}
-
- url.Fragment = ref.Fragment
+ url.Path = path
}
- url.Raw = url.String()
- return url
+ return &url
}
// Query parses RawQuery and returns the corresponding values.
@@ -679,7 +647,18 @@ func (u *URL) Query() Values {
return v
}
-// EncodedPath returns the URL's path in "URL path encoded" form.
-func (u *URL) EncodedPath() string {
- return escape(u.Path, encodePath)
+// RequestURI returns the encoded path?query or opaque?query
+// string that would be used in an HTTP request for u.
+func (u *URL) RequestURI() string {
+ result := u.Opaque
+ if result == "" {
+ result = escape(u.Path, encodePath)
+ if result == "" {
+ result = "/"
+ }
+ }
+ if u.RawQuery != "" {
+ result += "?" + u.RawQuery
+ }
+ return result
}
diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go
index dab3bfa..9fe5ff8 100644
--- a/libgo/go/net/url/url_test.go
+++ b/libgo/go/net/url/url_test.go
@@ -21,10 +21,8 @@ var urltests = []URLTest{
{
"http://www.google.com",
&URL{
- Raw: "http://www.google.com",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
+ Scheme: "http",
+ Host: "www.google.com",
},
"",
},
@@ -32,12 +30,9 @@ var urltests = []URLTest{
{
"http://www.google.com/",
&URL{
- Raw: "http://www.google.com/",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/",
- Path: "/",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
},
"",
},
@@ -45,12 +40,9 @@ var urltests = []URLTest{
{
"http://www.google.com/file%20one%26two",
&URL{
- Raw: "http://www.google.com/file%20one%26two",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/file%20one%26two",
- Path: "/file one&two",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/file one&two",
},
"http://www.google.com/file%20one&two",
},
@@ -58,13 +50,10 @@ var urltests = []URLTest{
{
"ftp://webmaster@www.google.com/",
&URL{
- Raw: "ftp://webmaster@www.google.com/",
- Scheme: "ftp",
- RawAuthority: "webmaster@www.google.com",
- RawUserinfo: "webmaster",
- Host: "www.google.com",
- RawPath: "/",
- Path: "/",
+ Scheme: "ftp",
+ User: User("webmaster"),
+ Host: "www.google.com",
+ Path: "/",
},
"",
},
@@ -72,13 +61,10 @@ var urltests = []URLTest{
{
"ftp://john%20doe@www.google.com/",
&URL{
- Raw: "ftp://john%20doe@www.google.com/",
- Scheme: "ftp",
- RawAuthority: "john%20doe@www.google.com",
- RawUserinfo: "john%20doe",
- Host: "www.google.com",
- RawPath: "/",
- Path: "/",
+ Scheme: "ftp",
+ User: User("john doe"),
+ Host: "www.google.com",
+ Path: "/",
},
"ftp://john%20doe@www.google.com/",
},
@@ -86,13 +72,10 @@ var urltests = []URLTest{
{
"http://www.google.com/?q=go+language",
&URL{
- Raw: "http://www.google.com/?q=go+language",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/?q=go+language",
- Path: "/",
- RawQuery: "q=go+language",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ RawQuery: "q=go+language",
},
"",
},
@@ -100,13 +83,10 @@ var urltests = []URLTest{
{
"http://www.google.com/?q=go%20language",
&URL{
- Raw: "http://www.google.com/?q=go%20language",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/?q=go%20language",
- Path: "/",
- RawQuery: "q=go%20language",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ RawQuery: "q=go%20language",
},
"",
},
@@ -114,48 +94,39 @@ var urltests = []URLTest{
{
"http://www.google.com/a%20b?q=c+d",
&URL{
- Raw: "http://www.google.com/a%20b?q=c+d",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/a%20b?q=c+d",
- Path: "/a b",
- RawQuery: "q=c+d",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/a b",
+ RawQuery: "q=c+d",
},
"",
},
- // path without leading /, so no query parsing
+ // path without leading /, so no parsing
{
"http:www.google.com/?q=go+language",
&URL{
- Raw: "http:www.google.com/?q=go+language",
- Scheme: "http",
- RawPath: "www.google.com/?q=go+language",
- Path: "www.google.com/?q=go+language",
- OpaquePath: true,
+ Scheme: "http",
+ Opaque: "www.google.com/",
+ RawQuery: "q=go+language",
},
"http:www.google.com/?q=go+language",
},
- // path without leading /, so no query parsing
+ // path without leading /, so no parsing
{
"http:%2f%2fwww.google.com/?q=go+language",
&URL{
- Raw: "http:%2f%2fwww.google.com/?q=go+language",
- Scheme: "http",
- RawPath: "%2f%2fwww.google.com/?q=go+language",
- Path: "//www.google.com/?q=go+language",
- OpaquePath: true,
+ Scheme: "http",
+ Opaque: "%2f%2fwww.google.com/",
+ RawQuery: "q=go+language",
},
- "http:%2f/www.google.com/?q=go+language",
+ "http:%2f%2fwww.google.com/?q=go+language",
},
// non-authority
{
"mailto:/webmaster@golang.org",
&URL{
- Raw: "mailto:/webmaster@golang.org",
- Scheme: "mailto",
- RawPath: "/webmaster@golang.org",
- Path: "/webmaster@golang.org",
+ Scheme: "mailto",
+ Path: "/webmaster@golang.org",
},
"",
},
@@ -163,11 +134,8 @@ var urltests = []URLTest{
{
"mailto:webmaster@golang.org",
&URL{
- Raw: "mailto:webmaster@golang.org",
- Scheme: "mailto",
- RawPath: "webmaster@golang.org",
- Path: "webmaster@golang.org",
- OpaquePath: true,
+ Scheme: "mailto",
+ Opaque: "webmaster@golang.org",
},
"",
},
@@ -175,8 +143,6 @@ var urltests = []URLTest{
{
"/foo?query=http://bad",
&URL{
- Raw: "/foo?query=http://bad",
- RawPath: "/foo?query=http://bad",
Path: "/foo",
RawQuery: "query=http://bad",
},
@@ -186,12 +152,7 @@ var urltests = []URLTest{
{
"//foo",
&URL{
- RawAuthority: "foo",
- Raw: "//foo",
- Host: "foo",
- Scheme: "",
- RawPath: "",
- Path: "",
+ Host: "foo",
},
"",
},
@@ -199,14 +160,10 @@ var urltests = []URLTest{
{
"//user@foo/path?a=b",
&URL{
- Raw: "//user@foo/path?a=b",
- RawAuthority: "user@foo",
- RawUserinfo: "user",
- Scheme: "",
- RawPath: "/path?a=b",
- Path: "/path",
- RawQuery: "a=b",
- Host: "foo",
+ User: User("user"),
+ Host: "foo",
+ Path: "/path",
+ RawQuery: "a=b",
},
"",
},
@@ -218,36 +175,18 @@ var urltests = []URLTest{
{
"///threeslashes",
&URL{
- RawAuthority: "",
- Raw: "///threeslashes",
- Host: "",
- Scheme: "",
- RawPath: "///threeslashes",
- Path: "///threeslashes",
+ Path: "///threeslashes",
},
"",
},
{
"http://user:password@google.com",
&URL{
- Raw: "http://user:password@google.com",
- Scheme: "http",
- RawAuthority: "user:password@google.com",
- RawUserinfo: "user:password",
- Host: "google.com",
- },
- "http://user:******@google.com",
- },
- {
- "http://user:longerpass@google.com",
- &URL{
- Raw: "http://user:longerpass@google.com",
- Scheme: "http",
- RawAuthority: "user:longerpass@google.com",
- RawUserinfo: "user:longerpass",
- Host: "google.com",
+ Scheme: "http",
+ User: UserPassword("user", "password"),
+ Host: "google.com",
},
- "http://user:******@google.com",
+ "http://user:password@google.com",
},
}
@@ -255,13 +194,10 @@ var urlnofragtests = []URLTest{
{
"http://www.google.com/?q=go+language#foo",
&URL{
- Raw: "http://www.google.com/?q=go+language#foo",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/?q=go+language#foo",
- Path: "/",
- RawQuery: "q=go+language#foo",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ RawQuery: "q=go+language#foo",
},
"",
},
@@ -271,28 +207,22 @@ var urlfragtests = []URLTest{
{
"http://www.google.com/?q=go+language#foo",
&URL{
- Raw: "http://www.google.com/?q=go+language#foo",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/?q=go+language#foo",
- Path: "/",
- RawQuery: "q=go+language",
- Fragment: "foo",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ RawQuery: "q=go+language",
+ Fragment: "foo",
},
"",
},
{
"http://www.google.com/?q=go+language#foo%26bar",
&URL{
- Raw: "http://www.google.com/?q=go+language#foo%26bar",
- Scheme: "http",
- RawAuthority: "www.google.com",
- Host: "www.google.com",
- RawPath: "/?q=go+language#foo%26bar",
- Path: "/",
- RawQuery: "q=go+language",
- Fragment: "foo&bar",
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ RawQuery: "q=go+language",
+ Fragment: "foo&bar",
},
"http://www.google.com/?q=go+language#foo&bar",
},
@@ -300,9 +230,15 @@ var urlfragtests = []URLTest{
// more useful string for debugging than fmt's struct printer
func ufmt(u *URL) string {
- return fmt.Sprintf("raw=%q, scheme=%q, rawpath=%q, auth=%q, userinfo=%q, host=%q, path=%q, rawq=%q, frag=%q",
- u.Raw, u.Scheme, u.RawPath, u.RawAuthority, u.RawUserinfo,
- u.Host, u.Path, u.RawQuery, u.Fragment)
+ var user, pass interface{}
+ if u.User != nil {
+ user = u.User.Username()
+ if p, ok := u.User.Password(); ok {
+ pass = p
+ }
+ }
+ return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawq=%q, frag=%q",
+ u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawQuery, u.Fragment)
}
func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
@@ -370,11 +306,11 @@ func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, t
t.Errorf("%s(%q) returned error %s", name, tt.in, err)
continue
}
- s := u.String()
expected := tt.in
if len(tt.roundtrip) > 0 {
expected = tt.roundtrip
}
+ s := u.String()
if s != expected {
t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
}
@@ -504,33 +440,11 @@ func TestEscape(t *testing.T) {
}
}
-type UserinfoTest struct {
- User string
- Password string
- Raw string
-}
-
-var userinfoTests = []UserinfoTest{
- {"user", "password", "user:password"},
- {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
- "foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
-}
-
-func TestEscapeUserinfo(t *testing.T) {
- for _, tt := range userinfoTests {
- if raw := EscapeUserinfo(tt.User, tt.Password); raw != tt.Raw {
- t.Errorf("EscapeUserinfo(%q, %q) = %q, want %q", tt.User, tt.Password, raw, tt.Raw)
- }
- }
-}
-
-func TestUnescapeUserinfo(t *testing.T) {
- for _, tt := range userinfoTests {
- if user, pass, err := UnescapeUserinfo(tt.Raw); user != tt.User || pass != tt.Password || err != nil {
- t.Errorf("UnescapeUserinfo(%q) = %q, %q, %v, want %q, %q, nil", tt.Raw, user, pass, err, tt.User, tt.Password)
- }
- }
-}
+//var userinfoTests = []UserinfoTest{
+// {"user", "password", "user:password"},
+// {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
+// "foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
+//}
type EncodeQueryTest struct {
m Values
@@ -664,6 +578,57 @@ func TestResolveReference(t *testing.T) {
t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
}
+ // Ensure Opaque resets the URL.
+ base = mustParse("scheme://user@foo.com/bar")
+ abs = base.ResolveReference(&URL{Opaque: "opaque"})
+ want := mustParse("scheme:opaque")
+ if *abs != *want {
+ t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", abs, want)
+ }
+}
+
+func TestResolveReferenceOpaque(t *testing.T) {
+ mustParse := func(url string) *URL {
+ u, err := ParseWithReference(url)
+ if err != nil {
+ t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+ }
+ return u
+ }
+ for _, test := range resolveReferenceTests {
+ base := mustParse(test.base)
+ rel := mustParse(test.rel)
+ url := base.ResolveReference(rel)
+ urlStr := url.String()
+ if urlStr != test.expected {
+ t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+ }
+ }
+
+ // Test that new instances are returned.
+ base := mustParse("http://foo.com/")
+ abs := base.ResolveReference(mustParse("."))
+ if base == abs {
+ t.Errorf("Expected no-op reference to return new URL instance.")
+ }
+ barRef := mustParse("http://bar.com/")
+ abs = base.ResolveReference(barRef)
+ if abs == barRef {
+ t.Errorf("Expected resolution of absolute reference to return new URL instance.")
+ }
+
+ // Test the convenience wrapper too
+ base = mustParse("http://foo.com/path/one/")
+ abs, _ = base.Parse("../two")
+ expected := "http://foo.com/path/two"
+ if abs.String() != expected {
+ t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
+ }
+ _, err := base.Parse("")
+ if err == nil {
+ t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
+ }
+
}
func TestQueryValues(t *testing.T) {
@@ -747,3 +712,60 @@ func TestParseQuery(t *testing.T) {
}
}
}
+
+type RequestURITest struct {
+ url *URL
+ out string
+}
+
+var requritests = []RequestURITest{
+ {
+ &URL{
+ Scheme: "http",
+ Host: "example.com",
+ Path: "",
+ },
+ "/",
+ },
+ {
+ &URL{
+ Scheme: "http",
+ Host: "example.com",
+ Path: "/a b",
+ },
+ "/a%20b",
+ },
+ {
+ &URL{
+ Scheme: "http",
+ Host: "example.com",
+ Path: "/a b",
+ RawQuery: "q=go+language",
+ },
+ "/a%20b?q=go+language",
+ },
+ {
+ &URL{
+ Scheme: "myschema",
+ Opaque: "opaque",
+ },
+ "opaque",
+ },
+ {
+ &URL{
+ Scheme: "myschema",
+ Opaque: "opaque",
+ RawQuery: "q=go+language",
+ },
+ "opaque?q=go+language",
+ },
+}
+
+func TestRequestURI(t *testing.T) {
+ for _, tt := range requritests {
+ s := tt.url.RequestURI()
+ if s != tt.out {
+ t.Errorf("%#v.RequestURI() == %q (expected %q)", tt.url, s, tt.out)
+ }
+ }
+}