LogoPly
Features

OpenAPI

Generate an OpenAPI 3.0 document from Ply route metadata.

OpenAPI

The openapi package builds an OpenAPI 3.0 document from the routes registered on a Ply app.

import "github.com/Dziqha/ply/openapi"

openapiHandler := openapi.New(app, openapi.Options{
	Info: openapi.Info{
		Title:       "Users API",
		Version:     "1.0.0",
		Description: "User management endpoints.",
	},
	Servers: []openapi.Server{{URL: "https://api.example.com"}},
}).Handler()

app.Get("/openapi.json", openapiHandler)

The handler serializes the document once, when it is created. Register all routes and set their metadata before creating it. Routes added afterwards do not appear in that document.

Route metadata

App methods return the route, so metadata can be set inline:

route := app.Get("/users/:id", getUser)
route.Summary = "Get user"
route.Description = "Returns one user by ID."
route.Tags = []string{"users"}
route.OperationID = "getUser"
FieldEffect
SummaryOperation summary
DescriptionOperation description
TagsOperation tags
OperationIDStable operation ID
DeprecatedMarks the operation deprecated
HiddenExcludes the route from the document

When Summary is empty, the builder uses Name. When OperationID is empty, it generates one from the method and path.

Paths and parameters

Ply path parameters are converted to OpenAPI path parameters:

/users/:id  ->  /users/{id}

Each parameter is emitted as a required string path parameter. Wildcard routes are skipped by default. Set IncludeWildcards to include them with a single {path} parameter.

Overrides

Options.Operations adds request bodies, responses, security, and other details that are not inferred from a route:

Operations: map[string]openapi.Operation{
	"POST /users": {
		Summary: "Create user",
		RequestBody: &openapi.RequestBody{
			Required: true,
			Content: map[string]openapi.MediaType{
				"application/json": {
					Schema: &openapi.Schema{Ref: "#/components/schemas/UserInput"},
				},
			},
		},
		Responses: map[string]openapi.Response{
			"201": {Description: "Created"},
			"400": {Description: "Invalid input"},
		},
	},
},

Keys use METHOD /path. Both the Ply path (POST /users/:id) and the converted path (POST /users/{id}) are accepted.

Components and security

Options{
	Components: &openapi.Components{
		Schemas: map[string]*openapi.Schema{
			"User": {
				Type: "object",
				Properties: map[string]*openapi.Schema{
					"id":   {Type: "string"},
					"name": {Type: "string"},
				},
			},
		},
		SecuritySchemes: map[string]openapi.SecurityScheme{
			"bearerAuth": {
				Type:         "http",
				Scheme:       "bearer",
				BearerFormat: "JWT",
			},
		},
	},
	Security: []map[string][]string{{"bearerAuth": {}}},
}

Security applies to the whole document. An operation can override it through Operations.

Raw documents

Use Document() to inspect or modify the generated document, JSON() to serialize it, or Handler(doc) to serve an already-built document:

doc := openapi.New(app).Document()
doc.Info.Title = "Internal API"

app.Get("/openapi.json", openapi.Handler(doc))

Notes

  • The package generates JSON documents. It does not serve Swagger UI or Redoc.
  • Route metadata is read at build time. Freeze the route set before creating the handler in production.
  • Hidden routes are useful for health checks, metrics, and gateway catch-all routes that should not appear in public API documentation.