Optimize request uri parsing - defer Host header reading

This commit is contained in:
Aliaksandr Valialkin
2015-11-19 15:05:27 +02:00
parent 48c0f89ee7
commit 2b1eca3a70
6 changed files with 40 additions and 18 deletions
+1 -1
View File
@@ -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) {
+2 -2
View File
@@ -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))
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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.
+31 -9
View File
@@ -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
+3 -3
View File
@@ -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)