Skip to content

Commit

Permalink
Merge branch 'main' into cors-private-network-support
Browse files Browse the repository at this point in the history
  • Loading branch information
gaby authored Mar 19, 2024
2 parents 1562aa0 + 7fa8b2d commit 0ea8c85
Show file tree
Hide file tree
Showing 19 changed files with 1,950 additions and 844 deletions.
14 changes: 4 additions & 10 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,12 @@ linters-settings:

gocritic:
# TODO: Uncomment the following lines
# enabled-tags:
# - diagnostic
enabled-tags:
- diagnostic
# - style
# - performance
# - experimental
# - opinionated
disabled-checks:
- ifElseChain # TODO: Do not disable
# - hugeParam
# - rangeExprCopy
# - rangeValCopy
settings:
captLocal:
paramsOnly: false
Expand Down Expand Up @@ -195,6 +190,8 @@ linters-settings:
disabled: true
- name: unchecked-type-assertion
disabled: true # TODO: Do not disable
- name: unhandled-error
arguments: ['bytes\.Buffer\.Write']

stylecheck:
checks:
Expand All @@ -217,9 +214,6 @@ linters-settings:

testifylint:
enable-all: true
# TODO: Do not disable any options
disable:
- go-require

testpackage:
skip-regexp: "^$"
Expand Down
3 changes: 1 addition & 2 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -988,8 +988,7 @@ func (app *App) Test(req *http.Request, timeout ...time.Duration) (*http.Respons

type disableLogger struct{}

func (*disableLogger) Printf(_ string, _ ...any) {
// fmt.Println(fmt.Sprintf(format, args...))
func (*disableLogger) Printf(string, ...any) {
}

func (app *App) init() *App {
Expand Down
2 changes: 0 additions & 2 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1316,13 +1316,11 @@ func Test_App_Group(t *testing.T) {
resp, err := app.Test(httptest.NewRequest(MethodPost, "/test/v1/", nil))
require.NoError(t, err, "app.Test(req)")
require.Equal(t, 200, resp.StatusCode, "Status code")
// require.Equal(t, "/test/v1", resp.Header.Get("Location"), "Location")

api.Get("/users", dummyHandler)
resp, err = app.Test(httptest.NewRequest(MethodGet, "/test/v1/UsErS", nil))
require.NoError(t, err, "app.Test(req)")
require.Equal(t, 200, resp.StatusCode, "Status code")
// require.Equal(t, "/test/v1/users", resp.Header.Get("Location"), "Location")
}

func Test_App_Route(t *testing.T) {
Expand Down
1 change: 0 additions & 1 deletion bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,6 @@ func Benchmark_Bind_Query_Comma(b *testing.B) {
}
c.Request().SetBody([]byte(``))
c.Request().Header.SetContentType("")
// c.Request().URI().SetQueryString("id=1&name=tom&hobby=basketball&hobby=football")
c.Request().URI().SetQueryString("id=1&name=tom&hobby=basketball,football")
q := new(Query)
b.ReportAllocs()
Expand Down
7 changes: 4 additions & 3 deletions client/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ func Test_Parser_Request_URL(t *testing.T) {

flag1, flag2, flag3 := false, false, false
for _, v := range values["bar"] {
if v == "foo1" {
switch v {
case "foo1":
flag1 = true
} else if v == "foo2" {
case "foo2":
flag2 = true
} else if v == "foo" {
case "foo":
flag3 = true
}
}
Expand Down
121 changes: 40 additions & 81 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,14 @@ func (c *DefaultCtx) Fresh() bool {
// 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...)
}

// GetRespHeader returns the HTTP response header specified by field.
Expand Down Expand Up @@ -973,22 +980,22 @@ func (c *DefaultCtx) Params(key string, defaultValue ...string) string {
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 @@ func (c *DefaultCtx) Queries() map[string]string {
// 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...)
}

// Range returns a struct containing the type and a slice of ranges.
Expand Down Expand Up @@ -1761,3 +1706,17 @@ func (c *DefaultCtx) Bind() *Bind {
}
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
}

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

return converted, nil
}
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
Expand Down
Loading

0 comments on commit 0ea8c85

Please sign in to comment.