Basic Usage
3 minute read
Learn how to generate OpenAPI specifications from Go code using the openapi package.
Creating an API Configuration
The first step is to create an API configuration using New() or MustNew():
import "rivaas.dev/openapi"
// With error handling
api, err := openapi.New(
openapi.WithTitle("My API", "1.0.0"),
openapi.WithInfoDescription("API description"),
)
if err != nil {
log.Fatal(err)
}
// Without error handling (panics on error)
api := openapi.MustNew(
openapi.WithTitle("My API", "1.0.0"),
openapi.WithInfoDescription("API description"),
)
The MustNew() function is convenient for initialization code. Use it where panicking on error is acceptable.
Generating Specifications
Use api.Generate() with a context and variadic operation arguments:
result, err := api.Generate(context.Background(),
openapi.GET("/users",
openapi.WithSummary("List users"),
openapi.WithResponse(200, []User{}),
),
openapi.GET("/users/:id",
openapi.WithSummary("Get user"),
openapi.WithResponse(200, User{}),
),
openapi.POST("/users",
openapi.WithSummary("Create user"),
openapi.WithRequest(CreateUserRequest{}),
openapi.WithResponse(201, User{}),
),
)
if err != nil {
log.Fatal(err)
}
The Result Object
The Generate() method returns a Result object containing:
JSON- The OpenAPI specification as JSON bytes.YAML- The OpenAPI specification as YAML bytes.Warnings- Any generation warnings. See Diagnostics for details.
// Use the JSON specification
fmt.Println(string(result.JSON))
// Or use the YAML specification
fmt.Println(string(result.YAML))
// Check for warnings
if len(result.Warnings) > 0 {
fmt.Printf("Generated with %d warnings\n", len(result.Warnings))
}
Defining Operations
Operations are defined using HTTP method constructors:
openapi.GET("/path", options...)
openapi.POST("/path", options...)
openapi.PUT("/path", options...)
openapi.PATCH("/path", options...)
openapi.DELETE("/path", options...)
openapi.HEAD("/path", options...)
openapi.OPTIONS("/path", options...)
openapi.TRACE("/path", options...)
Each constructor takes a path and optional operation options.
Path Parameters
Use colon syntax for path parameters:
openapi.GET("/users/:id",
openapi.WithSummary("Get user by ID"),
openapi.WithResponse(200, User{}),
)
openapi.GET("/orgs/:orgId/users/:userId",
openapi.WithSummary("Get user in organization"),
openapi.WithResponse(200, User{}),
)
Path parameters are automatically discovered and marked as required.
Request and Response Types
Define request and response types using Go structs:
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
// Use in operations
openapi.POST("/users",
openapi.WithRequest(CreateUserRequest{}),
openapi.WithResponse(201, User{}),
)
The package automatically converts Go types to OpenAPI schemas.
Multiple Response Types
Operations can have multiple response types for different status codes:
type ErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
}
openapi.GET("/users/:id",
openapi.WithSummary("Get user"),
openapi.WithResponse(200, User{}),
openapi.WithResponse(404, ErrorResponse{}),
openapi.WithResponse(500, ErrorResponse{}),
)
Empty Responses
For responses with no body, use nil:
openapi.DELETE("/users/:id",
openapi.WithSummary("Delete user"),
openapi.WithResponse(204, nil),
)
Complete Example
Here’s a complete example putting it all together:
package main
import (
"context"
"fmt"
"log"
"os"
"rivaas.dev/openapi"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
type ErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
}
func main() {
api := openapi.MustNew(
openapi.WithTitle("User API", "1.0.0"),
openapi.WithInfoDescription("API for managing users"),
openapi.WithServer("http://localhost:8080", "Local development"),
)
result, err := api.Generate(context.Background(),
openapi.GET("/users",
openapi.WithSummary("List users"),
openapi.WithResponse(200, []User{}),
),
openapi.GET("/users/:id",
openapi.WithSummary("Get user"),
openapi.WithResponse(200, User{}),
openapi.WithResponse(404, ErrorResponse{}),
),
openapi.POST("/users",
openapi.WithSummary("Create user"),
openapi.WithRequest(CreateUserRequest{}),
openapi.WithResponse(201, User{}),
openapi.WithResponse(400, ErrorResponse{}),
),
openapi.DELETE("/users/:id",
openapi.WithSummary("Delete user"),
openapi.WithResponse(204, nil),
),
)
if err != nil {
log.Fatal(err)
}
// Write to file
if err := os.WriteFile("openapi.json", result.JSON, 0644); err != nil {
log.Fatal(err)
}
fmt.Println("OpenAPI specification written to openapi.json")
}
Next Steps
- Learn about Configuration to customize your API settings
- Explore Operations for advanced operation definitions
- See Auto-Discovery to learn about automatic parameter discovery
- Check Security to add authentication schemes
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.