muxopenapi

package module
v0.3.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2025 License: MIT Imports: 7 Imported by: 0

README

muxopenapi

Go Reference Go Report Card

A lightweight adapter for the gorilla/mux package that automatically generates OpenAPI 3.x specifications from your routes using oaswrap/spec.

Features

  • ⚡ Seamless Integration — Works with your existing gorilla/mux routes and handlers
  • 📝 Automatic Documentation — Generate OpenAPI specs from route definitions and struct tags
  • 🎯 Type Safety — Full Go type safety for OpenAPI configuration
  • 🔧 Multiple UI Options — Swagger UI, Stoplight Elements, ReDoc, Scalar or RapiDoc served automatically at /docs
  • 📄 YAML Export — OpenAPI spec available at /docs/openapi.yaml
  • 🚀 Zero Overhead — Minimal performance impact on your API

Installation

go get github.com/oaswrap/spec/adapter/muxopenapi

Quick Start

package main

import (
	"encoding/json"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/oaswrap/spec/adapter/muxopenapi"
	"github.com/oaswrap/spec/option"
)

func main() {
	mux := mux.NewRouter()
	r := muxopenapi.NewRouter(mux,
		option.WithTitle("My API"),
		option.WithVersion("1.0.0"),
		option.WithSecurity("bearerAuth", option.SecurityHTTPBearer("Bearer")),
	)

	api := r.PathPrefix("/api").Subrouter()
	v1 := api.PathPrefix("/v1").Subrouter()

	v1.HandleFunc("/login", LoginHandler).Methods("POST").With(
		option.Summary("User Login"),
		option.Request(new(LoginRequest)),
		option.Response(200, new(LoginResponse)),
	)
	auth := v1.PathPrefix("/").Subrouter().With(
		option.GroupSecurity("bearerAuth"),
	)
	auth.Use(AuthMiddleware)
	auth.HandleFunc("/users/{id}", GetUserHandler).Methods("GET").With(
		option.Summary("Get User by ID"),
		option.Request(new(GetUserRequest)),
		option.Response(200, new(User)),
	)

	log.Printf("🚀 OpenAPI docs available at: %s", "http://localhost:3000/docs")

	// Start the server
	server := &http.Server{
		Handler:           mux,
		Addr:              ":3000",
		ReadHeaderTimeout: 5 * time.Second,
	}
	if err := server.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

type LoginRequest struct {
	Username string `json:"username" required:"true"`
	Password string `json:"password" required:"true"`
}

type LoginResponse struct {
	Token string `json:"token"`
}

type GetUserRequest struct {
	ID string `path:"id" required:"true"`
}

type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

func AuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Simulate authentication logic
		authHeader := r.Header.Get("Authorization")
		if authHeader != "" && authHeader == "Bearer example-token" {
			next.ServeHTTP(w, r)
		} else {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
		}
	})
}

func LoginHandler(w http.ResponseWriter, r *http.Request) {
	var req LoginRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request", http.StatusBadRequest)
		return
	}
	// Simulate login logic
	_ = json.NewEncoder(w).Encode(LoginResponse{Token: "example-token"})
}

func GetUserHandler(w http.ResponseWriter, r *http.Request) {
	var req GetUserRequest
	vars := mux.Vars(r)
	id := vars["id"]
	if id == "" {
		http.Error(w, "User ID is required", http.StatusBadRequest)
		return
	}
	req.ID = id
	// Simulate fetching user by ID
	user := User{ID: req.ID, Name: "John Doe"}
	_ = json.NewEncoder(w).Encode(user)
}

Documentation Features

Built-in Endpoints

When you create a muxopenapi router, the following endpoints are automatically available:

  • /docs — Interactive UI documentation
  • /docs/openapi.yaml — Raw OpenAPI specification in YAML format

If you want to disable the built-in UI, you can do so by passing option.WithDisableDocs() when creating the router:

r := muxopenapi.NewRouter(c,
    option.WithTitle("My API"),
    option.WithVersion("1.0.0"),
    option.WithDisableDocs(),
)
Supported Documentation UIs

Choose from multiple UI options, powered by oaswrap/spec-ui:

  • Stoplight Elements — Modern, clean design (default)
  • Swagger UI — Classic interface with try-it functionality
  • ReDoc — Three-panel responsive layout
  • Scalar — Beautiful and fast interface
  • RapiDoc — Highly customizable
r := muxopenapi.NewRouter(c,
	option.WithTitle("My API"),
	option.WithVersion("1.0.0"),
	option.WithScalar(), // Use Scalar as the documentation UI
)
Rich Schema Documentation

Use struct tags to generate detailed OpenAPI schemas. Note: These tags are used only for OpenAPI spec generation and documentation - they do not perform actual request validation.

type CreateProductRequest struct {
    Name        string   `json:"name" required:"true" minLength:"1" maxLength:"100"`
    Description string   `json:"description" maxLength:"500"`
    Price       float64  `json:"price" required:"true" minimum:"0" maximum:"999999.99"`
    Category    string   `json:"category" required:"true" enum:"electronics,books,clothing"`
    Tags        []string `json:"tags" maxItems:"10"`
    InStock     bool     `json:"in_stock" default:"true"`
}

For more struct tag options, see the swaggest/openapi-go.

Examples

Check out complete examples in the main repository:

Best Practices

  1. Organize with Tags — Group related operations using option.Tags()
  2. Document Everything — Use option.Summary() and option.Description() for all routes
  3. Define Error Responses — Include common error responses (400, 401, 404, 500)
  4. Use Validation Tags — Leverage struct tags for request validation documentation
  5. Security First — Define and apply appropriate security schemes
  6. Version Your API — Use route groups for API versioning (/api/v1, /api/v2)

API Reference

Contributing

We welcome contributions! Please open issues and PRs at the main oaswrap/spec repository.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Generator

type Generator interface {
	Router

	// GenerateSchema generates the OpenAPI schema for the router.
	GenerateSchema(formats ...string) ([]byte, error)

	// MarshalJSON marshals the schema to JSON.
	MarshalJSON() ([]byte, error)

	// MarshalYAML marshals the schema to YAML.
	MarshalYAML() ([]byte, error)

	// Validate validates the schema.
	Validate() error

	// WriteSchemaTo writes the schema to a file.
	WriteSchemaTo(path string) error
}

Generator is an interface that defines methods for generating OpenAPI schemas.

func NewGenerator

func NewGenerator(mux *mux.Router, opts ...option.OpenAPIOption) Generator

NewGenerator creates a new OpenAPI router with the provided mux.Router instance and options.

It initializes the OpenAPI configuration and sets up the necessary routes for serving.

func NewRouter

func NewRouter(mux *mux.Router, opts ...option.OpenAPIOption) Generator

NewRouter creates a new OpenAPI router with the provided mux.Router instance and options.

It initializes the OpenAPI configuration and sets up the necessary routes for serving.

type Route

type Route interface {
	// GetError returns an error resulted from building the route, if any.
	GetError() error

	// GetHandler returns the handler for the route, if any.
	GetHandler() http.Handler

	// GetName returns the name for the route, if any.
	GetName() string

	// Handler sets a handler for the route.
	Handler(handler http.Handler) Route

	// HandlerFunc sets a handler function for the route.
	HandlerFunc(handler func(http.ResponseWriter, *http.Request)) Route

	// Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched.
	Headers(pairs ...string) Route

	// Host adds a matcher for the URL host. It accepts a template with zero or more URL variables enclosed by {}.
	Host(host string) Route

	// Methods adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched, e.g.: "GET", "POST", "PUT".
	Methods(methods ...string) Route

	// Name sets the name for the route, used to build URLs. It is an error to call Name more than once on a route.
	Name(name string) Route

	// Path adds a matcher for the URL path. It accepts a template with zero or more URL variables enclosed by {}. The template must start with a "/".
	Path(path string) Route

	// PathPrefix adds a matcher for the URL path prefix. This matches if the given template is a prefix of the full URL path.
	PathPrefix(prefix string) Route

	// Queries adds a matcher for URL query values. It accepts a sequence of key/value pairs.
	Queries(pairs ...string) Route

	// Schemes adds a matcher for URL schemes. It accepts a sequence of schemes to be matched, e.g.: "http", "https".
	Schemes(schemes ...string) Route

	// SkipClean reports whether path cleaning is enabled for this route via Router.SkipClean.
	SkipClean() bool

	// Subrouter creates a subrouter for the route.
	Subrouter(opts ...option.GroupOption) Router

	// With applies OpenAPI operation options to this route.
	With(opts ...option.OperationOption) Route
}

Route defines the interface for a route that can handle HTTP requests.

type Router

type Router interface {
	http.Handler

	// Get returns a route registered with the given name.
	Get(name string) Route

	// GetRoute returns a route registered with the given name.
	GetRoute(name string) Route

	// Handle registers a new route with a matcher for the URL path. See Route.Path() and Route.Handler().
	Handle(path string, handler http.Handler) Route

	// HandleFunc registers a new route with a matcher for the URL path. See Route.Path() and Route.HandlerFunc().
	HandleFunc(path string, handler func(http.ResponseWriter, *http.Request)) Route

	// Headers registers a new route with a matcher for request header values. See Route.Headers().
	Headers(pairs ...string) Route

	// Host registers a new route with a matcher for the URL host. See Route.Host().
	Host(host string) Route

	// Methods registers a new route with a matcher for HTTP methods. See Route.Methods().
	Methods(methods ...string) Route

	// Name registers a new route with a name. See Route.Name().
	Name(name string) Route

	// NewRoute registers an empty route.
	NewRoute() Route

	// Path registers a new route with a matcher for the URL path. See Route.Path().
	Path(path string) Route

	// PathPrefix registers a new route with a matcher for the URL path prefix. See Route.PathPrefix().
	PathPrefix(prefix string) Route

	// Queries registers a new route with a matcher for URL query values. See Route.Queries().
	Queries(pairs ...string) Route

	// Schemes registers a new route with a matcher for URL schemes. See Route.Schemes().
	Schemes(schemes ...string) Route

	// SkipClean defines the path cleaning behaviour for new routes. The initial value is false.
	SkipClean(value bool) Router

	// StrictSlash defines the trailing slash behavior for new routes. The initial value is false.
	StrictSlash(value bool) Router

	// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
	Use(middlewares ...mux.MiddlewareFunc) Router

	// UseEncodedPath tells the router to match the encoded original path to the routes.
	UseEncodedPath() Router

	// With applies OpenAPI group options to this router.
	With(opts ...option.GroupOption) Router
}

Router is an interface that defines methods for handling HTTP routes with OpenAPI support.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL