Skip to content

adlandh/echo-oapi-middleware

Repository files navigation

Echo OpenAPI Middleware

Go Reference Go Report Card License: MIT Go Version

Echo middleware for serving OpenAPI/Swagger specifications and UI. Type-safe, zero-dependency (except for Echo and kin-openapi).

Features

Feature Description
🚀 Type-Safe Uses *openapi3.T — no runtime parsing errors
📄 YAML Auto-Serialization Specs serialized to YAML automatically
🎨 Swagger UI Built-in UI with CDN (works offline with local assets)
⚙️ Fully Configurable Custom paths for UI and spec endpoints
🛡️ Non-Mutating Original spec object is never modified
📝 HEAD Support Correct Content-Length for HEAD requests
Well Tested 100% test coverage with table-driven tests

Table of Contents

Installation

go get github.com/adlandh/echo-oapi-middleware/v2

Quick Start

Minimal Example (YAML Only)

package main

import (
    "github.com/getkin/kin-openapi/openapi3"
    "github.com/labstack/echo/v5"
    echooapimiddleware "github.com/adlandh/echo-oapi-middleware/v2"
)

func main() {
    e := echo.New()

    spec := &openapi3.T{
        OpenAPI: "3.0.3",
        Info:    &openapi3.Info{Title: "My API", Version: "1.0.0"},
        Paths:   &openapi3.Paths{},
    }

    // Serves YAML at GET /swagger.yaml
    e.Use(echooapimiddleware.SwaggerYaml(spec))

    e.GET("/api/users", func(c *echo.Context) error {
        return c.JSON(200, []string{"user1", "user2"})
    })

    e.Start(":8080")
}

With Swagger UI

func main() {
    e := echo.New()

    spec := &openapi3.T{
        OpenAPI: "3.0.3",
        Info:    &openapi3.Info{Title: "Pet Store", Version: "1.0.0"},
        Paths:   &openapi3.Paths{},
    }

    // Serves UI at GET /swagger, /swagger/, /swagger/index.html
    // Serves YAML at GET /swagger.yaml
    e.Use(echooapimiddleware.SwaggerUI(spec))

    e.Start(":8080")
}

With oapi-codegen

If you use oapi-codegen to generate your API:

import (
    "github.com/labstack/echo/v5"
    echooapimiddleware "github.com/adlandh/echo-oapi-middleware/v2"
    "your-generated-api/pkg/api"
)

func main() {
    e := echo.New()

    spec, _ := api.GetSwagger() // From generated code

    e.Use(echooapimiddleware.SwaggerUI(spec))
    // ...
}

API Reference

SwaggerYaml

Serves OpenAPI spec as YAML.

func SwaggerYaml(spec *openapi3.T) echo.MiddlewareFunc
Endpoint Method Content-Type
/swagger.yaml GET, HEAD text/yaml; charset=utf-8

SwaggerYamlWithConfig

Serves OpenAPI spec with custom configuration.

func SwaggerYamlWithConfig(spec *openapi3.T, cfg SwaggerYamlConfig) echo.MiddlewareFunc

SwaggerUI

Serves Swagger UI + YAML spec.

func SwaggerUI(spec *openapi3.T) echo.MiddlewareFunc
Endpoint Method Content-Type
/swagger GET, HEAD text/html; charset=utf-8
/swagger/ GET, HEAD text/html; charset=utf-8
/swagger/index.html GET, HEAD text/html; charset=utf-8
/swagger.yaml GET, HEAD text/yaml; charset=utf-8

SwaggerUIWithConfig

Serves Swagger UI with custom configuration.

func SwaggerUIWithConfig(spec *openapi3.T, cfg SwaggerUIConfig) echo.MiddlewareFunc

Configuration

SwaggerYamlConfig

type SwaggerYamlConfig struct {
    // Path for YAML endpoint.
    // Default: "/swagger.yaml"
    Path string

    // KeepServers preserves the servers field in output.
    // Default: false (servers are stripped for CORS compatibility)
    KeepServers bool
}

SwaggerUIConfig

type SwaggerUIConfig struct {
    // Path for Swagger UI.
    // Default: "/swagger"
    Path string

    // SpecPath for YAML endpoint.
    // Default: "/swagger.yaml"
    SpecPath string

    // KeepServers preserves the servers field in output.
    // Default: false
    KeepServers bool
}

Advanced Usage

Custom Paths

e.Use(echooapimiddleware.SwaggerUIWithConfig(spec, echooapimiddleware.SwaggerUIConfig{
    Path:     "/api/docs",      // UI at /api/docs
    SpecPath: "/api/openapi.yaml", // YAML at /api/openapi.yaml
}))

Multiple API Versions

func main() {
    e := echo.New()

    // v1 API
    e.Use(echooapimiddleware.SwaggerUIWithConfig(&openapi3.T{
        OpenAPI: "3.0.3",
        Info:    &openapi3.Info{Title: "Pet Store", Version: "1.0.0"},
        Paths:   &openapi3.Paths{},
    }, echooapimiddleware.SwaggerUIConfig{
        Path:     "/v1/docs",
        SpecPath: "/v1/openapi.yaml",
    }))

    // v2 API
    e.Use(echooapimiddleware.SwaggerUIWithConfig(&openapi3.T{
        OpenAPI: "3.0.3",
        Info:    &openapi3.Info{Title: "Pet Store", Version: "2.0.0"},
        Paths:   &openapi3.Paths{},
    }, echooapimiddleware.SwaggerUIConfig{
        Path:     "/v2/docs",
        SpecPath: "/v2/openapi.yaml",
    }))

    e.Start(":8080")
}

Preserve Servers

By default, servers are stripped from output (better CORS). To preserve:

e.Use(echooapimiddleware.SwaggerYamlWithConfig(spec, echooapimiddleware.SwaggerYamlConfig{
    KeepServers: true,
}))

Load Spec from File

import (
    "io"
    "os"
    "gopkg.in/yaml.v3"
)

func main() {
    f, _ := os.Open("openapi.yaml")
    defer f.Close()

    data, _ := io.ReadAll(f)

    var spec openapi3.T
    yaml.Unmarshal(data, &spec)

    e.Use(echooapimiddleware.SwaggerUI(&spec))
}

Important Notes

Non-Mutating

The middleware never modifies your spec object:

spec := &openapi3.T{
    OpenAPI: "3.0.3",
    Info:    &openapi3.Info{Title: "API"},
    Servers: openapi3.Servers{{URL: "https://api.example.com"}},
}

e.Use(echooapimiddleware.SwaggerYaml(spec))

// spec.Servers is STILL here - not mutated!
_ = spec.Servers // safe

Request Methods

  • GET — returns full response
  • HEAD — returns headers only (Content-Length set correctly)
  • Other methods pass through to next handler

CDN Dependencies

Swagger UI loads from unpkg CDN:

  • https://unpkg.com/swagger-ui-dist@5/swagger-ui.css
  • https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js

For offline use, you'll need to serve these assets separately or use a local copy.

Performance

Metric Value
Serialization Once at middleware creation
Request overhead ~350ns
Memory per request O(1)

Requirements

  • Go 1.25+
  • Echo v5github.com/labstack/echo/v5
  • kin-openapigithub.com/getkin/kin-openapi

License

MIT — see LICENSE file.

About

Echo OAPI Middleware is a lightweight middleware for Echo that exposes your OpenAPI/Swagger YAML at a configurable endpoint

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages