Replace the hardcoded Swagger 2.0 JSON template with SpecBuilder-backed OpenAPI 3.1 generation. The swagger spec is now built lazily from registered RouteGroups (including DescribableGroup and ToolBridge endpoints) and cached via sync.Once. Uses unique swag instance names to avoid global registry collisions in tests. Co-Authored-By: Virgil <virgil@lethean.io> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
55 lines
1.4 KiB
Go
55 lines
1.4 KiB
Go
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
swaggerFiles "github.com/swaggo/files"
|
|
ginSwagger "github.com/swaggo/gin-swagger"
|
|
"github.com/swaggo/swag"
|
|
)
|
|
|
|
// swaggerSeq provides unique instance names so multiple Engine instances
|
|
// (common in tests) do not collide in the global swag registry.
|
|
var swaggerSeq atomic.Uint64
|
|
|
|
// swaggerSpec wraps SpecBuilder to satisfy the swag.Spec interface.
|
|
// The spec is built once on first access and cached.
|
|
type swaggerSpec struct {
|
|
builder *SpecBuilder
|
|
groups []RouteGroup
|
|
once sync.Once
|
|
doc string
|
|
}
|
|
|
|
// ReadDoc returns the OpenAPI 3.1 JSON document for this spec.
|
|
func (s *swaggerSpec) ReadDoc() string {
|
|
s.once.Do(func() {
|
|
data, err := s.builder.Build(s.groups)
|
|
if err != nil {
|
|
s.doc = `{"openapi":"3.1.0","info":{"title":"error","version":"0.0.0"},"paths":{}}`
|
|
return
|
|
}
|
|
s.doc = string(data)
|
|
})
|
|
return s.doc
|
|
}
|
|
|
|
// registerSwagger mounts the Swagger UI and doc.json endpoint.
|
|
func registerSwagger(g *gin.Engine, title, description, version string, groups []RouteGroup) {
|
|
spec := &swaggerSpec{
|
|
builder: &SpecBuilder{
|
|
Title: title,
|
|
Description: description,
|
|
Version: version,
|
|
},
|
|
groups: groups,
|
|
}
|
|
name := fmt.Sprintf("swagger_%d", swaggerSeq.Add(1))
|
|
swag.Register(name, spec)
|
|
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.NewHandler(), ginSwagger.InstanceName(name)))
|
|
}
|