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

chore: replace vendored gorilla/schema package #3152

Merged
merged 2 commits into from
Oct 11, 2024
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
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 @@

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 @@
// 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
Loading