Pular para o conteúdo
Esta página ainda não foi traduzida. O conteúdo abaixo está em inglês. Ler em inglês

APIs

Typed handlers

api.Register binds and validates the input struct, writes the output as JSON and describes the route for OpenAPI.

Última atualização:

Go
type StoreProduct struct {
	ShopID int64   `json:"shop"  validate:"required,positive"`
	Name   string  `json:"name"  validate:"required,max=80" doc:"Display name"`
	Price  float64 `json:"price" validate:"min=0"`
}

r.Group("/api/v1/shops/{shop}", func(g *router.Group) {
	g.Use(auth.Required(apiGuard)) // Op.Security only documents the scheme

	api.Register(g, "POST /products", api.Op{
		Name:     "products.store",
		Summary:  "Create a product",
		Tags:     []string{"products"},
		Security: []string{"bearer"},
	}, func(c *web.Ctx, in StoreProduct) (resources.Product, error) {
		p := models.Product{ShopID: in.ShopID, Name: in.Name, Price: in.Price}
		if err := orm.Create(c.Context(), db, &p); err != nil {
			return resources.Product{}, err
		}

		return resources.FromProduct(p), nil
	})
})

Input#

  • The input is built from the query string, the JSON or form body and the path parameters, in that order; path parameters win over body fields of the same name (a body cannot change {shop}).
  • GET, HEAD and DELETE read only the query string.
  • It is validated with the input struct's validate tags (the same rules as web.Bind); failures answer 422 with field errors, malformed JSON answers 400.
  • Use struct{} as the input type when there is none.

Output#

CaseStatus
Op.Status setthat status
output type is struct{}204, no body
POST201
otherwise200

Errors returned by the handler go through the normal problem+json path.

Response validation#

Set Op.ValidateResponse: true to check the output against its validate tags before it is written (the output type must be a struct, otherwise Register panics at boot):

Go
api.Register(g, "GET /tasks", api.Op{Name: "tasks.index", ValidateResponse: true}, tasks.Index)

The check runs when web.Services.CheckResponses is on (the same switch as web.JSONWith). The app turns it on whenever APP_ENV is not production, that is development or test: a staging deployment that runs with APP_ENV=development checks too and answers 500 on a mismatch. A mismatch is a server bug: it is logged and answered with a generic 500 instead of sending data that breaks the documented contract. In production the output is written without the check.

A list field tagged validate:"required" must be present and not null (a nil slice fails), but may be empty; use min=1 when it needs items.

Route metadata#

Op.Name names the route (and becomes the OpenAPI operationId). Every typed route carries an *api.Operation with its method, full path (group prefixes included), path parameters and input/output types, readable from router.RouteInfo.Doc. That is what the OpenAPI generator uses; plain web.HandlerFunc routes keep working beside typed ones.

Op.Security only declares the security scheme in the OpenAPI document; it does not authenticate anything. Protect the route or its group with auth.Required (and auth.Ability for token abilities).