Skip to content

Commit 3fc1b29

Browse files
authored
chore: replace vendored gorilla/schema package (gofiber#3152)
1 parent c86c3c0 commit 3fc1b29

File tree

13 files changed

+104
-1383
lines changed

13 files changed

+104
-1383
lines changed

bind_test.go

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ func Test_Bind_Query(t *testing.T) {
5555
type Query2 struct {
5656
Name string
5757
Hobby string
58+
Default string `query:"default,default:hello"`
5859
FavouriteDrinks []string
5960
Empty []string
6061
Alloc []string
62+
Defaults []string `query:"defaults,default:hello|world"`
6163
No []int64
6264
ID int
6365
Bool bool
@@ -76,13 +78,15 @@ func Test_Bind_Query(t *testing.T) {
7678
require.Equal(t, nilSlice, q2.Empty)
7779
require.Equal(t, []string{""}, q2.Alloc)
7880
require.Equal(t, []int64{1}, q2.No)
81+
require.Equal(t, "hello", q2.Default)
82+
require.Equal(t, []string{"hello", "world"}, q2.Defaults)
7983

8084
type RequiredQuery struct {
8185
Name string `query:"name,required"`
8286
}
8387
rq := new(RequiredQuery)
8488
c.Request().URI().SetQueryString("")
85-
require.Equal(t, "name is empty", c.Bind().Query(rq).Error())
89+
require.Equal(t, "bind: name is empty", c.Bind().Query(rq).Error())
8690

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

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

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

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

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

231235
c.Request().URI().SetQueryString("nested.agex=10")
232236
q2 = new(Query2)
233-
require.Equal(t, "nested.age is empty", c.Bind().Query(q2).Error())
237+
require.Equal(t, "bind: nested.age is empty", c.Bind().Query(q2).Error())
234238

235239
c.Request().URI().SetQueryString("nested.agex=10")
236240
q2 = new(Query2)
237-
require.Equal(t, "nested.age is empty", c.Bind().Query(q2).Error())
241+
require.Equal(t, "bind: nested.age is empty", c.Bind().Query(q2).Error())
238242

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

249253
c.Request().URI().SetQueryString("next.val=2")
250254
n = new(Node)
251-
require.Equal(t, "val is empty", c.Bind().Query(n).Error())
255+
require.Equal(t, "bind: val is empty", c.Bind().Query(n).Error())
252256

253257
c.Request().URI().SetQueryString("val=3&next.value=2")
254258
n = new(Node)
@@ -354,7 +358,7 @@ func Test_Bind_Header(t *testing.T) {
354358
}
355359
rh := new(RequiredHeader)
356360
c.Request().Header.Del("name")
357-
require.Equal(t, "name is empty", c.Bind().Header(rh).Error())
361+
require.Equal(t, "bind: name is empty", c.Bind().Header(rh).Error())
358362
}
359363

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

464468
c.Request().Header.Del("Name")
465469
q = new(Header1)
466-
require.Equal(t, "Name is empty", c.Bind().Header(q).Error())
470+
require.Equal(t, "bind: Name is empty", c.Bind().Header(q).Error())
467471

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

474478
c.Request().Header.Del("Nested.Agex")
475479
q = new(Header1)
476-
require.Equal(t, "Nested is empty", c.Bind().Header(q).Error())
480+
require.Equal(t, "bind: Nested is empty", c.Bind().Header(q).Error())
477481

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

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

515519
c.Request().Header.Del("Val")
516520
n = new(Node)
517-
require.Equal(t, "Val is empty", c.Bind().Header(n).Error())
521+
require.Equal(t, "bind: Val is empty", c.Bind().Header(n).Error())
518522

519523
c.Request().Header.Add("Val", "3")
520524
c.Request().Header.Del("Next.Val")
@@ -595,7 +599,7 @@ func Test_Bind_RespHeader(t *testing.T) {
595599
}
596600
rh := new(RequiredHeader)
597601
c.Response().Header.Del("name")
598-
require.Equal(t, "name is empty", c.Bind().RespHeader(rh).Error())
602+
require.Equal(t, "bind: name is empty", c.Bind().RespHeader(rh).Error())
599603
}
600604

601605
// go test -run Test_Bind_RespHeader_Map -v
@@ -648,7 +652,40 @@ func Benchmark_Bind_Query(b *testing.B) {
648652
for n := 0; n < b.N; n++ {
649653
err = c.Bind().Query(q)
650654
}
655+
656+
require.NoError(b, err)
657+
require.Equal(b, "tom", q.Name)
658+
require.Equal(b, 1, q.ID)
659+
require.Len(b, q.Hobby, 2)
660+
}
661+
662+
// go test -v -run=^$ -bench=Benchmark_Bind_Query_Default -benchmem -count=4
663+
func Benchmark_Bind_Query_Default(b *testing.B) {
664+
var err error
665+
666+
app := New()
667+
c := app.AcquireCtx(&fasthttp.RequestCtx{})
668+
669+
type Query struct {
670+
Name string `query:"name,default:tom"`
671+
Hobby []string `query:"hobby,default:football|basketball"`
672+
ID int `query:"id,default:1"`
673+
}
674+
c.Request().SetBody([]byte(``))
675+
c.Request().Header.SetContentType("")
676+
c.Request().URI().SetQueryString("")
677+
q := new(Query)
678+
b.ReportAllocs()
679+
b.ResetTimer()
680+
for n := 0; n < b.N; n++ {
681+
*q = Query{}
682+
err = c.Bind().Query(q)
683+
}
684+
651685
require.NoError(b, err)
686+
require.Equal(b, "tom", q.Name)
687+
require.Equal(b, 1, q.ID)
688+
require.Len(b, q.Hobby, 2)
652689
}
653690

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

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

14251462
c.Request().Header.DelCookie("Name")
14261463
q = new(Cookie1)
1427-
require.Equal(t, "Name is empty", c.Bind().Cookie(q).Error())
1464+
require.Equal(t, "bind: Name is empty", c.Bind().Cookie(q).Error())
14281465

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

14351472
c.Request().Header.DelCookie("Nested.Agex")
14361473
q = new(Cookie1)
1437-
require.Equal(t, "Nested is empty", c.Bind().Cookie(q).Error())
1474+
require.Equal(t, "bind: Nested is empty", c.Bind().Cookie(q).Error())
14381475

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

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

14761513
c.Request().Header.DelCookie("Val")
14771514
n = new(Node)
1478-
require.Equal(t, "Val is empty", c.Bind().Cookie(n).Error())
1515+
require.Equal(t, "bind: Val is empty", c.Bind().Cookie(n).Error())
14791516

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

15971634
// simple struct validator for testing

binder/mapping.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package binder
22

33
import (
44
"errors"
5+
"fmt"
56
"reflect"
67
"strings"
78
"sync"
89

910
"github.com/gofiber/utils/v2"
1011
"github.com/valyala/bytebufferpool"
1112

12-
"github.com/gofiber/fiber/v3/internal/schema"
13+
"github.com/gofiber/schema"
1314
)
1415

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

97-
return schemaDecoder.Decode(out, data)
98+
if err := schemaDecoder.Decode(out, data); err != nil {
99+
return fmt.Errorf("bind: %w", err)
100+
}
101+
102+
return nil
98103
}
99104

100105
// Parse data into the map

docs/api/bind.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,3 +573,40 @@ app.Post("/", func(c fiber.Ctx) error {
573573
}
574574
})
575575
```
576+
577+
## Default Fields
578+
579+
You can set default values for fields in the struct by using the `default` struct tag. Supported types:
580+
581+
- bool
582+
- float variants (float32, float64)
583+
- int variants (int, int8, int16, int32, int64)
584+
- uint variants (uint, uint8, uint16, uint32, uint64)
585+
- string
586+
- a slice of the above types. As shown in the example above, **| should be used to separate between slice items**.
587+
- a pointer to one of the above types **(pointer to slice and slice of pointers are not supported)**.
588+
589+
```go title="Example"
590+
type Person struct {
591+
Name string `query:"name,default:john"`
592+
Pass string `query:"pass"`
593+
Products []string `query:"products,default:shoe|hat"`
594+
}
595+
596+
app.Get("/", func(c fiber.Ctx) error {
597+
p := new(Person)
598+
599+
if err := c.Bind().Query(p); err != nil {
600+
return err
601+
}
602+
603+
log.Println(p.Name) // john
604+
log.Println(p.Pass) // doe
605+
log.Println(p.Products) // ["shoe,hat"]
606+
607+
// ...
608+
})
609+
// Run tests with the following curl command
610+
611+
// curl "http://localhost:3000/?pass=doe"
612+
```

error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"encoding/json"
55
"errors"
66

7-
"github.com/gofiber/fiber/v3/internal/schema"
7+
"github.com/gofiber/schema"
88
)
99

1010
// Wrap and return this for unreachable code if panicking is undesirable (i.e., in a handler).

error_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"errors"
66
"testing"
77

8-
"github.com/gofiber/fiber/v3/internal/schema"
8+
"github.com/gofiber/schema"
99
"github.com/stretchr/testify/require"
1010
)
1111

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/gofiber/fiber/v3
33
go 1.22
44

55
require (
6+
github.com/gofiber/schema v1.2.0
67
github.com/gofiber/utils/v2 v2.0.0-beta.6
78
github.com/google/uuid v1.6.0
89
github.com/mattn/go-colorable v0.1.13

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
22
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
33
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
44
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg=
6+
github.com/gofiber/schema v1.2.0/go.mod h1:YYwj01w3hVfaNjhtJzaqetymL56VW642YS3qZPhuE6c=
57
github.com/gofiber/utils/v2 v2.0.0-beta.6 h1:ED62bOmpRXdgviPlfTmf0Q+AXzhaTUAFtdWjgx+XkYI=
68
github.com/gofiber/utils/v2 v2.0.0-beta.6/go.mod h1:3Kz8Px3jInKFvqxDzDeoSygwEOO+3uyubTmUa6PqY+0=
79
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

internal/schema/LICENSE

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)