Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func bindData(destination any, data map[string][]string, tag string, dataFiles m
isElemInterface := k == reflect.Interface
isElemString := k == reflect.String
isElemSliceOfStrings := k == reflect.Slice && typ.Elem().Elem().Kind() == reflect.String
if !(isElemSliceOfStrings || isElemString || isElemInterface) {
if !isElemSliceOfStrings && !isElemString && !isElemInterface {
return nil
}
if val.IsNil() {
Expand Down
70 changes: 39 additions & 31 deletions binder_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ const (
// It returns the typed value and an error if binding fails. Returns ErrNonExistentKey if parameter not found.
//
// Empty String Handling:
// If the parameter exists but has an empty value, the zero value of type T is returned
// with no error. For example, a path parameter with value "" returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// If the parameter exists but has an empty value, the zero value of type T is returned
// with no error. For example, a path parameter with value "" returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// See ParseValue for supported types and options
func PathParam[T any](c *Context, paramName string, opts ...any) (T, error) {
Expand All @@ -74,10 +75,11 @@ func PathParam[T any](c *Context, paramName string, opts ...any) (T, error) {
// Returns an error only if parsing fails (e.g., "abc" for int type).
//
// Example:
// id, err := echo.PathParamOr[int](c, "id", 0)
// // If "id" is missing: returns (0, nil)
// // If "id" is "123": returns (123, nil)
// // If "id" is "abc": returns (0, BindingError)
//
// id, err := echo.PathParamOr[int](c, "id", 0)
// // If "id" is missing: returns (0, nil)
// // If "id" is "123": returns (123, nil)
// // If "id" is "abc": returns (0, BindingError)
//
// See ParseValue for supported types and options
func PathParamOr[T any](c *Context, paramName string, defaultValue T, opts ...any) (T, error) {
Expand All @@ -97,10 +99,11 @@ func PathParamOr[T any](c *Context, paramName string, defaultValue T, opts ...an
// It returns the typed value and an error if binding fails. Returns ErrNonExistentKey if parameter not found.
//
// Empty String Handling:
// If the parameter exists but has an empty value (?key=), the zero value of type T is returned
// with no error. For example, "?count=" returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// If the parameter exists but has an empty value (?key=), the zero value of type T is returned
// with no error. For example, "?count=" returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// Behavior Summary:
// - Missing key (?other=value): returns (zero, ErrNonExistentKey)
Expand Down Expand Up @@ -131,10 +134,11 @@ func QueryParam[T any](c *Context, key string, opts ...any) (T, error) {
// Returns an error only if parsing fails (e.g., "abc" for int type).
//
// Example:
// page, err := echo.QueryParamOr[int](c, "page", 1)
// // If "page" is missing: returns (1, nil)
// // If "page" is "5": returns (5, nil)
// // If "page" is "abc": returns (1, BindingError)
//
// page, err := echo.QueryParamOr[int](c, "page", 1)
// // If "page" is missing: returns (1, nil)
// // If "page" is "5": returns (5, nil)
// // If "page" is "abc": returns (1, BindingError)
//
// See ParseValue for supported types and options
func QueryParamOr[T any](c *Context, key string, defaultValue T, opts ...any) (T, error) {
Expand Down Expand Up @@ -175,10 +179,11 @@ func QueryParams[T any](c *Context, key string, opts ...any) ([]T, error) {
// Returns an error only if parsing any value fails.
//
// Example:
// ids, err := echo.QueryParamsOr[int](c, "ids", []int{})
// // If "ids" is missing: returns ([], nil)
// // If "ids" is "1&ids=2": returns ([1, 2], nil)
// // If "ids" contains "abc": returns ([], BindingError)
//
// ids, err := echo.QueryParamsOr[int](c, "ids", []int{})
// // If "ids" is missing: returns ([], nil)
// // If "ids" is "1&ids=2": returns ([1, 2], nil)
// // If "ids" contains "abc": returns ([], BindingError)
//
// See ParseValues for supported types and options
func QueryParamsOr[T any](c *Context, key string, defaultValue []T, opts ...any) ([]T, error) {
Expand All @@ -198,10 +203,11 @@ func QueryParamsOr[T any](c *Context, key string, defaultValue []T, opts ...any)
// It returns the typed value and an error if binding fails. Returns ErrNonExistentKey if parameter not found.
//
// Empty String Handling:
// If the form field exists but has an empty value, the zero value of type T is returned
// with no error. For example, an empty form field returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// If the form field exists but has an empty value, the zero value of type T is returned
// with no error. For example, an empty form field returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// See ParseValue for supported types and options
func FormValue[T any](c *Context, key string, opts ...any) (T, error) {
Expand Down Expand Up @@ -232,10 +238,11 @@ func FormValue[T any](c *Context, key string, opts ...any) (T, error) {
// Returns an error only if parsing fails or form parsing errors occur.
//
// Example:
// limit, err := echo.FormValueOr[int](c, "limit", 100)
// // If "limit" is missing: returns (100, nil)
// // If "limit" is "50": returns (50, nil)
// // If "limit" is "abc": returns (100, BindingError)
//
// limit, err := echo.FormValueOr[int](c, "limit", 100)
// // If "limit" is missing: returns (100, nil)
// // If "limit" is "50": returns (50, nil)
// // If "limit" is "abc": returns (100, BindingError)
//
// See ParseValue for supported types and options
func FormValueOr[T any](c *Context, key string, defaultValue T, opts ...any) (T, error) {
Expand Down Expand Up @@ -284,9 +291,10 @@ func FormValues[T any](c *Context, key string, opts ...any) ([]T, error) {
// Returns an error only if parsing any value fails or form parsing errors occur.
//
// Example:
// tags, err := echo.FormValuesOr[string](c, "tags", []string{})
// // If "tags" is missing: returns ([], nil)
// // If form parsing fails: returns (nil, error)
//
// tags, err := echo.FormValuesOr[string](c, "tags", []string{})
// // If "tags" is missing: returns ([], nil)
// // If form parsing fails: returns (nil, error)
//
// See ParseValues for supported types and options
func FormValuesOr[T any](c *Context, key string, defaultValue []T, opts ...any) ([]T, error) {
Expand Down
2 changes: 1 addition & 1 deletion middleware/basic_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (config BasicAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
if i >= limit {
break
}
if !(len(auth) > l+1 && strings.EqualFold(auth[:l], basic)) {
if len(auth) <= l+1 || !strings.EqualFold(auth[:l], basic) {
continue
}
i++
Expand Down
2 changes: 1 addition & 1 deletion middleware/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (config StaticConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
}

var he echo.HTTPStatusCoder
if !(errors.As(err, &he) && config.HTML5 && he.StatusCode() == http.StatusNotFound) {
if !errors.As(err, &he) || !config.HTML5 || he.StatusCode() != http.StatusNotFound {
return err
}
// is case HTML5 mode is enabled + echo 404 we serve index to the client
Expand Down
2 changes: 1 addition & 1 deletion response.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func UnwrapResponse(rw http.ResponseWriter) (*Response, error) {
type delayedStatusWriter struct {
http.ResponseWriter
committed bool
status int
status int
}

func (w *delayedStatusWriter) WriteHeader(statusCode int) {
Expand Down
2 changes: 1 addition & 1 deletion route.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (r RouteInfo) Reverse(pathValues ...any) string {
// in case of `*` wildcard or `:` (unescaped colon) param we replace everything till next slash or end of path
for ; i < l && r.Path[i] != '/'; i++ {
}
uri.WriteString(fmt.Sprintf("%v", pathValues[n]))
fmt.Fprintf(uri, "%v", pathValues[n])
n++
}
if i < l {
Expand Down
2 changes: 1 addition & 1 deletion router.go
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ func (r *DefaultRouter) Route(c *Context) HandlerFunc {
var rInfo *RouteInfo
if matchedRouteMethod != nil {
rHandler = matchedRouteMethod.handler
rPath = matchedRouteMethod.RouteInfo.Path
rPath = matchedRouteMethod.Path
rInfo = matchedRouteMethod.RouteInfo
} else {
// use previous match as basis. although we have no matching handler we have path match.
Expand Down
Loading