mirror of https://github.com/gofiber/fiber.git
224 lines
5.8 KiB
Markdown
224 lines
5.8 KiB
Markdown
# Fiber Binders
|
|
|
|
**Binder** is a new request/response binding feature for Fiber introduced in Fiber v3. It replaces the old Fiber parsers and offers enhanced capabilities such as custom binder registration, struct validation, support for `map[string]string`, `map[string][]string`, and more. Binder replaces the following components:
|
|
|
|
- `BodyParser`
|
|
- `ParamsParser`
|
|
- `GetReqHeaders`
|
|
- `GetRespHeaders`
|
|
- `AllParams`
|
|
- `QueryParser`
|
|
- `ReqHeaderParser`
|
|
|
|
## Default Binders
|
|
|
|
Fiber provides several default binders out of the box:
|
|
|
|
- [Form](form.go)
|
|
- [Query](query.go)
|
|
- [URI](uri.go)
|
|
- [Header](header.go)
|
|
- [Response Header](resp_header.go)
|
|
- [Cookie](cookie.go)
|
|
- [JSON](json.go)
|
|
- [XML](xml.go)
|
|
- [CBOR](cbor.go)
|
|
|
|
## Guides
|
|
|
|
### Binding into a Struct
|
|
|
|
Fiber supports binding request data directly into a struct using [gofiber/schema](https://github.com/gofiber/schema). Here's an example:
|
|
|
|
```go
|
|
// Field names must start with an uppercase letter
|
|
type Person struct {
|
|
Name string `json:"name" xml:"name" form:"name"`
|
|
Pass string `json:"pass" xml:"pass" form:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Body(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // Output: john
|
|
log.Println(p.Pass) // Output: doe
|
|
|
|
// Additional logic...
|
|
})
|
|
|
|
// Run tests with the following curl commands:
|
|
|
|
// JSON
|
|
curl -X POST -H "Content-Type: application/json" --data "{\"name\":\"john\",\"pass\":\"doe\"}" localhost:3000
|
|
|
|
// XML
|
|
curl -X POST -H "Content-Type: application/xml" --data "<login><name>john</name><pass>doe</pass></login>" localhost:3000
|
|
|
|
// URL-Encoded Form
|
|
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data "name=john&pass=doe" localhost:3000
|
|
|
|
// Multipart Form
|
|
curl -X POST -F name=john -F pass=doe http://localhost:3000
|
|
|
|
// Query Parameters
|
|
curl -X POST "http://localhost:3000/?name=john&pass=doe"
|
|
```
|
|
|
|
### Binding into a Map
|
|
|
|
Fiber allows binding request data into a `map[string]string` or `map[string][]string`. Here's an example:
|
|
|
|
```go
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
params := make(map[string][]string)
|
|
|
|
if err := c.Bind().Query(params); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(params["name"]) // Output: [john]
|
|
log.Println(params["pass"]) // Output: [doe]
|
|
log.Println(params["products"]) // Output: [shoe hat]
|
|
|
|
// Additional logic...
|
|
return nil
|
|
})
|
|
|
|
// Run tests with the following curl command:
|
|
|
|
curl "http://localhost:3000/?name=john&pass=doe&products=shoe&products=hat"
|
|
```
|
|
|
|
### Automatic Error Handling with `WithAutoHandling`
|
|
|
|
By default, Fiber returns binder errors directly. To handle errors automatically and return a `400 Bad Request` status, use the `WithAutoHandling()` method.
|
|
|
|
**Example:**
|
|
|
|
```go
|
|
// Field names must start with an uppercase letter
|
|
type Person struct {
|
|
Name string `json:"name,required"`
|
|
Pass string `json:"pass"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().WithAutoHandling().JSON(p); err != nil {
|
|
return err
|
|
// Automatically returns status code 400
|
|
// Response: Bad request: name is empty
|
|
}
|
|
|
|
// Additional logic...
|
|
return nil
|
|
})
|
|
|
|
// Run tests with the following curl command:
|
|
|
|
curl -X GET -H "Content-Type: application/json" --data "{\"pass\":\"doe\"}" localhost:3000
|
|
```
|
|
|
|
### Defining a Custom Binder
|
|
|
|
Fiber maintains a minimal codebase by not including every possible binder. If you need to use a custom binder, you can easily register and utilize it. Here's an example of creating a `toml` binder.
|
|
|
|
```go
|
|
type Person struct {
|
|
Name string `toml:"name"`
|
|
Pass string `toml:"pass"`
|
|
}
|
|
|
|
type tomlBinding struct{}
|
|
|
|
func (b *tomlBinding) Name() string {
|
|
return "toml"
|
|
}
|
|
|
|
func (b *tomlBinding) MIMETypes() []string {
|
|
return []string{"application/toml"}
|
|
}
|
|
|
|
func (b *tomlBinding) Parse(c fiber.Ctx, out any) error {
|
|
return toml.Unmarshal(c.Body(), out)
|
|
}
|
|
|
|
func main() {
|
|
app := fiber.New()
|
|
app.RegisterCustomBinder(&tomlBinding{})
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
out := new(Person)
|
|
if err := c.Bind().Body(out); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Alternatively, specify the custom binder:
|
|
// if err := c.Bind().Custom("toml", out); err != nil {
|
|
// return err
|
|
// }
|
|
|
|
return c.SendString(out.Pass) // Output: test
|
|
})
|
|
|
|
app.Listen(":3000")
|
|
}
|
|
|
|
// Run tests with the following curl command:
|
|
|
|
curl -X GET -H "Content-Type: application/toml" --data "name = 'bar'
|
|
pass = 'test'" localhost:3000
|
|
```
|
|
|
|
### Defining a Custom Validator
|
|
|
|
All Fiber binders support struct validation if a validator is defined in the configuration. You can create your own validator or use existing ones like [go-playground/validator](https://github.com/go-playground/validator) or [go-ozzo/ozzo-validation](https://github.com/go-ozzo/ozzo-validation). Here's an example of a simple custom validator:
|
|
|
|
```go
|
|
type Query struct {
|
|
Name string `query:"name"`
|
|
}
|
|
|
|
type structValidator struct{}
|
|
|
|
func (v *structValidator) Engine() any {
|
|
return nil // Implement if using an external validation engine
|
|
}
|
|
|
|
func (v *structValidator) ValidateStruct(out any) error {
|
|
data := reflect.ValueOf(out).Elem().Interface()
|
|
query := data.(Query)
|
|
|
|
if query.Name != "john" {
|
|
return errors.New("you should have entered the correct name!")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
app := fiber.New(fiber.Config{
|
|
StructValidator: &structValidator{},
|
|
})
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
out := new(Query)
|
|
if err := c.Bind().Query(out); err != nil {
|
|
return err // Returns: you should have entered the correct name!
|
|
}
|
|
return c.SendString(out.Name)
|
|
})
|
|
|
|
app.Listen(":3000")
|
|
}
|
|
|
|
// Run tests with the following curl command:
|
|
|
|
curl "http://localhost:3000/?name=efe"
|
|
```
|