Skip to content
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

✨ (v3) feature: Implement new generic functions: Params, Get and Convert #2850

Merged
merged 53 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
bcfe218
feature: implement generic params function
dozheiny Feb 11, 2024
986886a
Merge remote-tracking branch 'origin' into v3-params
dozheiny Feb 11, 2024
dfd0ecf
update: add ctx generic params benchmark function
dozheiny Feb 11, 2024
b6c30c9
fix: fix linter errors on boolean types
dozheiny Feb 11, 2024
17e2ec9
fix: fix linter errors on float variable types
dozheiny Feb 11, 2024
1ab9948
tests: add Test_Params_TypeAssertFail
dozheiny Feb 11, 2024
e7bc327
Merge branch 'main' into v3-params
sixcolors Feb 11, 2024
35a9469
Update ctx_test.go
gaby Feb 11, 2024
9e1c312
Merge branch 'main' into v3-params
gaby Feb 11, 2024
99c9e7c
typo: change genericType typo to GenericType in documents
dozheiny Feb 12, 2024
c30dd4f
Merge branch 'v3-params' of github.com:dozheiny/fiber into v3-params
dozheiny Feb 12, 2024
03b2eaa
Merge branch 'main' into v3-params
gaby Feb 13, 2024
ccd96fe
Merge branch 'main' into v3-params
dozheiny Feb 13, 2024
4a13c90
remove ParamsInt method and rewrite Params method
dozheiny Feb 15, 2024
71d4a85
add genericParseType tests and benchmarks and simplify genericQuery a…
dozheiny Feb 15, 2024
991a2bf
Merge branch 'main' into v3-params
ReneWerner87 Feb 19, 2024
4502c2d
added GetReqHeader generic function
dozheiny Feb 21, 2024
5da9a62
added tests for params generic function
dozheiny Feb 21, 2024
e682a5e
add tests for GetReqHeader generic function
dozheiny Feb 21, 2024
659fdab
Merge branch 'v3-params' of github.com:dozheiny/fiber into v3-params
dozheiny Feb 21, 2024
a63cebb
added GetReqHeader generic function
dozheiny Feb 21, 2024
c6fbd5e
Revert "added GetReqHeader generic function"
dozheiny Feb 21, 2024
84d53bf
resolve conflicts
dozheiny Feb 21, 2024
f3bc901
fix tests and benchamarks of generic tests
dozheiny Feb 23, 2024
dca0feb
Merge branch 'main' into v3-params
dozheiny Feb 23, 2024
d361736
added default value to array test genericParse
dozheiny Feb 23, 2024
7db0375
Merge branch 'v3-params' of github.com:dozheiny/fiber into v3-params
dozheiny Feb 23, 2024
2c30f74
fix Params generic function on default value and fixes some tests and…
dozheiny Feb 23, 2024
6825691
remove Test_Params_TypeAssertFail function(it didn't panic anyway)
dozheiny Feb 23, 2024
464663a
fix bad usage on parallel tests
dozheiny Feb 23, 2024
1ec2aa3
add convert function
dozheiny Feb 23, 2024
6e2cf41
fix generic tests
dozheiny Feb 23, 2024
4f0b56b
fix fail tests on use parallel multiple time
dozheiny Feb 23, 2024
232536a
fix typo on params comment section
dozheiny Feb 28, 2024
701c8c2
remove pointer refer on Convert
dozheiny Feb 28, 2024
8b84bea
update generic benchmarks
dozheiny Mar 2, 2024
178bcec
Merge branch 'master' of github.com:dozheiny/fiber into v3-params
dozheiny Mar 2, 2024
60d1cb8
reslove conflicts1
dozheiny Mar 2, 2024
50dbccc
add specific tests to integer and unsigned integer
dozheiny Mar 2, 2024
a80cd6b
fix typo on Convert document
dozheiny Mar 2, 2024
958ad2f
change uint tests of Test_genericParseTypeInts
dozheiny Mar 2, 2024
f19afb4
move generic types to utils.go file and change
dozheiny Mar 2, 2024
b02cae9
update genericParseInt unit tests
dozheiny Mar 2, 2024
0ba4911
update generic uint tests and pass value type in
dozheiny Mar 2, 2024
b70c6b9
Merge branch 'main' into v3-params
dozheiny Mar 5, 2024
874a80c
Merge branch 'main' into v3-params
dozheiny Mar 8, 2024
07b2e76
reverse dependency of Params and genericParams
dozheiny Mar 8, 2024
29005a3
Merge branch 'main' into v3-params
dozheiny Mar 9, 2024
bd22d95
Merge branch 'main' into v3-params
dozheiny Mar 12, 2024
1403ded
Merge branch 'main' into v3-params
ReneWerner87 Mar 13, 2024
2f44dc1
Merge branch 'main' into v3-params
dozheiny Mar 17, 2024
0230b4e
update convert docs
dozheiny Mar 17, 2024
57d29b7
Merge branch 'main' into v3-params
dozheiny Mar 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 40 additions & 81 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,14 @@
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting instead.
func (c *DefaultCtx) Get(key string, defaultValue ...string) string {
return defaultString(c.app.getString(c.fasthttp.Request.Header.Peek(key)), defaultValue)
return GetReqHeader(c, key, defaultValue...)
}

// GetReqHeader returns the HTTP request header specified by filed.
// This function is generic and can handle differnet headers type values.
func GetReqHeader[V GenericType](c Ctx, key string, defaultValue ...V) V {
var v V
return genericParseType[V](c.App().getString(c.Request().Header.Peek(key)), v, defaultValue...)
ReneWerner87 marked this conversation as resolved.
Show resolved Hide resolved
}

// GetRespHeader returns the HTTP response header specified by field.
ReneWerner87 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -973,22 +980,22 @@
return defaultString("", defaultValue)
}

// ParamsInt is used to get an integer from the route parameters
// it defaults to zero if the parameter is not found or if the
// parameter cannot be converted to an integer
// If a default value is given, it will return that value in case the param
// doesn't exist or cannot be converted to an integer
func (c *DefaultCtx) ParamsInt(key string, defaultValue ...int) (int, error) {
// Use Atoi to convert the param to an int or return zero and an error
value, err := strconv.Atoi(c.Params(key))
if err != nil {
if len(defaultValue) > 0 {
return defaultValue[0], nil
}
return 0, fmt.Errorf("failed to convert: %w", err)
}

return value, nil
// Params is used to get the route parameters.
// This function is generic and can handle differnet route parameters type values.
//
// Example:
//
// http://example.com/user/:user -> http://example.com/user/john
// Params[string](c, "user") -> returns john
//
// http://example.com/id/:id -> http://example.com/user/114
// Params[int](c, "id") -> returns 114 as integer.
//
// http://example.com/id/:number -> http://example.com/id/john
// Params[int](c, "number", 0) -> returns 0 because can't parse 'john' as integer.
func Params[V GenericType](c Ctx, key string, defaultValue ...V) V {
var v V
return genericParseType(c.Params(key), v, defaultValue...)
}

// Path returns the path part of the request URL.
Expand Down Expand Up @@ -1108,73 +1115,11 @@
// name := Query[string](c, "search") // Returns "john"
// age := Query[int](c, "age") // Returns 8
// unknown := Query[string](c, "unknown", "default") // Returns "default" since the query parameter "unknown" is not found
func Query[V QueryType](c Ctx, key string, defaultValue ...V) V {
func Query[V GenericType](c Ctx, key string, defaultValue ...V) V {
var v V
q := c.App().getString(c.Context().QueryArgs().Peek(key))

switch any(v).(type) {
case int:
return queryParseInt[V](q, 32, func(i int64) V { return assertValueType[V, int](int(i)) }, defaultValue...)
case int8:
return queryParseInt[V](q, 8, func(i int64) V { return assertValueType[V, int8](int8(i)) }, defaultValue...)
case int16:
return queryParseInt[V](q, 16, func(i int64) V { return assertValueType[V, int16](int16(i)) }, defaultValue...)
case int32:
return queryParseInt[V](q, 32, func(i int64) V { return assertValueType[V, int32](int32(i)) }, defaultValue...)
case int64:
return queryParseInt[V](q, 64, func(i int64) V { return assertValueType[V, int64](i) }, defaultValue...)
case uint:
return queryParseUint[V](q, 32, func(i uint64) V { return assertValueType[V, uint](uint(i)) }, defaultValue...)
case uint8:
return queryParseUint[V](q, 8, func(i uint64) V { return assertValueType[V, uint8](uint8(i)) }, defaultValue...)
case uint16:
return queryParseUint[V](q, 16, func(i uint64) V { return assertValueType[V, uint16](uint16(i)) }, defaultValue...)
case uint32:
return queryParseUint[V](q, 32, func(i uint64) V { return assertValueType[V, uint32](uint32(i)) }, defaultValue...)
case uint64:
return queryParseUint[V](q, 64, func(i uint64) V { return assertValueType[V, uint64](i) }, defaultValue...)
case float32:
return queryParseFloat[V](q, 32, func(i float64) V { return assertValueType[V, float32](float32(i)) }, defaultValue...)
case float64:
return queryParseFloat[V](q, 64, func(i float64) V { return assertValueType[V, float64](i) }, defaultValue...)
case bool:
return queryParseBool[V](q, func(b bool) V { return assertValueType[V, bool](b) }, defaultValue...)
case string:
if q == "" && len(defaultValue) > 0 {
return defaultValue[0]
}
return assertValueType[V, string](q)
case []byte:
if q == "" && len(defaultValue) > 0 {
return defaultValue[0]
}
return assertValueType[V, []byte](c.App().getBytes(q))
default:
if len(defaultValue) > 0 {
return defaultValue[0]
}
return v
}
}

type QueryType interface {
QueryTypeInteger | QueryTypeFloat | bool | string | []byte
}

type QueryTypeInteger interface {
QueryTypeIntegerSigned | QueryTypeIntegerUnsigned
}

type QueryTypeIntegerSigned interface {
int | int8 | int16 | int32 | int64
}

type QueryTypeIntegerUnsigned interface {
uint | uint8 | uint16 | uint32 | uint64
}

type QueryTypeFloat interface {
float32 | float64
return genericParseType[V](q, v, defaultValue...)
ReneWerner87 marked this conversation as resolved.
Show resolved Hide resolved
}

// Range returns a struct containing the type and a slice of ranges.
Expand Down Expand Up @@ -1761,3 +1706,17 @@
}
return c.bind
}

// Converts a string value to a specified type, handling errors and optional default values.
func Convert[T any](value string, convertor func(string) (T, error), defaultValue ...T) (T, error) {
converted, err := convertor(value)
if err != nil {
if len(defaultValue) > 0 {
return defaultValue[0], nil

Check warning on line 1715 in ctx.go

View check run for this annotation

Codecov / codecov/patch

ctx.go#L1711-L1715

Added lines #L1711 - L1715 were not covered by tests
}

return converted, fmt.Errorf("failed to convert: %w", err)

Check warning on line 1718 in ctx.go

View check run for this annotation

Codecov / codecov/patch

ctx.go#L1718

Added line #L1718 was not covered by tests
}

return converted, nil

Check warning on line 1721 in ctx.go

View check run for this annotation

Codecov / codecov/patch

ctx.go#L1721

Added line #L1721 was not covered by tests
}
ReneWerner87 marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 0 additions & 7 deletions ctx_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,6 @@ type Ctx interface {
// Make copies or use the Immutable setting to use the value outside the Handler.
Params(key string, defaultValue ...string) string

// ParamsInt is used to get an integer from the route parameters
// it defaults to zero if the parameter is not found or if the
// parameter cannot be converted to an integer
// If a default value is given, it will return that value in case the param
// doesn't exist or cannot be converted to an integer
ParamsInt(key string, defaultValue ...int) (int, error)

// Path returns the path part of the request URL.
// Optionally, you could override the path.
Path(override ...string) string
Comment on lines 224 to 229
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

The removal of the ParamsInt method from the Ctx interface aligns with the PR's objective to introduce more generic functions for handling data types. This change simplifies the interface and encourages the use of the new generic functions. Ensure that the documentation and examples are updated to reflect this change and guide users on how to use the new generic functions for parsing integer parameters.

Expand Down
Loading
Loading