Files
Fabric/internal/server/serve.go
Kayvan Sylvan c06c94f8b8 # CHANGES
- Add Swagger UI at `/swagger/index.html` endpoint
- Generate OpenAPI spec files (JSON and YAML)
- Document chat, patterns, and models endpoints
- Update contributing guide with Swagger annotation instructions
- Add swaggo dependencies to project
- Configure authentication bypass for Swagger documentation
- Add custom YAML handler for OpenAPI spec
- Update REST API documentation with Swagger links
- Add dictionary entries for new tools
2025-12-18 07:12:08 -08:00

87 lines
2.4 KiB
Go

package restapi
import (
"log/slog"
"net/http"
"os"
"path/filepath"
"github.com/danielmiessler/fabric/internal/core"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "github.com/danielmiessler/fabric/docs" // swagger docs
)
// @title Fabric REST API
// @version 1.0
// @description REST API for Fabric AI augmentation framework. Provides endpoints for chat completions, pattern management, contexts, sessions, and more.
// @contact.name Fabric Support
// @contact.url https://github.com/danielmiessler/fabric
// @license.name MIT
// @license.url https://opensource.org/licenses/MIT
// @host localhost:8080
// @BasePath /
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key
func Serve(registry *core.PluginRegistry, address string, apiKey string) (err error) {
r := gin.New()
// Middleware
r.Use(gin.Logger())
r.Use(gin.Recovery())
if apiKey != "" {
r.Use(APIKeyMiddleware(apiKey))
} else {
slog.Warn("Starting REST API server without API key authentication. This may pose security risks.")
}
// Swagger UI and documentation endpoint with custom YAML handler
r.GET("/swagger/*any", func(c *gin.Context) {
// Check if request is for swagger.yaml
if c.Param("any") == "/swagger.yaml" {
// Try to find swagger.yaml relative to current directory or executable
yamlPath := "docs/swagger.yaml"
if _, err := os.Stat(yamlPath); os.IsNotExist(err) {
// Try relative to executable
if exePath, err := os.Executable(); err == nil {
yamlPath = filepath.Join(filepath.Dir(exePath), "docs", "swagger.yaml")
}
}
if _, err := os.Stat(yamlPath); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "swagger.yaml not found - generate it with: swag init -g internal/server/serve.go -o docs"})
return
}
c.File(yamlPath)
return
}
// For all other swagger paths, use the default handler
ginSwagger.WrapHandler(swaggerFiles.Handler)(c)
})
// Register routes
fabricDb := registry.Db
NewPatternsHandler(r, fabricDb.Patterns)
NewContextsHandler(r, fabricDb.Contexts)
NewSessionsHandler(r, fabricDb.Sessions)
NewChatHandler(r, registry, fabricDb)
NewYouTubeHandler(r, registry)
NewConfigHandler(r, fabricDb)
NewModelsHandler(r, registry.VendorManager)
NewStrategiesHandler(r)
// Start server
err = r.Run(address)
if err != nil {
return err
}
return
}