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

Proposal: Remove Must and Should when binding structs #3178

Closed
wants to merge 6 commits into from
Closed
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
53 changes: 13 additions & 40 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,7 @@ type StructValidator interface {

// Bind struct
type Bind struct {
ctx Ctx
should bool
}

// Should To handle binder errors manually, you can prefer Should method.
// It's default behavior of binder.
func (b *Bind) Should() *Bind {
b.should = true

return b
}

// Must If you want to handle binder errors automatically, you can use Must.
// If there's an error it'll return error and 400 as HTTP status.
func (b *Bind) Must() *Bind {
b.should = false

return b
}

// Check Should/Must errors and return it by usage.
func (b *Bind) returnErr(err error) error {
if !b.should {
b.ctx.Status(StatusBadRequest)
return NewError(StatusBadRequest, "Bad request: "+err.Error())
}

return err
ctx Ctx
}

// Struct validation.
Expand All @@ -67,7 +40,7 @@ func (b *Bind) Custom(name string, dest any) error {
binders := b.ctx.App().customBinders
for _, customBinder := range binders {
if customBinder.Name() == name {
return b.returnErr(customBinder.Parse(b.ctx, dest))
return customBinder.Parse(b.ctx, dest)
}
}

Expand All @@ -76,7 +49,7 @@ func (b *Bind) Custom(name string, dest any) error {

// Header binds the request header strings into the struct, map[string]string and map[string][]string.
func (b *Bind) Header(out any) error {
if err := b.returnErr(binder.HeaderBinder.Bind(b.ctx.Request(), out)); err != nil {
if err := binder.HeaderBinder.Bind(b.ctx.Request(), out); err != nil {
return err
}

Expand All @@ -85,17 +58,17 @@ func (b *Bind) Header(out any) error {

// RespHeader binds the response header strings into the struct, map[string]string and map[string][]string.
func (b *Bind) RespHeader(out any) error {
if err := b.returnErr(binder.RespHeaderBinder.Bind(b.ctx.Response(), out)); err != nil {
if err := binder.RespHeaderBinder.Bind(b.ctx.Response(), out); err != nil {
return err
}

return b.validateStruct(out)
}

// Cookie binds the requesr cookie strings into the struct, map[string]string and map[string][]string.
// Cookie binds the request cookie strings into the struct, map[string]string and map[string][]string.
// NOTE: If your cookie is like key=val1,val2; they'll be binded as an slice if your map is map[string][]string. Else, it'll use last element of cookie.
func (b *Bind) Cookie(out any) error {
if err := b.returnErr(binder.CookieBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := binder.CookieBinder.Bind(b.ctx.Context(), out); err != nil {
return err
}

Expand All @@ -104,7 +77,7 @@ func (b *Bind) Cookie(out any) error {

// Query binds the query string into the struct, map[string]string and map[string][]string.
func (b *Bind) Query(out any) error {
if err := b.returnErr(binder.QueryBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := binder.QueryBinder.Bind(b.ctx.Context(), out); err != nil {
return err
}

Expand All @@ -113,7 +86,7 @@ func (b *Bind) Query(out any) error {

// JSON binds the body string into the struct.
func (b *Bind) JSON(out any) error {
if err := b.returnErr(binder.JSONBinder.Bind(b.ctx.Body(), b.ctx.App().Config().JSONDecoder, out)); err != nil {
if err := binder.JSONBinder.Bind(b.ctx.Body(), b.ctx.App().Config().JSONDecoder, out); err != nil {
return err
}

Expand All @@ -122,7 +95,7 @@ func (b *Bind) JSON(out any) error {

// XML binds the body string into the struct.
func (b *Bind) XML(out any) error {
if err := b.returnErr(binder.XMLBinder.Bind(b.ctx.Body(), out)); err != nil {
if err := binder.XMLBinder.Bind(b.ctx.Body(), out); err != nil {
return err
}

Expand All @@ -131,7 +104,7 @@ func (b *Bind) XML(out any) error {

// Form binds the form into the struct, map[string]string and map[string][]string.
func (b *Bind) Form(out any) error {
if err := b.returnErr(binder.FormBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := binder.FormBinder.Bind(b.ctx.Context(), out); err != nil {
return err
}

Expand All @@ -140,7 +113,7 @@ func (b *Bind) Form(out any) error {

// URI binds the route parameters into the struct, map[string]string and map[string][]string.
func (b *Bind) URI(out any) error {
if err := b.returnErr(binder.URIBinder.Bind(b.ctx.Route().Params, b.ctx.Params, out)); err != nil {
if err := binder.URIBinder.Bind(b.ctx.Route().Params, b.ctx.Params, out); err != nil {
return err
}

Expand All @@ -149,7 +122,7 @@ func (b *Bind) URI(out any) error {

// MultipartForm binds the multipart form into the struct, map[string]string and map[string][]string.
func (b *Bind) MultipartForm(out any) error {
if err := b.returnErr(binder.FormBinder.BindMultipart(b.ctx.Context(), out)); err != nil {
if err := binder.FormBinder.BindMultipart(b.ctx.Context(), out); err != nil {
return err
}

Expand All @@ -171,7 +144,7 @@ func (b *Bind) Body(out any) error {
for _, customBinder := range binders {
for _, mime := range customBinder.MIMETypes() {
if mime == ctype {
return b.returnErr(customBinder.Parse(b.ctx, out))
return customBinder.Parse(b.ctx, out)
}
}
}
Expand Down
15 changes: 0 additions & 15 deletions bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1616,21 +1616,6 @@ func Test_Bind_CustomBinder(t *testing.T) {
require.Equal(t, "john", d.Name)
}

// go test -run Test_Bind_Must
func Test_Bind_Must(t *testing.T) {
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})

type RequiredQuery struct {
Name string `query:"name,required"`
}
rq := new(RequiredQuery)
c.Request().URI().SetQueryString("")
err := c.Bind().Must().Query(rq)
require.Equal(t, StatusBadRequest, c.Response().StatusCode())
require.Equal(t, "Bad request: bind: name is empty", err.Error())
}

// simple struct validator for testing
type structValidator struct{}

Expand Down
1 change: 0 additions & 1 deletion ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -1859,7 +1859,6 @@ func (c *DefaultCtx) Bind() *Bind {
if c.bind == nil {
c.bind = &Bind{
ctx: c,
should: true,
}
}
return c.bind
Expand Down