swagger

package module
v1.2.3 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2025 License: Apache-2.0 Imports: 19 Imported by: 0

README

Swagger Plugin for Lynx Framework

A secure and feature-rich Swagger/OpenAPI documentation generator and UI server for the Lynx microservice framework.

⚠️ SECURITY WARNING

This plugin is designed for development and testing environments only. It will automatically disable itself in production environments for security reasons.

Features

  • Automatic API documentation generation from Go code annotations
  • Interactive Swagger UI for API exploration and testing
  • Real-time documentation updates with file watching
  • Secure by default with environment-based restrictions
  • Path traversal protection and file access validation
  • XSS protection with HTML escaping
  • Secure HTTP headers and CORS configuration
  • Environment-aware - automatically disabled in production

Security Features

🔒 Environment Restrictions
  • Automatically disabled in production environments
  • Configurable allowed environments (development, testing only)
  • Environment variable detection (ENV, GO_ENV, APP_ENV)
🛡️ Path Security
  • Prevents path traversal attacks
  • Restricts file scanning to safe directories
  • Validates scan directories against current working directory
  • File size limits and type restrictions
🌐 HTTP Security
  • Secure HTTP server configuration with timeouts
  • Security headers (X-Frame-Options, X-XSS-Protection, etc.)
  • Content Security Policy (CSP)
  • Restricted CORS policy (localhost only by default)
📝 Input Validation
  • HTML escaping to prevent XSS attacks
  • Safe annotation parsing without regex injection
  • Input sanitization and validation

Installation

go get github.com/go-lynx/lynx/plugins/swagger

Quick Start

1. Import the plugin
import _ "github.com/go-lynx/lynx/plugins/swagger"
2. Basic configuration
lynx:
  swagger:
    enabled: true
    security:
      environment: "development"
    ui:
      enabled: true
      port: 8081
      path: "/swagger"
    gen:
      enabled: true
      scan_dirs: ["./app"]
      output_path: "./docs/swagger.json"
3. Add annotations to your code
// @title My API
// @version 1.0
// @description API documentation

// @Router /users [get]
// @Summary Get users
// @Description Retrieve list of users
// @Param page query int false "Page number"
// @Success 200 {object} []User
func GetUsers(w http.ResponseWriter, r *http.Request) {
    // Your handler code
}

Configuration

Security Configuration
security:
  # Environment detection
  environment: "development"  # Auto-detected from ENV vars
  
  # Allowed environments (Swagger will only run in these)
  allowed_environments:
    - "development"
    - "testing"
  
  # Automatically disable in production
  disable_in_production: true
  
  # Trusted origins for CORS
  trusted_origins:
    - "http://localhost:8080"
    - "http://localhost:8081"
  
  # Require authentication (optional)
  require_auth: false
UI Configuration
ui:
  enabled: true
  port: 8081                    # Must be >= 1024
  path: "/swagger"
  title: "API Documentation"
  deep_linking: true
  display_request_duration: true
  doc_expansion: "list"
  default_models_expand_depth: 1
Generator Configuration
gen:
  enabled: true
  
  # Safe scan directories (within current working directory only)
  scan_dirs:
    - "./app/controllers"
    - "./app/handlers"
  
  # Exclude directories
  exclude_dirs:
    - "./vendor"
    - "./test"
    - "./.git"
  
  output_path: "./docs/swagger.json"
  watch_enabled: true
  watch_interval: 5s
  gen_on_startup: true

Environment Variables

The plugin automatically detects the environment from these variables:

export ENV=development          # Primary environment variable
export GO_ENV=development       # Go-specific environment
export APP_ENV=development      # Application-specific environment

Production Deployment

Option 1: Explicit Disable
lynx:
  swagger:
    enabled: false
Option 2: Environment-Based Disable
export ENV=production

The plugin will automatically detect the production environment and disable itself.

Option 3: Security Configuration
lynx:
  swagger:
    enabled: true
    security:
      environment: "production"
      disable_in_production: true  # Will disable automatically

Security Best Practices

1. Environment Isolation
  • Never run Swagger in production
  • Use separate configurations for different environments
  • Leverage environment variables for configuration
2. Network Security
  • Bind to localhost only in development
  • Use non-privileged ports (>= 1024)
  • Restrict CORS to trusted origins only
3. File Access Control
  • Limit scan directories to application code only
  • Never scan system directories (/etc, /var, etc.)
  • Validate all file paths before access
4. Input Validation
  • Always escape user input in HTML generation
  • Validate configuration parameters
  • Use safe parsing methods

Troubleshooting

Plugin Won't Start

Error: "swagger plugin is not allowed in environment: production"

Solution: This is expected behavior. Swagger is automatically disabled in production for security.

Permission Denied

Error: "scanning directory /etc is not allowed for security reasons"

Solution: Only scan directories within your application. Never scan system directories.

Port Already in Use

Error: "Failed to start Swagger UI server: address already in use"

Solution: Change the port in configuration or stop the conflicting service.

Examples

See the example/ directory for complete working examples:

  • full_example.go - Complete API with annotations
  • swagger-secure.yml - Secure configuration example

Contributing

When contributing to this plugin:

  1. Security First: Always consider security implications
  2. Environment Awareness: Ensure changes respect environment restrictions
  3. Input Validation: Validate and sanitize all inputs
  4. Testing: Test security features thoroughly

License

Apache 2.0 License - see LICENSE file for details.

Security Reporting

If you discover a security vulnerability, please report it privately to the maintainers before public disclosure.

Documentation

Index

Constants

View Source
const (
	EnvDevelopment = "development"
	EnvTesting     = "testing"
	EnvStaging     = "staging"
	EnvProduction  = "production"
)

Environment types

Variables

This section is empty.

Functions

func GenerateSwaggerUIHTML

func GenerateSwaggerUIHTML(specURL, title string) string

GenerateSwaggerUIHTML generates Swagger UI HTML (kept for backward compatibility) Deprecated: Use ui.Handler instead

Types

type AnnotationParser

type AnnotationParser struct {
	// contains filtered or unexported fields
}

AnnotationParser annotation parser with memory management

func NewAnnotationParser

func NewAnnotationParser(swagger *spec.Swagger, allowedDirs []string) *AnnotationParser

NewAnnotationParser creates an annotation parser

func (*AnnotationParser) BuildSwagger

func (p *AnnotationParser) BuildSwagger() error

BuildSwagger builds Swagger specification

func (*AnnotationParser) ClearCache

func (p *AnnotationParser) ClearCache()

ClearCache clears all caches and resets statistics

func (*AnnotationParser) GetErrorSummary

func (p *AnnotationParser) GetErrorSummary() map[string]int

GetErrorSummary returns a summary of parsing errors

func (*AnnotationParser) GetMemoryStats

func (p *AnnotationParser) GetMemoryStats() map[string]interface{}

GetMemoryStats returns memory usage statistics

func (*AnnotationParser) GetStats

func (p *AnnotationParser) GetStats() *ParseStats

GetStats returns parsing statistics

func (*AnnotationParser) OptimizeMemory

func (p *AnnotationParser) OptimizeMemory()

OptimizeMemory optimizes memory usage

func (*AnnotationParser) ParseFile

func (p *AnnotationParser) ParseFile(filename string) error

ParseFile parses a file with comprehensive error handling

func (*AnnotationParser) ScanDirectory

func (p *AnnotationParser) ScanDirectory(dir string) error

ScanDirectory scans directory

type Field

type Field struct {
	Name     string
	Type     string
	Tag      string
	Required bool
	Doc      string
}

Field field information

type FileWatcher

type FileWatcher struct {
	// contains filtered or unexported fields
}

FileWatcher enhanced file monitoring

func (*FileWatcher) GetStats

func (w *FileWatcher) GetStats() map[string]interface{}

GetStats returns file watcher statistics

func (*FileWatcher) IsHealthy

func (w *FileWatcher) IsHealthy() bool

IsHealthy returns the health status of the file watcher

type FileWatcherConfig

type FileWatcherConfig struct {
	Enabled       bool          `json:"enabled" yaml:"enabled"`
	Interval      time.Duration `json:"interval" yaml:"interval"`
	DebounceDelay time.Duration `json:"debounce_delay" yaml:"debounce_delay"`
	MaxRetries    int           `json:"max_retries" yaml:"max_retries"`
	RetryDelay    time.Duration `json:"retry_delay" yaml:"retry_delay"`
	BatchSize     int           `json:"batch_size" yaml:"batch_size"`
	HealthCheck   bool          `json:"health_check" yaml:"health_check"`
}

FileWatcherConfig configuration for file watching

type GenConfig

type GenConfig struct {
	Enabled     bool              `json:"enabled" yaml:"enabled"`
	ScanDirs    []string          `json:"scan_dirs" yaml:"scan_dirs"`
	OutputPath  string            `json:"output_path" yaml:"output_path"`
	WatchFiles  bool              `json:"watch_files" yaml:"watch_files"`
	FileWatcher FileWatcherConfig `json:"file_watcher" yaml:"file_watcher"`
}

GenConfig generator configuration

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator Swagger documentation generator

type HeaderInfo

type HeaderInfo struct {
	Type        string
	Format      string
	Description string
}

HeaderInfo response header information

type InfoConfig

type InfoConfig struct {
	Title          string `json:"title" yaml:"title"`
	Description    string `json:"description" yaml:"description"`
	Version        string `json:"version" yaml:"version"`
	TermsOfService string `json:"termsOfService" yaml:"termsOfService"`
	Contact        struct {
		Name  string `json:"name" yaml:"name"`
		Email string `json:"email" yaml:"email"`
		URL   string `json:"url" yaml:"url"`
	} `json:"contact" yaml:"contact"`
	License struct {
		Name string `json:"name" yaml:"name"`
		URL  string `json:"url" yaml:"url"`
	} `json:"license" yaml:"license"`
}

InfoConfig API basic information

type ModelInfo

type ModelInfo struct {
	Name        string
	Description string
	Properties  map[string]PropertyInfo
	Required    []string
}

ModelInfo model information

type Package

type Package struct {
	Name    string
	Structs map[string]*Struct
}

Package package information

type ParamInfo

type ParamInfo struct {
	Name        string
	In          string // path, query, header, body, formData
	Type        string
	Format      string
	Required    bool
	Description string
	Default     interface{}
	Example     interface{}
}

ParamInfo parameter information

type Parameter

type Parameter struct {
	Name        string
	In          string // path, query, header, body
	Type        string
	Required    bool
	Description string
	Example     interface{}
}

Parameter parameter information

type ParseError

type ParseError struct {
	File    string
	Line    int
	Message string
	Type    string
	Time    time.Time
}

ParseError detailed error information

type ParseStats

type ParseStats struct {
	TotalFiles   int
	SuccessFiles int
	FailedFiles  int
	TotalLines   int
	ParsedRoutes int
	ParsedModels int
	Errors       []ParseError
	StartTime    time.Time
	EndTime      time.Time
}

ParseStats statistics for parsing operations

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser code parser

type PlugSwagger

type PlugSwagger struct {
	*plugins.BasePlugin
	// contains filtered or unexported fields
}

PlugSwagger Swagger plugin

func NewSwaggerPlugin

func NewSwaggerPlugin() *PlugSwagger

NewSwaggerPlugin creates a Swagger plugin

func (*PlugSwagger) AddDefinition

func (p *PlugSwagger) AddDefinition(name string, schema spec.Schema)

AddDefinition adds definition

func (*PlugSwagger) AddPath

func (p *PlugSwagger) AddPath(path string, item spec.PathItem)

AddPath adds path

func (*PlugSwagger) CheckHealth

func (p *PlugSwagger) CheckHealth() error

CheckHealth health check

func (*PlugSwagger) CleanupTasks

func (p *PlugSwagger) CleanupTasks() error

CleanupTasks cleanup tasks

func (*PlugSwagger) GetSwagger

func (p *PlugSwagger) GetSwagger() *spec.Swagger

GetSwagger gets Swagger specification

func (*PlugSwagger) Health

func (p *PlugSwagger) Health() error

Health health check

func (*PlugSwagger) InitializeResources

func (p *PlugSwagger) InitializeResources(rt plugins.Runtime) error

InitializeResources initializes resources

func (*PlugSwagger) SetDefaultValues

func (p *PlugSwagger) SetDefaultValues()

SetDefaultValues sets default values for configuration

func (*PlugSwagger) StartupTasks

func (p *PlugSwagger) StartupTasks() error

StartupTasks startup tasks

func (*PlugSwagger) UpdateSwagger

func (p *PlugSwagger) UpdateSwagger(swagger *spec.Swagger)

UpdateSwagger updates Swagger specification

type PropertyInfo

type PropertyInfo struct {
	Type        string
	Format      string
	Description string
	Example     interface{}
	Enum        []interface{}
	Minimum     *float64
	Maximum     *float64
	MinLength   *int64
	MaxLength   *int64
	Pattern     string
}

PropertyInfo property information

type Response

type Response struct {
	Description string
	Schema      interface{}
	Examples    map[string]interface{}
}

Response response information

type ResponseInfo

type ResponseInfo struct {
	Description string
	Schema      *SchemaInfo
	Headers     map[string]HeaderInfo
}

ResponseInfo response information

type Route

type Route struct {
	Method      string
	Path        string
	Handler     string
	Summary     string
	Description string
	Tags        []string
	Parameters  []Parameter
	Responses   map[string]Response
}

Route route information

type RouteInfo

type RouteInfo struct {
	Method      string
	Path        string
	Summary     string
	Description string
	Tags        []string
	Params      []ParamInfo
	Responses   map[int]ResponseInfo
	Security    []map[string][]string
}

RouteInfo route information

type SchemaInfo

type SchemaInfo struct {
	Type       string
	Format     string
	Ref        string
	Properties map[string]*SchemaInfo
	Items      *SchemaInfo
	Required   []string
}

SchemaInfo schema information

type SecurityConfig

type SecurityConfig struct {
	Environment    string   `json:"environment" yaml:"environment"`
	AllowedEnvs    []string `json:"allowed_environments" yaml:"allowed_environments"`
	DisableInProd  bool     `json:"disable_in_production" yaml:"disable_in_production"`
	TrustedOrigins []string `json:"trusted_origins" yaml:"trusted_origins"`
	RequireAuth    bool     `json:"require_auth" yaml:"require_auth"`
}

SecurityConfig security configuration

type StringBuilderPool

type StringBuilderPool struct {
	// contains filtered or unexported fields
}

StringBuilderPool string builder object pool

func NewStringBuilderPool

func NewStringBuilderPool(size int) *StringBuilderPool

NewStringBuilderPool creates a new string builder pool

func (*StringBuilderPool) Get

func (p *StringBuilderPool) Get() *strings.Builder

Get gets a string builder from pool

func (*StringBuilderPool) Put

func (p *StringBuilderPool) Put(sb *strings.Builder)

Put returns a string builder to pool

type Struct

type Struct struct {
	Name   string
	Fields []Field
	Doc    string
}

Struct struct information

type SwaggerConfig

type SwaggerConfig struct {
	Enabled  bool           `json:"enabled" yaml:"enabled"`
	Info     InfoConfig     `json:"info" yaml:"info"`
	UI       UIConfig       `json:"ui" yaml:"ui"`
	Gen      GenConfig      `json:"generator" yaml:"generator"`
	Security SecurityConfig `json:"security" yaml:"security"`
}

SwaggerConfig plugin configuration

type SwaggerUIServer

type SwaggerUIServer struct {
	// contains filtered or unexported fields
}

SwaggerUIServer Swagger UI server

func NewSwaggerUIServer

func NewSwaggerUIServer(port int, path, specURL, title string) *SwaggerUIServer

NewSwaggerUIServer creates a Swagger UI server

func (*SwaggerUIServer) Start

func (s *SwaggerUIServer) Start() error

Start starts the UI server

func (*SwaggerUIServer) Stop

func (s *SwaggerUIServer) Stop() error

Stop stops the UI server

type UIConfig

type UIConfig struct {
	Path                     string `json:"path" yaml:"path"`
	Enabled                  bool   `json:"enabled" yaml:"enabled"`
	DeepLinking              bool   `json:"deepLinking" yaml:"deepLinking"`
	DisplayRequestDuration   bool   `json:"displayRequestDuration" yaml:"displayRequestDuration"`
	DocExpansion             string `json:"docExpansion" yaml:"docExpansion"`
	DefaultModelsExpandDepth int    `json:"defaultModelsExpandDepth" yaml:"defaultModelsExpandDepth"`
	Port                     int    `json:"port" yaml:"port"`
}

UIConfig UI configuration

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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