OpenAPI Builder¶
The pkg/openapibuilder package provides a fluent API for programmatically constructing OpenAPI 3.x specifications.
Overview¶
import "github.com/grokify/traffic2openapi/pkg/openapibuilder"
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("My API").
Version("1.0.0").
Build()
Supported Versions¶
| Version | Constant | Description |
|---|---|---|
| 3.0.3 | Version303 |
Wide compatibility |
| 3.1.0 | Version310 |
JSON Schema 2020-12 (default) |
| 3.2.0 | Version320 |
Latest features |
SpecBuilder¶
The entry point for building OpenAPI specifications.
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("Pet Store API").
Description("A sample Pet Store API").
Version("1.0.0").
TermsOfService("https://example.com/terms").
Contact("API Support", "support@example.com", "https://example.com/support").
License("MIT", "https://opensource.org/licenses/MIT").
Server("https://api.example.com").
ServerWithDescription("https://staging.example.com", "Staging server").
Build()
PathBuilder¶
Define API paths and their operations.
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("User API").
Version("1.0.0").
Path("/users").
Get().
Summary("List all users").
OperationID("listUsers").
Tag("users").
Response(200).Description("Success").JSON(usersSchema).Done().
Done().
Post().
Summary("Create a user").
OperationID("createUser").
Tag("users").
RequestBody().Required().JSON(createUserSchema).Done().
Response(201).Description("Created").JSON(userSchema).Done().
Done().
Done().
Path("/users/{userId}").
Get().
Summary("Get user by ID").
OperationID("getUser").
PathParam("userId").Description("User ID").Schema(openapibuilder.StringSchema()).Done().
Response(200).Description("Success").JSON(userSchema).Done().
Response(404).Description("Not found").Done().
Done().
Done().
Build()
SchemaBuilder¶
Build JSON Schema definitions for request/response bodies.
Primitive Types¶
// String
openapibuilder.StringSchema()
openapibuilder.StringSchema().Format("email")
openapibuilder.StringSchema().Format("uuid")
openapibuilder.StringSchema().MinLength(1).MaxLength(100)
openapibuilder.StringSchema().Pattern(`^[a-z]+$`)
openapibuilder.StringSchema().Enum("active", "inactive", "pending")
// Integer
openapibuilder.IntegerSchema()
openapibuilder.IntegerSchema().Format("int64")
openapibuilder.IntegerSchema().Minimum(0).Maximum(100)
// Number
openapibuilder.NumberSchema()
openapibuilder.NumberSchema().Format("double")
// Boolean
openapibuilder.BooleanSchema()
Complex Types¶
// Object
openapibuilder.ObjectSchema().
Property("id", openapibuilder.IntegerSchema().Format("int64")).
Property("name", openapibuilder.StringSchema()).
Property("email", openapibuilder.StringSchema().Format("email")).
Required("id", "name")
// Array
openapibuilder.ArraySchema(openapibuilder.StringSchema())
openapibuilder.ArraySchema(openapibuilder.RefSchema("User"))
// Reference
openapibuilder.RefSchema("User") // References #/components/schemas/User
// Nullable (version-aware)
openapibuilder.StringSchema().Nullable() // OpenAPI 3.0: nullable: true
// OpenAPI 3.1+: type: ["string", "null"]
Composition¶
// AllOf
openapibuilder.AllOfSchema(
openapibuilder.RefSchema("BaseModel"),
openapibuilder.ObjectSchema().Property("extra", openapibuilder.StringSchema()),
)
// OneOf
openapibuilder.OneOfSchema(
openapibuilder.RefSchema("Cat"),
openapibuilder.RefSchema("Dog"),
)
// AnyOf
openapibuilder.AnyOfSchema(
openapibuilder.StringSchema(),
openapibuilder.IntegerSchema(),
)
Components¶
Define reusable schemas, parameters, and security schemes.
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("API").
Version("1.0.0").
Components().
// Schemas
Schema("User", openapibuilder.ObjectSchema().
Property("id", openapibuilder.IntegerSchema()).
Property("name", openapibuilder.StringSchema()).
Required("id", "name")).
Schema("Error", openapibuilder.ObjectSchema().
Property("code", openapibuilder.IntegerSchema()).
Property("message", openapibuilder.StringSchema())).
// Security Schemes
SecurityScheme("bearerAuth").BearerAuth().BearerFormat("JWT").Done().
SecurityScheme("apiKey").APIKeyAuth("X-API-Key", "header").Done().
SecurityScheme("oauth2").OAuth2().
AuthorizationCodeFlow(
"https://auth.example.com/authorize",
"https://auth.example.com/token",
).
Scope("read:users", "Read user data").
Scope("write:users", "Write user data").
Done().
Done().
Done().
Build()
Security¶
Apply security requirements to operations.
// Global security (applies to all operations)
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("API").
Version("1.0.0").
Components().
SecurityScheme("bearerAuth").BearerAuth().Done().
Done().
Security("bearerAuth"). // Apply globally
Path("/users").
Get().
// Inherits global security
Done().
Done().
Build()
// Per-operation security
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("API").
Version("1.0.0").
Path("/public").
Get().
Security().None(). // No auth required
Done().
Done().
Path("/private").
Get().
Security().Scheme("bearerAuth"). // Requires bearer token
Done().
Done().
Build()
Parameters¶
Define query, path, header, and cookie parameters.
openapibuilder.NewSpec(openapibuilder.Version310).
Path("/users").
Get().
// Query parameters
QueryParam("limit").
Description("Maximum results").
Schema(openapibuilder.IntegerSchema().Minimum(1).Maximum(100)).
Done().
QueryParam("offset").
Description("Pagination offset").
Schema(openapibuilder.IntegerSchema().Minimum(0)).
Done().
// Header parameter
HeaderParam("X-Request-ID").
Description("Request tracking ID").
Schema(openapibuilder.StringSchema().Format("uuid")).
Done().
Done().
Done().
Path("/users/{userId}").
Get().
// Path parameter
PathParam("userId").
Description("User identifier").
Schema(openapibuilder.StringSchema()).
Done().
Done().
Done()
Request Bodies¶
Define request body schemas.
openapibuilder.NewSpec(openapibuilder.Version310).
Path("/users").
Post().
RequestBody().
Required().
Description("User to create").
JSON(openapibuilder.ObjectSchema().
Property("name", openapibuilder.StringSchema()).
Property("email", openapibuilder.StringSchema().Format("email")).
Required("name", "email")).
Done().
Response(201).Description("Created").Done().
Done().
Done()
Responses¶
Define response schemas for different status codes.
openapibuilder.NewSpec(openapibuilder.Version310).
Path("/users/{userId}").
Get().
Response(200).
Description("User found").
JSON(openapibuilder.RefSchema("User")).
Header("X-Request-ID", openapibuilder.StringSchema()).
Done().
Response(404).
Description("User not found").
JSON(openapibuilder.RefSchema("Error")).
Done().
Response(500).
Description("Internal server error").
JSON(openapibuilder.RefSchema("Error")).
Done().
Done().
Done()
Error Handling¶
The builder validates specifications at build time.
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
// Missing required title
Version("1.0.0").
Build()
if err != nil {
// err: "title is required"
}
Use MustBuild() for panic-on-error behavior (useful in tests):
spec := openapibuilder.NewSpec(openapibuilder.Version310).
Title("API").
Version("1.0.0").
MustBuild() // Panics if validation fails
Full Example¶
package main
import (
"log"
"github.com/grokify/traffic2openapi/pkg/openapi"
"github.com/grokify/traffic2openapi/pkg/openapibuilder"
)
func main() {
spec, err := openapibuilder.NewSpec(openapibuilder.Version310).
Title("Pet Store API").
Description("A sample API for managing pets").
Version("1.0.0").
Server("https://api.petstore.io/v1").
Components().
Schema("Pet", openapibuilder.ObjectSchema().
Property("id", openapibuilder.IntegerSchema().Format("int64")).
Property("name", openapibuilder.StringSchema()).
Property("status", openapibuilder.StringSchema().Enum("available", "pending", "sold")).
Required("id", "name")).
Schema("Error", openapibuilder.ObjectSchema().
Property("code", openapibuilder.IntegerSchema()).
Property("message", openapibuilder.StringSchema())).
SecurityScheme("bearerAuth").BearerAuth().BearerFormat("JWT").Done().
Done().
Security("bearerAuth").
Path("/pets").
Get().
Summary("List all pets").
OperationID("listPets").
Tag("pets").
QueryParam("limit").Schema(openapibuilder.IntegerSchema().Maximum(100)).Done().
QueryParam("status").Schema(openapibuilder.StringSchema().Enum("available", "pending", "sold")).Done().
Response(200).Description("A list of pets").
JSON(openapibuilder.ArraySchema(openapibuilder.RefSchema("Pet"))).Done().
Done().
Post().
Summary("Create a pet").
OperationID("createPet").
Tag("pets").
RequestBody().Required().JSON(openapibuilder.RefSchema("Pet")).Done().
Response(201).Description("Pet created").JSON(openapibuilder.RefSchema("Pet")).Done().
Response(400).Description("Invalid input").JSON(openapibuilder.RefSchema("Error")).Done().
Done().
Done().
Path("/pets/{petId}").
Get().
Summary("Get a pet by ID").
OperationID("getPet").
Tag("pets").
PathParam("petId").Description("Pet ID").Schema(openapibuilder.IntegerSchema().Format("int64")).Done().
Response(200).Description("Pet found").JSON(openapibuilder.RefSchema("Pet")).Done().
Response(404).Description("Pet not found").JSON(openapibuilder.RefSchema("Error")).Done().
Done().
Done().
Build()
if err != nil {
log.Fatal(err)
}
// Write to file
if err := openapi.WriteFile("petstore.yaml", spec); err != nil {
log.Fatal(err)
}
}