Skip to content

Commit

Permalink
chore: replace vendored gorilla/schema package
Browse files Browse the repository at this point in the history
  • Loading branch information
efectn committed Oct 11, 2024
1 parent 44cd700 commit fabf880
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 1,383 deletions.
73 changes: 55 additions & 18 deletions bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ func Test_Bind_Query(t *testing.T) {
type Query2 struct {
Name string
Hobby string
Default string `query:"default,default:hello"`
FavouriteDrinks []string
Empty []string
Alloc []string
Defaults []string `query:"defaults,default:hello|world"`
No []int64
ID int
Bool bool
Expand All @@ -76,13 +78,15 @@ func Test_Bind_Query(t *testing.T) {
require.Equal(t, nilSlice, q2.Empty)
require.Equal(t, []string{""}, q2.Alloc)
require.Equal(t, []int64{1}, q2.No)
require.Equal(t, "hello", q2.Default)
require.Equal(t, []string{"hello", "world"}, q2.Defaults)

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

type ArrayQuery struct {
Data []string
Expand Down Expand Up @@ -204,15 +208,15 @@ func Test_Bind_Query_Schema(t *testing.T) {

c.Request().URI().SetQueryString("namex=tom&nested.age=10")
q = new(Query1)
require.Equal(t, "name is empty", c.Bind().Query(q).Error())
require.Equal(t, "bind: name is empty", c.Bind().Query(q).Error())

c.Request().URI().SetQueryString("name=tom&nested.agex=10")
q = new(Query1)
require.NoError(t, c.Bind().Query(q))

c.Request().URI().SetQueryString("name=tom&test.age=10")
q = new(Query1)
require.Equal(t, "nested is empty", c.Bind().Query(q).Error())
require.Equal(t, "bind: nested is empty", c.Bind().Query(q).Error())

type Query2 struct {
Name string `query:"name"`
Expand All @@ -230,11 +234,11 @@ func Test_Bind_Query_Schema(t *testing.T) {

c.Request().URI().SetQueryString("nested.agex=10")
q2 = new(Query2)
require.Equal(t, "nested.age is empty", c.Bind().Query(q2).Error())
require.Equal(t, "bind: nested.age is empty", c.Bind().Query(q2).Error())

c.Request().URI().SetQueryString("nested.agex=10")
q2 = new(Query2)
require.Equal(t, "nested.age is empty", c.Bind().Query(q2).Error())
require.Equal(t, "bind: nested.age is empty", c.Bind().Query(q2).Error())

type Node struct {
Next *Node `query:"next,required"`
Expand All @@ -248,7 +252,7 @@ func Test_Bind_Query_Schema(t *testing.T) {

c.Request().URI().SetQueryString("next.val=2")
n = new(Node)
require.Equal(t, "val is empty", c.Bind().Query(n).Error())
require.Equal(t, "bind: val is empty", c.Bind().Query(n).Error())

c.Request().URI().SetQueryString("val=3&next.value=2")
n = new(Node)
Expand Down Expand Up @@ -354,7 +358,7 @@ func Test_Bind_Header(t *testing.T) {
}
rh := new(RequiredHeader)
c.Request().Header.Del("name")
require.Equal(t, "name is empty", c.Bind().Header(rh).Error())
require.Equal(t, "bind: name is empty", c.Bind().Header(rh).Error())
}

// go test -run Test_Bind_Header_Map -v
Expand Down Expand Up @@ -463,7 +467,7 @@ func Test_Bind_Header_Schema(t *testing.T) {

c.Request().Header.Del("Name")
q = new(Header1)
require.Equal(t, "Name is empty", c.Bind().Header(q).Error())
require.Equal(t, "bind: Name is empty", c.Bind().Header(q).Error())

c.Request().Header.Add("Name", "tom")
c.Request().Header.Del("Nested.Age")
Expand All @@ -473,7 +477,7 @@ func Test_Bind_Header_Schema(t *testing.T) {

c.Request().Header.Del("Nested.Agex")
q = new(Header1)
require.Equal(t, "Nested is empty", c.Bind().Header(q).Error())
require.Equal(t, "bind: Nested is empty", c.Bind().Header(q).Error())

c.Request().Header.Del("Nested.Agex")
c.Request().Header.Del("Name")
Expand All @@ -499,7 +503,7 @@ func Test_Bind_Header_Schema(t *testing.T) {
c.Request().Header.Del("Nested.Age")
c.Request().Header.Add("Nested.Agex", "10")
h2 = new(Header2)
require.Equal(t, "Nested.age is empty", c.Bind().Header(h2).Error())
require.Equal(t, "bind: Nested.age is empty", c.Bind().Header(h2).Error())

type Node struct {
Next *Node `header:"Next,required"`
Expand All @@ -514,7 +518,7 @@ func Test_Bind_Header_Schema(t *testing.T) {

c.Request().Header.Del("Val")
n = new(Node)
require.Equal(t, "Val is empty", c.Bind().Header(n).Error())
require.Equal(t, "bind: Val is empty", c.Bind().Header(n).Error())

c.Request().Header.Add("Val", "3")
c.Request().Header.Del("Next.Val")
Expand Down Expand Up @@ -595,7 +599,7 @@ func Test_Bind_RespHeader(t *testing.T) {
}
rh := new(RequiredHeader)
c.Response().Header.Del("name")
require.Equal(t, "name is empty", c.Bind().RespHeader(rh).Error())
require.Equal(t, "bind: name is empty", c.Bind().RespHeader(rh).Error())
}

// go test -run Test_Bind_RespHeader_Map -v
Expand Down Expand Up @@ -648,7 +652,40 @@ func Benchmark_Bind_Query(b *testing.B) {
for n := 0; n < b.N; n++ {
err = c.Bind().Query(q)
}

require.NoError(b, err)
require.Equal(b, "tom", q.Name)
require.Equal(b, 1, q.ID)
require.Len(b, q.Hobby, 2)
}

// go test -v -run=^$ -bench=Benchmark_Bind_Query_Default -benchmem -count=4
func Benchmark_Bind_Query_Default(b *testing.B) {
var err error

app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})

type Query struct {
Name string `query:"name,default:tom"`
Hobby []string `query:"hobby,default:football|basketball"`
ID int `query:"id,default:1"`
}
c.Request().SetBody([]byte(``))
c.Request().Header.SetContentType("")
c.Request().URI().SetQueryString("")
q := new(Query)
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
*q = Query{}
err = c.Bind().Query(q)
}

require.NoError(b, err)
require.Equal(b, "tom", q.Name)
require.Equal(b, 1, q.ID)
require.Len(b, q.Hobby, 2)
}

// go test -v -run=^$ -bench=Benchmark_Bind_Query_Map -benchmem -count=4
Expand Down Expand Up @@ -1314,7 +1351,7 @@ func Test_Bind_Cookie(t *testing.T) {
}
rh := new(RequiredCookie)
c.Request().Header.DelCookie("name")
require.Equal(t, "name is empty", c.Bind().Cookie(rh).Error())
require.Equal(t, "bind: name is empty", c.Bind().Cookie(rh).Error())
}

// go test -run Test_Bind_Cookie_Map -v
Expand Down Expand Up @@ -1424,7 +1461,7 @@ func Test_Bind_Cookie_Schema(t *testing.T) {

c.Request().Header.DelCookie("Name")
q = new(Cookie1)
require.Equal(t, "Name is empty", c.Bind().Cookie(q).Error())
require.Equal(t, "bind: Name is empty", c.Bind().Cookie(q).Error())

c.Request().Header.SetCookie("Name", "tom")
c.Request().Header.DelCookie("Nested.Age")
Expand All @@ -1434,7 +1471,7 @@ func Test_Bind_Cookie_Schema(t *testing.T) {

c.Request().Header.DelCookie("Nested.Agex")
q = new(Cookie1)
require.Equal(t, "Nested is empty", c.Bind().Cookie(q).Error())
require.Equal(t, "bind: Nested is empty", c.Bind().Cookie(q).Error())

c.Request().Header.DelCookie("Nested.Agex")
c.Request().Header.DelCookie("Name")
Expand All @@ -1460,7 +1497,7 @@ func Test_Bind_Cookie_Schema(t *testing.T) {
c.Request().Header.DelCookie("Nested.Age")
c.Request().Header.SetCookie("Nested.Agex", "10")
h2 = new(Cookie2)
require.Equal(t, "Nested.Age is empty", c.Bind().Cookie(h2).Error())
require.Equal(t, "bind: Nested.Age is empty", c.Bind().Cookie(h2).Error())

type Node struct {
Next *Node `cookie:"Next,required"`
Expand All @@ -1475,7 +1512,7 @@ func Test_Bind_Cookie_Schema(t *testing.T) {

c.Request().Header.DelCookie("Val")
n = new(Node)
require.Equal(t, "Val is empty", c.Bind().Cookie(n).Error())
require.Equal(t, "bind: Val is empty", c.Bind().Cookie(n).Error())

c.Request().Header.SetCookie("Val", "3")
c.Request().Header.DelCookie("Next.Val")
Expand Down Expand Up @@ -1591,7 +1628,7 @@ func Test_Bind_Must(t *testing.T) {
c.Request().URI().SetQueryString("")
err := c.Bind().Must().Query(rq)
require.Equal(t, StatusBadRequest, c.Response().StatusCode())
require.Equal(t, "Bad request: name is empty", err.Error())
require.Equal(t, "Bad request: bind: name is empty", err.Error())
}

// simple struct validator for testing
Expand Down
9 changes: 7 additions & 2 deletions binder/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package binder

import (
"errors"
"fmt"
"reflect"
"strings"
"sync"

"github.com/gofiber/utils/v2"
"github.com/valyala/bytebufferpool"

"github.com/gofiber/fiber/v3/internal/schema"
"github.com/gofiber/schema"
)

// ParserConfig form decoder config for SetParserDecoder
Expand Down Expand Up @@ -94,7 +95,11 @@ func parseToStruct(aliasTag string, out any, data map[string][]string) error {
// Set alias tag
schemaDecoder.SetAliasTag(aliasTag)

return schemaDecoder.Decode(out, data)
if err := schemaDecoder.Decode(out, data); err != nil {
return fmt.Errorf("bind: %w", err)

Check warning on line 99 in binder/mapping.go

View check run for this annotation

Codecov / codecov/patch

binder/mapping.go#L98-L99

Added lines #L98 - L99 were not covered by tests
}

return nil

Check warning on line 102 in binder/mapping.go

View check run for this annotation

Codecov / codecov/patch

binder/mapping.go#L102

Added line #L102 was not covered by tests
}

// Parse data into the map
Expand Down
37 changes: 37 additions & 0 deletions docs/api/bind.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,40 @@ app.Post("/", func(c fiber.Ctx) error {
}
})
```

## Default Fields

You can set default values for fields in the struct by using the `default` struct tag. Supported types:

- bool
- float variants (float32, float64)
- int variants (int, int8, int16, int32, int64)
- uint variants (uint, uint8, uint16, uint32, uint64)
- string
- a slice of the above types. As shown in the example above, **| should be used to separate between slice items**.
- a pointer to one of the above types **(pointer to slice and slice of pointers are not supported)**.

```go title="Example"
type Person struct {
Name string `query:"name,default:john"`
Pass string `query:"pass"`
Products []string `query:"products,default:shoe|hat"`
}

app.Get("/", func(c fiber.Ctx) error {
p := new(Person)

if err := c.Bind().Query(p); err != nil {
return err
}

log.Println(p.Name) // john
log.Println(p.Pass) // doe
log.Println(p.Products) // ["shoe,hat"]

// ...
})
// Run tests with the following curl command

// curl "http://localhost:3000/?pass=doe"
```
2 changes: 1 addition & 1 deletion error.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/json"
"errors"

"github.com/gofiber/fiber/v3/internal/schema"
"github.com/gofiber/schema"
)

// Wrap and return this for unreachable code if panicking is undesirable (i.e., in a handler).
Expand Down
2 changes: 1 addition & 1 deletion error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
"testing"

"github.com/gofiber/fiber/v3/internal/schema"
"github.com/gofiber/schema"
"github.com/stretchr/testify/require"
)

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/gofiber/fiber/v3
go 1.22

require (
github.com/gofiber/schema v1.2.0
github.com/gofiber/utils/v2 v2.0.0-beta.6
github.com/google/uuid v1.6.0
github.com/mattn/go-colorable v0.1.13
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg=
github.com/gofiber/schema v1.2.0/go.mod h1:YYwj01w3hVfaNjhtJzaqetymL56VW642YS3qZPhuE6c=
github.com/gofiber/utils/v2 v2.0.0-beta.6 h1:ED62bOmpRXdgviPlfTmf0Q+AXzhaTUAFtdWjgx+XkYI=
github.com/gofiber/utils/v2 v2.0.0-beta.6/go.mod h1:3Kz8Px3jInKFvqxDzDeoSygwEOO+3uyubTmUa6PqY+0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
Expand Down
27 changes: 0 additions & 27 deletions internal/schema/LICENSE

This file was deleted.

Loading

0 comments on commit fabf880

Please sign in to comment.