From 5da26217c3d6bea442f9f858c96dee600c722013 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 8 Nov 2021 01:19:21 +0200 Subject: [PATCH] http.go: Request.SetURI() (Fix #1141) Currently, the only way to set URI for a request is to call SetRequestURI(string). Then when a request performed the string will be parsed into a fasthttp.URI struct. If there are many requests with the same URI then we'll waste CPU for a parsing of the same URI string. With the new SetURI(*URI) method we can once parse a URI string into a fasthttp.URI struct and then reuse it for many requests. Unfortunately the URI will be copied because may be modified inside the request. But anyway this will be more lightweight than parsing. --- http.go | 14 ++++++++++++++ http_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/http.go b/http.go index 8021a2528d..c8c2eb439e 100644 --- a/http.go +++ b/http.go @@ -774,6 +774,20 @@ func (req *Request) URI() *URI { return &req.uri } +// SetURI initializes request URI +// Use this method if a single URI may be reused across multiple requests. +// Otherwise, you can just use SetRequestURI() and it will be parsed as new URI. +// The URI is copied and can be safely modified later. +func (req *Request) SetURI(newUri *URI) { + if newUri != nil { + newUri.CopyTo(&req.uri) + req.parsedURI = true + return + } + req.uri.Reset() + req.parsedURI = false +} + func (req *Request) parseURI() error { if req.parsedURI { return nil diff --git a/http_test.go b/http_test.go index 8d57bb050a..24493fcd77 100644 --- a/http_test.go +++ b/http_test.go @@ -515,6 +515,31 @@ tailfoobar` } } +func TestRequestSetURI(t *testing.T) { + t.Parallel() + + var r Request + + uri := "/foo/bar?baz" + u := &URI{} + u.Parse(nil, []byte(uri)) //nolint:errcheck + // Set request uri via SetURI() + r.SetURI(u) // copies URI + // modifying an original URI struct doesn't affect stored URI inside of request + u.SetPath("newPath") + if string(r.RequestURI()) != uri { + t.Fatalf("unexpected request uri %q. Expecting %q", r.RequestURI(), uri) + } + + // Set request uri to nil just resets the URI + r.Reset() + uri = "/" + r.SetURI(nil) + if string(r.RequestURI()) != uri { + t.Fatalf("unexpected request uri %q. Expecting %q", r.RequestURI(), uri) + } +} + func TestRequestRequestURI(t *testing.T) { t.Parallel()