Routes & operations
Routes and operations turn an annotation into an entry in the spec’s paths
map, wired to the parameters it accepts and the responses it returns. This page
covers the two operation annotations and the companion structs they reference.
Each pane pairs the annotated Go (left) with the exact fragment the scanner
emits (right), from the test-covered
docs/examples/concepts/routes
package.
For the exhaustive rule on any annotation below, follow its link to the
Maintainers reference; the
Parameters: / Responses: body grammars are covered in
Sub-languages.
swagger:route
swagger:route <METHOD> <path> [tags] <operationID> declares a path and its
operation in one annotation. The body’s responses: block ties status codes to
named responses ($ref into the spec’s responses). It lives in a plain
comment block — no Go declaration required.
// swagger:route GET /pets pets listPets
//
// Lists pets in the store, optionally filtered by tag.
//
// responses:
//
// 200: petsResponse
// default: errorResponseFull source: docs/examples/concepts/routes/routes.go
{
"get": {
"tags": [
"pets"
],
"summary": "Lists pets in the store, optionally filtered by tag.",
"operationId": "listPets",
"parameters": [
{
"type": "string",
"x-go-name": "Tag",
"description": "Tag filters pets by tag.",
"name": "tag",
"in": "query"
},
{
"maximum": 100,
"minimum": 1,
"type": "integer",
"format": "int32",
"x-go-name": "Limit",
"description": "Limit caps the number of results.",
"name": "limit",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/petsResponse"
},
"default": {
"$ref": "#/responses/errorResponse"
}
}
}
}
Full source: docs/examples/concepts/routes/testdata/route.json
The body can also carry an indented Parameters: block to declare simple
parameters (path / query / header) inline — no swagger:parameters struct
needed. For body parameters or parameter sets shared across operations, use
swagger:parameters instead. The block syntax is covered
in sub-languages.
swagger:operation
swagger:operation carries the same header but spells the operation out as a
YAML document after a --- fence — useful when you want to author the operation
object directly (here a path parameter and an inline $ref response schema).
// swagger:operation GET /pets/{id} pets getPet
//
// ---
// summary: Get a pet by ID.
// parameters:
// - name: id
// in: path
// required: true
// type: integer
// format: int64
// responses:
// '200':
// description: the requested pet
// schema:
// $ref: '#/definitions/Pet'
// default:
// $ref: '#/responses/errorResponse'Full source: docs/examples/concepts/routes/routes.go
{
"get": {
"tags": [
"pets"
],
"summary": "Get a pet by ID.",
"operationId": "getPet",
"parameters": [
{
"type": "integer",
"format": "int64",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "the requested pet",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"$ref": "#/responses/errorResponse"
}
}
}
}
Full source: docs/examples/concepts/routes/testdata/operation.json
swagger:parameters
swagger:parameters <operationID>… declares a struct whose fields become the
parameters of the named operation(s). Field doc comments carry in:, the
validations, and the description; the parameters attach to every operation ID
listed.
// ListPetsParams is the parameter set for the listPets operation. Each field
// becomes one parameter; the operation IDs after swagger:parameters name the
// operations the set applies to.
//
// swagger:parameters listPets
type ListPetsParams struct {
// Tag filters pets by tag.
//
// in: query
Tag string `json:"tag"`
// Limit caps the number of results.
//
// in: query
// minimum: 1
// maximum: 100
Limit int32 `json:"limit"`
}Full source: docs/examples/concepts/routes/routes.go
[
{
"type": "string",
"x-go-name": "Tag",
"description": "Tag filters pets by tag.",
"name": "tag",
"in": "query"
},
{
"maximum": 100,
"minimum": 1,
"type": "integer",
"format": "int32",
"x-go-name": "Limit",
"description": "Limit caps the number of results.",
"name": "limit",
"in": "query"
}
]
Full source: docs/examples/concepts/routes/testdata/parameters.json
A field marked in: body makes its Go type the request body schema — the
usual shape for a POST or PUT payload:
// CreatePetParams is the request parameter set for createPet. A field marked
// `in: body` makes its Go type the request body schema — the usual shape for a
// POST or PUT payload.
//
// swagger:parameters createPet
type CreatePetParams struct {
// Body is the pet to create.
//
// in: body
// required: true
Body Pet `json:"body"`
}
// swagger:route POST /pets/import pets createPet
//
// responses:
//
// 200: petsResponseFull source: docs/examples/concepts/routes/routes.go
[
{
"x-go-name": "Body",
"description": "Body is the pet to create.",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
]
Full source: docs/examples/concepts/routes/testdata/bodyparam.json
When a parameter field’s Go type is a struct (or any type that has no simple
Swagger representation), it cannot be a query/path/header parameter on its own. A
swagger:type override
collapses it to a simple parameter — a scalar, or a []-wrapped scalar for an
array parameter:
// Cursor is an opaque pagination token. As a struct it cannot be a query
// parameter on its own; swagger:type publishes it as a simple parameter.
type Cursor struct {
Page int
Token string
}
// FilterPetsParams shows swagger:type on parameter fields: a struct-typed field
// is collapsed to a simple parameter. The override accepts a scalar or a
// []-wrapped scalar — the inline / type-name forms are rejected here (a
// non-body parameter has no schema to inline into).
//
// swagger:parameters filterPets
type FilterPetsParams struct {
// After is an opaque cursor carried as a plain string query parameter.
//
// in: query
// swagger:type string
After Cursor `json:"after"`
// Sort is a list of sort keys carried as an array-of-string query parameter.
//
// in: query
// swagger:type []string
Sort []Cursor `json:"sort"`
}
// swagger:route GET /pets/filter pets filterPets
//
// Filter pets with cursor pagination.
//
// responses:
//
// 200: description: matched petsFull source: docs/examples/concepts/routes/routes.go
[
{
"type": "string",
"x-go-name": "After",
"description": "After is an opaque cursor carried as a plain string query parameter.",
"name": "after",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"x-go-name": "Sort",
"description": "Sort is a list of sort keys carried as an array-of-string query parameter.",
"name": "sort",
"in": "query"
}
]
Full source: docs/examples/concepts/routes/testdata/paramtype.json
swagger:response
swagger:response <name> declares a struct as a named entry in the spec’s
top-level responses. A Body field (or in: body) becomes the response
schema; routes reference it by name. Here the body is a []Pet, so the schema
is an array of $refs.
// PetsResponse is the list returned by listPets.
//
// swagger:response petsResponse
type PetsResponse struct {
// in: body
Body []Pet
}
// ErrorResponse is the default error payload.
//
// swagger:response errorResponse
type ErrorResponse struct {
// in: body
Body struct {
// Message is a human-readable error message.
Message string `json:"message"`
}
}Full source: docs/examples/concepts/routes/routes.go
{
"description": "PetsResponse is the list returned by listPets.",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
}
Full source: docs/examples/concepts/routes/testdata/response.json
swagger:file
swagger:file on a parameter field marks it as a binary upload — the parameter
emits as {type: file}. It belongs on a formData field of a
swagger:parameters struct.
// swagger:route POST /pets/{id}/photo pets uploadPetPhoto
//
// responses:
//
// 200: petsResponse
// UploadParams is the multipart upload for the uploadPetPhoto operation.
//
// swagger:parameters uploadPetPhoto
type UploadParams struct {
// Photo is the image to upload.
//
// in: formData
// swagger:file
Photo io.ReadCloser `json:"photo"`
}Full source: docs/examples/concepts/routes/routes.go
[
{
"type": "file",
"x-go-name": "Photo",
"description": "Photo is the image to upload.",
"name": "photo",
"in": "formData"
}
]
Full source: docs/examples/concepts/routes/testdata/file.json
externalDocs
An externalDocs: block (description + url) links an object out to external
documentation. It rides an operation (in a swagger:route or
swagger:operation body) and a full schema (a swagger:model). It is a
full-Schema-only keyword: on a simple-schema parameter (anything but in: body)
it is dropped with a diagnostic. The same ExternalDocs: block on a
swagger:meta package populates the spec’s top-level externalDocs (see
Document metadata).
// swagger:route GET /pets/search pets searchPets
//
// Searches pets. The operation links out to external documentation.
//
// externalDocs:
// description: Search guide
// url: https://example.com/docs/search
//
// responses:
//
// 200: petsResponse
// CatalogEntry carries externalDocs at the schema level (the link rides the
// definition) and on its fields. (On a simple-schema parameter externalDocs is
// dropped with a diagnostic: it is a full-Schema-only keyword.)
//
// externalDocs: {description: "Catalog schema reference", url: "https://example.com/docs/catalog"}
//
// swagger:model
type CatalogEntry struct {
// SKU is the catalog identifier.
SKU string `json:"sku"`
// Vendor is a plain field: externalDocs attaches directly to the property.
//
// externalDocs: {description: "Vendor field docs", url: "https://example.com/docs/vendor"}
Vendor string `json:"vendor"`
// Supplier is a $ref'd field: its sibling externalDocs lifts onto the
// field's allOf compound (a bare $ref cannot carry sibling keywords).
//
// externalDocs: {description: "Supplier docs", url: "https://example.com/docs/supplier"}
Supplier Supplier `json:"supplier"`
}
// Supplier is referenced by CatalogEntry.Supplier.
//
// swagger:model
type Supplier struct {
// Name is the supplier name.
Name string `json:"name"`
}Full source: docs/examples/concepts/routes/routes.go
{
"description": "Search guide",
"url": "https://example.com/docs/search"
}
Full source: docs/examples/concepts/routes/testdata/externaldocs.json
On a model the link rides the definition, and it also rides individual
struct fields: on a plain field it attaches to the property directly; on a
$ref’d field it is lifted onto the field’s allOf compound (a bare $ref
cannot carry sibling keywords). The value can be written as the indented block
above or as an equivalent inline { description: …, url: … } mapping — which
reads better on a single-line doc comment:
// swagger:route GET /pets/search pets searchPets
//
// Searches pets. The operation links out to external documentation.
//
// externalDocs:
// description: Search guide
// url: https://example.com/docs/search
//
// responses:
//
// 200: petsResponse
// CatalogEntry carries externalDocs at the schema level (the link rides the
// definition) and on its fields. (On a simple-schema parameter externalDocs is
// dropped with a diagnostic: it is a full-Schema-only keyword.)
//
// externalDocs: {description: "Catalog schema reference", url: "https://example.com/docs/catalog"}
//
// swagger:model
type CatalogEntry struct {
// SKU is the catalog identifier.
SKU string `json:"sku"`
// Vendor is a plain field: externalDocs attaches directly to the property.
//
// externalDocs: {description: "Vendor field docs", url: "https://example.com/docs/vendor"}
Vendor string `json:"vendor"`
// Supplier is a $ref'd field: its sibling externalDocs lifts onto the
// field's allOf compound (a bare $ref cannot carry sibling keywords).
//
// externalDocs: {description: "Supplier docs", url: "https://example.com/docs/supplier"}
Supplier Supplier `json:"supplier"`
}
// Supplier is referenced by CatalogEntry.Supplier.
//
// swagger:model
type Supplier struct {
// Name is the supplier name.
Name string `json:"name"`
}Full source: docs/examples/concepts/routes/routes.go
{
"description": "CatalogEntry carries externalDocs at the schema level (the link rides the\ndefinition) and on its fields. (On a simple-schema parameter externalDocs is\ndropped with a diagnostic: it is a full-Schema-only keyword.)",
"type": "object",
"properties": {
"sku": {
"description": "SKU is the catalog identifier.",
"type": "string",
"x-go-name": "SKU"
},
"supplier": {
"description": "Supplier is a $ref'd field: its sibling externalDocs lifts onto the\nfield's allOf compound (a bare $ref cannot carry sibling keywords).",
"allOf": [
{
"$ref": "#/definitions/Supplier"
}
],
"x-go-name": "Supplier",
"externalDocs": {
"description": "Supplier docs",
"url": "https://example.com/docs/supplier"
}
},
"vendor": {
"description": "Vendor is a plain field: externalDocs attaches directly to the property.",
"type": "string",
"x-go-name": "Vendor",
"externalDocs": {
"description": "Vendor field docs",
"url": "https://example.com/docs/vendor"
}
}
},
"x-go-package": "github.com/go-openapi/codescan/docs/examples/concepts/routes",
"externalDocs": {
"description": "Catalog schema reference",
"url": "https://example.com/docs/catalog"
}
}
Full source: docs/examples/concepts/routes/testdata/externaldocs_schema.json
What’s next
- Sharing parameters & responses
— declare a header or error response once and
$refit from many operations. - Validations — constrain parameter and field values.
- Model definitions — the schemas these operations reference.
- Shaping the output —
$refvs inline, aliases, and the other rendering knobs.