-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🔥 feat: Add support for iterator methods to Fiber client #3228
Merged
Merged
Changes from 12 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
0949f42
chore: simplify parserRequestBodyFile logic
efectn 7578ae3
client: add support for go1.23 iterators
efectn 26a3439
Apply suggestions from code review
gaby b57b7c2
fix linter
efectn b4c7c54
fix tests
efectn 86e93b1
correct benchmark
efectn 3e1d427
Merge branch 'main' into client-iterators-2
efectn 7488d53
fix linter
efectn 0343f06
create docs
efectn bb43f28
update
efectn cd9b6c9
rename FormDatas -> AllFormData
efectn 0b71163
add examples for maps.Collect()
efectn 65c0448
Merge branch 'main' into client-iterators-2
gaby fa4c54a
change request/response markdown examples
ReneWerner87 40361f9
Merge branch 'main' into client-iterators-2
ReneWerner87 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,10 @@ | |
"context" | ||
"errors" | ||
"io" | ||
"iter" | ||
"path/filepath" | ||
"reflect" | ||
"slices" | ||
"strconv" | ||
"sync" | ||
"time" | ||
|
@@ -129,6 +131,31 @@ | |
return r.header.PeekMultiple(key) | ||
} | ||
|
||
// Headers returns all headers in the request using an iterator. | ||
// You can use maps.Collect() to collect all headers into a map. | ||
// | ||
// The returned value is valid until the request object is released. | ||
// Any future calls to Headers method will return the modified value. Do not store references to returned value. Make copies instead. | ||
func (r *Request) Headers() iter.Seq2[string, []string] { | ||
return func(yield func(string, []string) bool) { | ||
peekKeys := r.header.PeekKeys() | ||
keys := make([][]byte, len(peekKeys)) | ||
copy(keys, peekKeys) // It is necessary to have immutable byte slice. | ||
|
||
for _, key := range keys { | ||
vals := r.header.PeekAll(utils.UnsafeString(key)) | ||
valsStr := make([]string, len(vals)) | ||
for i, v := range vals { | ||
valsStr[i] = utils.UnsafeString(v) | ||
} | ||
|
||
if !yield(utils.UnsafeString(key), valsStr) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// AddHeader method adds a single header field and its value in the request instance. | ||
func (r *Request) AddHeader(key, val string) *Request { | ||
r.header.Add(key, val) | ||
|
@@ -168,6 +195,33 @@ | |
return res | ||
} | ||
|
||
// Params returns all params in the request using an iterator. | ||
// You can use maps.Collect() to collect all params into a map. | ||
// | ||
// The returned value is valid until the request object is released. | ||
// Any future calls to Params method will return the modified value. Do not store references to returned value. Make copies instead. | ||
func (r *Request) Params() iter.Seq2[string, []string] { | ||
return func(yield func(string, []string) bool) { | ||
keys := r.params.Keys() | ||
|
||
for _, key := range keys { | ||
if key == "" { | ||
continue | ||
} | ||
|
||
vals := r.params.PeekMulti(key) | ||
valsStr := make([]string, len(vals)) | ||
for i, v := range vals { | ||
valsStr[i] = utils.UnsafeString(v) | ||
} | ||
|
||
if !yield(key, valsStr) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// AddParam method adds a single param field and its value in the request instance. | ||
func (r *Request) AddParam(key, val string) *Request { | ||
r.params.Add(key, val) | ||
|
@@ -254,6 +308,18 @@ | |
return "" | ||
} | ||
|
||
// Cookies returns all cookies in the cookies using an iterator. | ||
// You can use maps.Collect() to collect all cookies into a map. | ||
func (r *Request) Cookies() iter.Seq2[string, string] { | ||
return func(yield func(string, string) bool) { | ||
r.cookies.VisitAll(func(key, val string) { | ||
if !yield(key, val) { | ||
return | ||
} | ||
}) | ||
} | ||
} | ||
|
||
// SetCookie method sets a single cookie field and its value in the request instance. | ||
// It will override cookie which set in client instance. | ||
func (r *Request) SetCookie(key, val string) *Request { | ||
|
@@ -291,6 +357,18 @@ | |
return "" | ||
} | ||
|
||
// PathParams returns all path params in request instance. | ||
// You can use maps.Collect() to collect all cookies into a map. | ||
func (r *Request) PathParams() iter.Seq2[string, string] { | ||
return func(yield func(string, string) bool) { | ||
r.path.VisitAll(func(key, val string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thanks for the report. Will fix it |
||
if !yield(key, val) { | ||
return | ||
} | ||
}) | ||
} | ||
} | ||
|
||
// SetPathParam method sets a single path param field and its value in the request instance. | ||
// It will override path param which set in client instance. | ||
func (r *Request) SetPathParam(key, val string) *Request { | ||
|
@@ -376,6 +454,33 @@ | |
return res | ||
} | ||
|
||
// AllFormData method returns all form datas in request instance. | ||
// You can use maps.Collect() to collect all cookies into a map. | ||
// | ||
// The returned value is valid until the request object is released. | ||
// Any future calls to FormDatas method will return the modified value. Do not store references to returned value. Make copies instead. | ||
func (r *Request) AllFormData() iter.Seq2[string, []string] { | ||
return func(yield func(string, []string) bool) { | ||
keys := r.formData.Keys() | ||
|
||
for _, key := range keys { | ||
if key == "" { | ||
continue | ||
} | ||
|
||
vals := r.formData.PeekMulti(key) | ||
valsStr := make([]string, len(vals)) | ||
for i, v := range vals { | ||
valsStr[i] = utils.UnsafeString(v) | ||
} | ||
|
||
if !yield(key, valsStr) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// AddFormData method adds a single form data field and its value in the request instance. | ||
func (r *Request) AddFormData(key, val string) *Request { | ||
r.formData.AddData(key, val) | ||
|
@@ -435,6 +540,14 @@ | |
return nil | ||
} | ||
|
||
// Files method returns all files in request instance. | ||
// | ||
// The returned value is valid until the request object is released. | ||
// Any future calls to Files method will return the modified value. Do not store references to returned value. Make copies instead. | ||
func (r *Request) Files() []*File { | ||
return r.files | ||
} | ||
|
||
// FileByPath returns file ptr store in request obj by path. | ||
func (r *Request) FileByPath(path string) *File { | ||
for _, v := range r.files { | ||
|
@@ -617,6 +730,16 @@ | |
*fasthttp.Args | ||
} | ||
|
||
// Keys method returns all keys in the query params. | ||
func (p *QueryParam) Keys() []string { | ||
keys := make([]string, 0, p.Len()) | ||
p.VisitAll(func(key, _ []byte) { | ||
keys = append(keys, utils.UnsafeString(key)) | ||
}) | ||
|
||
return slices.Compact(keys) | ||
} | ||
|
||
// AddParams receive a map and add each value to param. | ||
func (p *QueryParam) AddParams(r map[string][]string) { | ||
for k, v := range r { | ||
|
@@ -747,6 +870,16 @@ | |
*fasthttp.Args | ||
} | ||
|
||
// Keys method returns all keys in the form data. | ||
func (f *FormData) Keys() []string { | ||
keys := make([]string, 0, f.Len()) | ||
f.VisitAll(func(key, _ []byte) { | ||
keys = append(keys, utils.UnsafeString(key)) | ||
}) | ||
|
||
return slices.Compact(keys) | ||
} | ||
|
||
// AddData method is a wrapper of Args's Add method. | ||
func (f *FormData) AddData(key, val string) { | ||
f.Add(key, val) | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VisitAll
in its current form does not support early returns. If the caller of the iterator stops iterating early (e.g. bybreak
infor range
),yield
would be called again after it returnedfalse
, and this causes a runtime panic.Please update
VisitAll
to support early returns, and add a test to verify that stopping the iterator early works.