diff --git a/client.go b/client.go index f4bbe58..4b4aa40 100644 --- a/client.go +++ b/client.go @@ -160,7 +160,7 @@ func (c *Client) DoTimeout(req *Request, resp *Response, timeout time.Duration) // to the requested host are busy. func (c *Client) Do(req *Request, resp *Response) error { uri := req.URI() - host := uri.Host + host := uri.Host() isTLS := false if bytes.Equal(uri.Scheme, strHTTPS) { diff --git a/http.go b/http.go index c11119f..8a0e6be 100644 --- a/http.go +++ b/http.go @@ -187,7 +187,7 @@ func (req *Request) parseURI() { } req.parsedURI = true - req.uri.Parse(req.Header.Host(), req.Header.RequestURI()) + req.uri.parseQuick(req.Header.RequestURI(), &req.Header) } // PostArgs returns POST arguments. @@ -290,7 +290,7 @@ func isSkipResponseBody(statusCode int) bool { func (req *Request) Write(w *bufio.Writer) error { if len(req.Header.Host()) == 0 { uri := req.URI() - req.Header.SetHostBytes(uri.Host) + req.Header.SetHostBytes(uri.Host()) req.Header.SetRequestURIBytes(uri.RequestURI()) } req.Header.SetContentLength(len(req.body)) diff --git a/http_test.go b/http_test.go index d010d69..bd2f9a2 100644 --- a/http_test.go +++ b/http_test.go @@ -491,8 +491,8 @@ func TestRequestURI(t *testing.T) { req.Header.SetRequestURI(requestURI) uri := req.URI() - if string(uri.Host) != host { - t.Fatalf("Unexpected host %q. Expected %q", uri.Host, host) + if string(uri.Host()) != host { + t.Fatalf("Unexpected host %q. Expected %q", uri.Host(), host) } if string(uri.PathOriginal) != expectedPathOriginal { t.Fatalf("Unexpected source path %q. Expected %q", uri.PathOriginal, expectedPathOriginal) diff --git a/server.go b/server.go index 015e73d..284c7f0 100644 --- a/server.go +++ b/server.go @@ -345,7 +345,7 @@ func (ctx *RequestCtx) Path() []byte { // // The host is valid until returning from RequestHandler. func (ctx *RequestCtx) Host() []byte { - return ctx.URI().Host + return ctx.URI().Host() } // QueryArgs returns query arguments from RequestURI. diff --git a/uri.go b/uri.go index 5313bca..e220a07 100644 --- a/uri.go +++ b/uri.go @@ -16,11 +16,6 @@ type URI struct { // Scheme is always lowercased. Scheme []byte - // Host part, i.e. aaa.com of http://aaa.com/foo/bar?baz=123#qwe . - // - // Host is always lowercased. - Host []byte - // Path part, i.e. /foo/bar of http://aaa.com/foo/bar?baz=123#qwe . // // Path is always urldecoded and normalized, @@ -33,39 +28,66 @@ type URI struct { // Hash part, i.e. qwe of http://aaa.com/foo/bar?baz=123#qwe . Hash []byte + host []byte + queryArgs Args parsedQueryArgs bool fullURI []byte requestURI []byte + + h *RequestHeader } // Reset clears uri. func (x *URI) Reset() { x.PathOriginal = x.PathOriginal[:0] x.Scheme = x.Scheme[:0] - x.Host = x.Host[:0] x.Path = x.Path[:0] x.QueryString = x.QueryString[:0] x.Hash = x.Hash[:0] + + x.host = x.host[:0] x.queryArgs.Reset() x.parsedQueryArgs = false x.fullURI = x.fullURI[:0] x.requestURI = x.requestURI[:0] + x.h = nil +} + +// Host returns host part, i.e. aaa.com of http://aaa.com/foo/bar?baz=123#qwe . +// +// Host is always lowercased. +func (x *URI) Host() []byte { + if len(x.host) == 0 && x.h != nil { + x.host = append(x.host[:0], x.h.Host()...) + lowercaseBytes(x.host) + x.h = nil + } + return x.host } // Parse initializes URI from the given host and uri. // // It is safe modifying host and uri buffers after the Parse call. func (x *URI) Parse(host, uri []byte) { + x.parse(host, uri, nil) +} + +func (x *URI) parseQuick(uri []byte, h *RequestHeader) { + x.parse(nil, uri, h) +} + +func (x *URI) parse(host, uri []byte, h *RequestHeader) { x.Reset() + x.h = h scheme, host, uri := splitHostUri(host, uri) x.Scheme = append(x.Scheme, scheme...) lowercaseBytes(x.Scheme) - x.Host = append(x.Host, host...) - lowercaseBytes(x.Host) + x.host = append(x.host, host...) + lowercaseBytes(x.host) b := uri n := bytes.IndexByte(b, '?') @@ -172,7 +194,7 @@ func (x *URI) FullURI() []byte { } dst := append(x.fullURI[:0], scheme...) dst = append(dst, strColonSlashSlash...) - dst = append(dst, x.Host...) + dst = append(dst, x.Host()...) lowercaseBytes(dst) x.fullURI = append(dst, x.RequestURI()...) return x.fullURI diff --git a/uri_test.go b/uri_test.go index bb2527a..ff9c6b1 100644 --- a/uri_test.go +++ b/uri_test.go @@ -88,7 +88,7 @@ func testURIFullURI(t *testing.T, scheme, host, path, hash string, args *Args, e var u URI u.Scheme = []byte(scheme) - u.Host = []byte(host) + u.host = []byte(host) u.Path = []byte(path) u.Hash = []byte(hash) args.CopyTo(u.QueryArgs()) @@ -164,8 +164,8 @@ func testURIParse(t *testing.T, u *URI, host, uri, if !bytes.Equal(u.FullURI(), []byte(expectedURI)) { t.Fatalf("Unexpected uri %q. Expected %q. host=%q, uri=%q", u.FullURI(), expectedURI, host, uri) } - if !bytes.Equal(u.Host, []byte(expectedHost)) { - t.Fatalf("Unexpected host %q. Expected %q. host=%q, uri=%q", u.Host, expectedHost, host, uri) + if !bytes.Equal(u.Host(), []byte(expectedHost)) { + t.Fatalf("Unexpected host %q. Expected %q. host=%q, uri=%q", u.Host(), expectedHost, host, uri) } if !bytes.Equal(u.PathOriginal, []byte(expectedPathOriginal)) { t.Fatalf("Unexpected original path %q. Expected %q. host=%q, uri=%q", u.PathOriginal, expectedPathOriginal, host, uri)