Browse Source

http.go: Request.SetURI() (Fix #1141) (#1148)

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.
Sergey Ponomarev 2 months ago
parent
commit
8febad0797
2 changed files with 39 additions and 0 deletions
  1. 14 0
      http.go
  2. 25 0
      http_test.go

+ 14 - 0
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

+ 25 - 0
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()