Binding
Analizar datos de request es una parte crucial de una aplicación web. En Echo esto se llama binding, y puede leer desde cuatro partes de un request HTTP:
- Parámetros de path de URL
- Parámetros de query de URL
- Headers
- Body del request
Binding con tags de struct
Sección titulada «Binding con tags de struct»Define un struct con tags que especifican el origen de datos y la clave, y luego llama a c.Bind()
con un puntero a él. Aquí el parámetro de query id se vincula al campo ID:
type User struct { ID string `query:"id"`}
// handler for /users?id=<userID>var user Userif err := c.Bind(&user); err != nil { return c.String(http.StatusBadRequest, "bad request")}Orígenes de datos
Sección titulada «Orígenes de datos»| Tag | Origen |
|---|---|
query | Parámetro de query |
param | Parámetro de path |
header | Valor de header |
form | Datos de formulario (query + body) |
json | Body del request (encoding/json) |
xml | Body del request (encoding/xml) |
Los campos de path, query, header y form requieren un tag explícito. JSON y XML usan el nombre del campo del struct cuando se omite el tag, igual que la biblioteca estándar.
Content types del body
Sección titulada «Content types del body»Al decodificar el body del request, el header Content-Type selecciona el decoder:
application/jsonapplication/xmlapplication/x-www-form-urlencoded
Múltiples orígenes y precedencia
Sección titulada «Múltiples orígenes y precedencia»Un campo puede declarar varios orígenes. Los datos se vinculan en este orden, y cada paso sobrescribe el anterior:
- Parámetros de path
- Parámetros de query (solo GET / DELETE)
- Body del request
type User struct { ID string `param:"id" query:"id" form:"id" json:"id" xml:"id"`}Binding directo desde un origen
Sección titulada «Binding directo desde un origen»echo.BindBody(c, &payload) // request bodyecho.BindQueryParams(c, &payload) // query parametersecho.BindPathValues(c, &payload) // path parametersecho.BindHeaders(c, &payload) // headerstype UserDTO struct { Name string `json:"name" form:"name" query:"name"` Email string `json:"email" form:"email" query:"email"`}
e.POST("/users", func(c *echo.Context) error { var dto UserDTO if err := c.Bind(&dto); err != nil { return c.String(http.StatusBadRequest, "bad request") } user := User{Name: dto.Name, Email: dto.Email, IsAdmin: false} executeSomeBusinessLogic(user) return c.JSON(http.StatusOK, user)})Binding fluido
Sección titulada «Binding fluido»Para binding explícito y type-safe desde un único origen, usa los binders fluidos. Encadenan la configuración y la ejecutan, recopilando errores:
// /api/search?active=true&id=1&id=2&id=3&length=25var opts struct { IDs []int64 Active bool}length := int64(50)
err := echo.QueryParamsBinder(c). Int64("length", &length). Int64s("id", &opts.IDs). Bool("active", &opts.Active). BindError() // first error, if anyBinders disponibles: echo.QueryParamsBinder(c), echo.PathValuesBinder(c),
echo.FormFieldBinder(c). Termina una cadena con BindError() (primer error) o
BindErrors() (todos los errores). FailFast(false) ejecuta toda la cadena; está activado por defecto.
Cada tipo soportado ofrece métodos Type(...), MustType(...), Types(...) (slices) y
MustTypes(...), por ejemplo Int64, MustInt64, Int64s. Usa
BindWithDelimiter("id", &dest, ",") para separar valores unidos por comas.
Binder personalizado
Sección titulada «Binder personalizado»Registra un binder personalizado mediante Echo#Binder:
type CustomBinder struct{}
func (cb *CustomBinder) Bind(c *echo.Context, i any) error { db := new(echo.DefaultBinder) if err := db.Bind(c, i); err != echo.ErrUnsupportedMediaType { return err } // custom logic here return nil}
e.Binder = &CustomBinder{}