binder

package
v3.0.0-beta.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 26, 2024 License: MIT Imports: 9 Imported by: 0

README

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:

Guides

Binding into a Struct

Fiber supports binding request data directly into a struct using gorilla/schema. Here's an example:

// 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:

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:

// 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.

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 or go-ozzo/ozzo-validation. Here's an example of a simple custom validator:

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"

Documentation

Index

Constants

View Source
const MIMEMultipartForm string = "multipart/form-data"

Variables

View Source
var (
	ErrSuitableContentNotFound = errors.New("binder: suitable content not found to parse body")
	ErrMapNotConvertable       = errors.New("binder: map is not convertable to map[string]string or map[string][]string")
)

Binder errors

View Source
var CBORBinderPool = sync.Pool{
	New: func() any {
		return &CBORBinding{}
	},
}
View Source
var CookieBinderPool = sync.Pool{
	New: func() any {
		return &CookieBinding{}
	},
}
View Source
var FormBinderPool = sync.Pool{
	New: func() any {
		return &FormBinding{}
	},
}
View Source
var HeaderBinderPool = sync.Pool{
	New: func() any {
		return &HeaderBinding{}
	},
}
View Source
var JSONBinderPool = sync.Pool{
	New: func() any {
		return &JSONBinding{}
	},
}
View Source
var QueryBinderPool = sync.Pool{
	New: func() any {
		return &QueryBinding{}
	},
}
View Source
var RespHeaderBinderPool = sync.Pool{
	New: func() any {
		return &RespHeaderBinding{}
	},
}
View Source
var URIBinderPool = sync.Pool{
	New: func() any {
		return &URIBinding{}
	},
}
View Source
var XMLBinderPool = sync.Pool{
	New: func() any {
		return &XMLBinding{}
	},
}

Functions

func FilterFlags

func FilterFlags(content string) string

Get content type from content type header

func GetFromThePool

func GetFromThePool[T any](pool *sync.Pool) T

func PutToThePool

func PutToThePool[T any](pool *sync.Pool, binder T)

func SetParserDecoder

func SetParserDecoder(parserConfig ParserConfig)

SetParserDecoder allow globally change the option of form decoder, update decoderPool

Types

type CBORBinding

type CBORBinding struct {
	CBORDecoder utils.CBORUnmarshal
}

CBORBinding is the CBOR binder for CBOR request body.

func (*CBORBinding) Bind

func (b *CBORBinding) Bind(body []byte, out any) error

Bind parses the request body as CBOR and returns the result.

func (*CBORBinding) Name

func (*CBORBinding) Name() string

Name returns the binding name.

func (*CBORBinding) Reset

func (b *CBORBinding) Reset()

Reset resets the CBORBinding binder.

type CookieBinding

type CookieBinding struct {
	EnableSplitting bool
}

CookieBinding is the cookie binder for cookie request body.

func (*CookieBinding) Bind

func (b *CookieBinding) Bind(req *fasthttp.Request, out any) error

Bind parses the request cookie and returns the result.

func (*CookieBinding) Name

func (*CookieBinding) Name() string

Name returns the binding name.

func (*CookieBinding) Reset

func (b *CookieBinding) Reset()

Reset resets the CookieBinding binder.

type FormBinding

type FormBinding struct {
	EnableSplitting bool
}

FormBinding is the form binder for form request body.

func (*FormBinding) Bind

func (b *FormBinding) Bind(req *fasthttp.Request, out any) error

Bind parses the request body and returns the result.

func (*FormBinding) Name

func (*FormBinding) Name() string

Name returns the binding name.

func (*FormBinding) Reset

func (b *FormBinding) Reset()

Reset resets the FormBinding binder.

type HeaderBinding

type HeaderBinding struct {
	EnableSplitting bool
}

v is the header binder for header request body.

func (*HeaderBinding) Bind

func (b *HeaderBinding) Bind(req *fasthttp.Request, out any) error

Bind parses the request header and returns the result.

func (*HeaderBinding) Name

func (*HeaderBinding) Name() string

Name returns the binding name.

func (*HeaderBinding) Reset

func (b *HeaderBinding) Reset()

Reset resets the HeaderBinding binder.

type JSONBinding

type JSONBinding struct {
	JSONDecoder utils.JSONUnmarshal
}

JSONBinding is the JSON binder for JSON request body.

func (*JSONBinding) Bind

func (b *JSONBinding) Bind(body []byte, out any) error

Bind parses the request body as JSON and returns the result.

func (*JSONBinding) Name

func (*JSONBinding) Name() string

Name returns the binding name.

func (*JSONBinding) Reset

func (b *JSONBinding) Reset()

Reset resets the JSONBinding binder.

type ParserConfig

type ParserConfig struct {
	SetAliasTag       string
	ParserType        []ParserType
	IgnoreUnknownKeys bool
	ZeroEmpty         bool
}

ParserConfig form decoder config for SetParserDecoder

type ParserType

type ParserType struct {
	CustomType any
	Converter  func(string) reflect.Value
}

ParserType require two element, type and converter for register. Use ParserType with BodyParser for parsing custom type in form data.

type QueryBinding

type QueryBinding struct {
	EnableSplitting bool
}

QueryBinding is the query binder for query request body.

func (*QueryBinding) Bind

func (b *QueryBinding) Bind(reqCtx *fasthttp.Request, out any) error

Bind parses the request query and returns the result.

func (*QueryBinding) Name

func (*QueryBinding) Name() string

Name returns the binding name.

func (*QueryBinding) Reset

func (b *QueryBinding) Reset()

Reset resets the QueryBinding binder.

type RespHeaderBinding

type RespHeaderBinding struct {
	EnableSplitting bool
}

RespHeaderBinding is the respHeader binder for response header.

func (*RespHeaderBinding) Bind

func (b *RespHeaderBinding) Bind(resp *fasthttp.Response, out any) error

Bind parses the response header and returns the result.

func (*RespHeaderBinding) Name

func (*RespHeaderBinding) Name() string

Name returns the binding name.

func (*RespHeaderBinding) Reset

func (b *RespHeaderBinding) Reset()

Reset resets the RespHeaderBinding binder.

type URIBinding

type URIBinding struct{}

uriBinding is the URI binder for URI parameters.

func (*URIBinding) Bind

func (b *URIBinding) Bind(params []string, paramsFunc func(key string, defaultValue ...string) string, out any) error

Bind parses the URI parameters and returns the result.

func (*URIBinding) Name

func (*URIBinding) Name() string

Name returns the binding name.

func (*URIBinding) Reset

func (*URIBinding) Reset()

Reset resets URIBinding binder.

type XMLBinding

type XMLBinding struct {
	XMLDecoder utils.XMLUnmarshal
}

XMLBinding is the XML binder for XML request body.

func (*XMLBinding) Bind

func (b *XMLBinding) Bind(body []byte, out any) error

Bind parses the request body as XML and returns the result.

func (*XMLBinding) Name

func (*XMLBinding) Name() string

Name returns the binding name.

func (*XMLBinding) Reset

func (b *XMLBinding) Reset()

Reset resets the XMLBinding binder.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL