# 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 "johndoe" 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" ```