Document a REST API with an OpenAPI 3.0 specification.
- Code, not configuration.
- No magic comments, tags, or decorators.
- Use with or without a Go web framework.
- Populates schema automatically using reflection.
Why would I want to use this?
- Add OpenAPI documentation to an API.
- Create a
swagger.jsonorswagger.yamlfile.
- Create a
- Serve the Swagger UI to customers.
Examples
See the ./examples directory for complete examples.
Create an OpenAPI 3.0 (swagger) file
// Configure the models. api := rest.NewAPI("messages") api.StripPkgPaths = []string{"github.com/a-h/rest/example", "github.com/a-h/respond"} api.RegisterModel(rest.ModelOf[respond.Error](), rest.WithDescription("Standard JSON error"), func(s *openapi3.Schema) { status := s.Properties["statusCode"] status.Value.WithMin(100).WithMax(600) }) api.Get("/topic/{id}"). HasPathParameter("id", rest.PathParam{ Description: "id of the topic", Regexp: `\d+`, }). HasResponseModel(http.StatusOK, rest.ModelOf[models.Topic]()). HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()) // Create the specification. spec, err := api.Spec() if err != nil { log.Fatalf("failed to create spec: %v", err) } // Write to stdout. enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") enc.Encode(spec)
Serve API documentation alongside your API
// Create routes. router := http.NewServeMux() router.Handle("/topics", &get.Handler{}) router.Handle("/topic", &post.Handler{}) api := rest.NewAPI("messages") api.StripPkgPaths = []string{"github.com/a-h/rest/example", "github.com/a-h/respond"} // Register the error type with customisations. api.RegisterModel(rest.ModelOf[respond.Error](), rest.WithDescription("Standard JSON error"), func(s *openapi3.Schema) { status := s.Properties["statusCode"] status.Value.WithMin(100).WithMax(600) }) api.Get("/topics"). HasResponseModel(http.StatusOK, rest.ModelOf[get.TopicsGetResponse]()). HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()) api.Post("/topic"). HasRequestModel(rest.ModelOf[post.TopicPostRequest]()). HasResponseModel(http.StatusOK, rest.ModelOf[post.TopicPostResponse]()). HasResponseModel(http.StatusInternalServerError, rest.ModelOf[respond.Error]()) // Create the spec. spec, err := api.Spec() if err != nil { log.Fatalf("failed to create spec: %v", err) } // Apply any global customisation. spec.Info.Version = "v1.0.0." spec.Info.Description = "Messages API" // Attach the Swagger UI handler to your router. ui, err := swaggerui.New(spec) if err != nil { log.Fatalf("failed to create swagger UI handler: %v", err) } router.Handle("/swagger-ui", ui) router.Handle("/swagger-ui/", ui) // And start listening. fmt.Println("Listening on :8080...") fmt.Println("Visit http://localhost:8080/swagger-ui to see API definitions") fmt.Println("Listening on :8080...") http.ListenAndServe(":8080", router)
Tasks
test
run-example
Dir: ./examples/stdlib