Documentation
¶
Overview ¶
Package servex provides a basic HTTP(S) server based on a net/http and gorilla/mux.
Index ¶
- Constants
- Variables
- func GetTLSConfig(cert *tls.Certificate) *tls.Config
- func MakeRawRequest(path, host string, headers map[string]string, body ...string) []byte
- func MakeRawResponse(code int, headers map[string]string, body ...string) []byte
- func Read(r *http.Request) ([]byte, error)
- func ReadAndValidate[T interface{ ... }](r *http.Request) (T, error)
- func ReadAndValidateWithLimit[T interface{ ... }](r *http.Request, maxSize int64) (T, error)
- func ReadCertificate(cert, key []byte) (tls.Certificate, error)
- func ReadCertificateFromFile(certFile, keyFile string) (tls.Certificate, error)
- func ReadFile(r *http.Request, fileKey string) ([]byte, *multipart.FileHeader, error)
- func ReadFileWithLimit(r *http.Request, fileKey string, maxMemory, maxFileSize int64) ([]byte, *multipart.FileHeader, error)
- func ReadJSON[T any](r *http.Request) (T, error)
- func ReadJSONWithLimit[T any](r *http.Request, maxSize int64) (T, error)
- func ReadWithLimit(r *http.Request, maxSize int64) ([]byte, error)
- func RegisterCORSMiddleware(router MiddlewareRouter, opts Options)
- func RegisterCSRFMiddleware(router MiddlewareRouter, cfg SecurityConfig)
- func RegisterCacheControlMiddleware(router MiddlewareRouter, cfg CacheConfig)
- func RegisterCompressionMiddleware(router MiddlewareRouter, cfg CompressionConfig)
- func RegisterCustomHeadersMiddleware(router MiddlewareRouter, customHeaders map[string]string)
- func RegisterHTTPSRedirectMiddleware(router MiddlewareRouter, cfg HTTPSRedirectConfig)
- func RegisterHeaderRemovalMiddleware(router MiddlewareRouter, headersToRemove []string)
- func RegisterLocationBasedRateLimitMiddleware(router MiddlewareRouter, locationConfigs []LocationRateLimitConfig, ...) func()
- func RegisterLoggingMiddleware(router MiddlewareRouter, logger RequestLogger, metrics Metrics, ...)
- func RegisterProxyMiddleware(router MiddlewareRouter, config ProxyConfiguration, logger ...Logger) error
- func RegisterRateLimitMiddleware(router MiddlewareRouter, cfg RateLimitConfig, auditLogger ...AuditLogger) func()
- func RegisterRecoverMiddleware(router MiddlewareRouter, logger ErrorLogger)
- func RegisterRequestSizeLimitMiddleware(router MiddlewareRouter, opts Options)
- func RegisterSecurityHeadersMiddleware(router MiddlewareRouter, cfg SecurityConfig)
- func RegisterSimpleAuthMiddleware(router MiddlewareRouter, authToken string, opts ...Options)
- func RegisterStaticFileMiddleware(router MiddlewareRouter, cfg StaticFileConfig)
- func StartServer(cfg BaseConfig, handlerSetter func(*mux.Router), opts ...Option) (shutdown func(context.Context) error, err error)
- func StartServerFromConfig(configFile string, handlerSetter func(*mux.Router)) (shutdown func() error, err error)
- func StartServerWithShutdown(ctx context.Context, cfg BaseConfig, handlerSetter func(*mux.Router), ...) error
- type AuditEvent
- type AuditEventType
- type AuditLogger
- type AuditSeverity
- type AuthConfig
- type AuthConfiguration
- type AuthDatabase
- type AuthManager
- func (h *AuthManager) CreateUser(ctx context.Context, username, password string, roles ...UserRole) error
- func (h *AuthManager) GetAllUsersHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) GetCurrentUserHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) LoginHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) LogoutHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) RefreshHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) RegisterHandler(w http.ResponseWriter, r *http.Request)
- func (h *AuthManager) RegisterRoutes(r *mux.Router)
- func (h *AuthManager) UpdateUserRoleHandler(w http.ResponseWriter, r *http.Request)
- func (m *AuthManager) WithAuth(next http.HandlerFunc, roles ...UserRole) http.HandlerFunc
- type Backend
- type BaseConfig
- type BaseRequestLogger
- type CORSConfig
- type CORSConfiguration
- type CacheConfig
- type CacheConfiguration
- type CompressionConfig
- type CompressionConfiguration
- type Config
- type Context
- func (ctx *Context) APIVersion() string
- func (ctx *Context) BadGateway(err error, msg string, fields ...any)
- func (ctx *Context) BadRequest(err error, msg string, fields ...any)
- func (ctx *Context) Body() []byte
- func (ctx *Context) ClientIP() string
- func (ctx *Context) ClientIPWithTrustedProxies(trustedProxies []string) string
- func (ctx *Context) Conflict(err error, msg string, fields ...any)
- func (ctx *Context) Cookie(key string) (*http.Cookie, error)
- func (ctx *Context) Error(err error, code int, msg string, fields ...any)
- func (ctx *Context) Forbidden(err error, msg string, fields ...any)
- func (ctx *Context) FormValue(key string) string
- func (ctx *Context) Header(key string) string
- func (ctx *Context) InternalServerError(err error, msg string, fields ...any)
- func (ctx *Context) JSON(bodyRaw any)
- func (ctx *Context) MethodNotAllowed(fields ...any)
- func (ctx *Context) NoLog()
- func (ctx *Context) NotAcceptable(err error, msg string, fields ...any)
- func (ctx *Context) NotFound(err error, msg string, fields ...any)
- func (ctx *Context) NotImplemented(err error, msg string, fields ...any)
- func (ctx *Context) ParseUnixFromQuery(key string) (time.Time, error)
- func (ctx *Context) Path(key string) string
- func (ctx *Context) PreconditionFailed(err error, msg string, fields ...any)
- func (ctx *Context) Query(key string) string
- func (ctx *Context) Read() ([]byte, error)
- func (ctx *Context) ReadAndValidate(body interface{ ... }) error
- func (ctx *Context) ReadAndValidateWithLimit(body interface{ ... }, maxSize int64) error
- func (ctx *Context) ReadFile(fileKey string) ([]byte, *multipart.FileHeader, error)
- func (ctx *Context) ReadFileWithLimit(fileKey string, maxMemory, maxFileSize int64) ([]byte, *multipart.FileHeader, error)
- func (ctx *Context) ReadJSON(body any) error
- func (ctx *Context) ReadJSONWithLimit(body any, maxSize int64) error
- func (ctx *Context) ReadWithLimit(maxSize int64) ([]byte, error)
- func (ctx *Context) Redirect(url string, code int)
- func (ctx *Context) RedirectNotModified()
- func (ctx *Context) RedirectPermanent(url string)
- func (ctx *Context) RedirectPermanentPreserveMethod(url string)
- func (ctx *Context) RedirectSeeOther(url string)
- func (ctx *Context) RedirectTemporary(url string)
- func (ctx *Context) RedirectTemporaryPreserveMethod(url string)
- func (ctx *Context) RedirectToHTTPS(permanent ...bool)
- func (ctx *Context) RedirectToHTTPSPermanent()
- func (ctx *Context) RedirectToHTTPSTemporary()
- func (ctx *Context) RemoteAddr() string
- func (ctx *Context) RequestEntityTooLarge(err error, msg string, fields ...any)
- func (ctx *Context) RequestID() string
- func (ctx *Context) Response(code int, bodyRaw ...any)
- func (ctx *Context) ResponseFile(filename string, mimeType string, body []byte)
- func (ctx *Context) ServiceUnavailable(err error, msg string, fields ...any)
- func (ctx *Context) SetContentType(mimeType string, charset ...string)
- func (ctx *Context) SetCookie(name, value string, maxAge int, secure, httpOnly bool)
- func (ctx *Context) SetDeleteCookie(name string)
- func (ctx *Context) SetHeader(key string, value ...string)
- func (ctx *Context) SetRawCookie(c *http.Cookie)
- func (ctx *Context) TooManyRequests(err error, msg string, fields ...any)
- func (ctx *Context) Unauthorized(err error, msg string, fields ...any)
- func (ctx *Context) UnprocessableEntity(err error, msg string, fields ...any)
- func (ctx *Context) UnsupportedMediaType(err error, msg string, fields ...any)
- type DefaultAuditLogger
- func (al *DefaultAuditLogger) LogAuthenticationEvent(eventType AuditEventType, r *http.Request, userID string, success bool, ...)
- func (al *DefaultAuditLogger) LogCSRFEvent(eventType AuditEventType, r *http.Request, details map[string]any)
- func (al *DefaultAuditLogger) LogFilterEvent(eventType AuditEventType, r *http.Request, ...)
- func (al *DefaultAuditLogger) LogRateLimitEvent(r *http.Request, key string, details map[string]any)
- func (al *DefaultAuditLogger) LogSecurityEvent(event AuditEvent)
- func (al *DefaultAuditLogger) LogSuspiciousActivity(r *http.Request, activityType string, details map[string]any)
- type DynamicFilterMethods
- type ErrorLogger
- type ErrorResponse
- type Filter
- func (f *Filter) AddAllowedIP(ip string) error
- func (f *Filter) AddAllowedUserAgent(userAgent string) error
- func (f *Filter) AddBlockedIP(ip string) error
- func (f *Filter) AddBlockedUserAgent(userAgent string) error
- func (f *Filter) ClearAllAllowedIPs() error
- func (f *Filter) ClearAllAllowedUserAgents() error
- func (f *Filter) ClearAllBlockedIPs() error
- func (f *Filter) ClearAllBlockedUserAgents() error
- func (f *Filter) GetAllowedIPs() []string
- func (f *Filter) GetAllowedUserAgents() []string
- func (f *Filter) GetBlockedIPs() []string
- func (f *Filter) GetBlockedUserAgents() []string
- func (f *Filter) IsIPBlocked(ip string) bool
- func (f *Filter) IsUserAgentBlocked(userAgent string) bool
- func (f *Filter) RemoveAllowedIP(ip string) error
- func (f *Filter) RemoveAllowedUserAgent(userAgent string) error
- func (f *Filter) RemoveBlockedIP(ip string) error
- func (f *Filter) RemoveBlockedUserAgent(userAgent string) error
- type FilterBlockReason
- type FilterConfig
- type FilterConfiguration
- type HTTPSRedirectConfig
- type HTTPSRedirectConfiguration
- type HealthCheckConfig
- type InitialUser
- type LoadBalancingStrategy
- type LocationFilterConfig
- type LocationRateLimitConfig
- type Logger
- type LoggingConfiguration
- type MemoryAuthDatabase
- func (db *MemoryAuthDatabase) FindAll(ctx context.Context) ([]User, error)
- func (db *MemoryAuthDatabase) FindByID(ctx context.Context, id string) (User, bool, error)
- func (db *MemoryAuthDatabase) FindByUsername(ctx context.Context, username string) (User, bool, error)
- func (db *MemoryAuthDatabase) NewUser(ctx context.Context, username string, passwordHash string, roles ...UserRole) (string, error)
- func (db *MemoryAuthDatabase) UpdateUser(ctx context.Context, id string, diff *UserDiff) error
- type Metrics
- type MiddlewareRouter
- type NoopAuditLogger
- func (nal *NoopAuditLogger) LogAuthenticationEvent(eventType AuditEventType, r *http.Request, userID string, success bool, ...)
- func (nal *NoopAuditLogger) LogCSRFEvent(eventType AuditEventType, r *http.Request, details map[string]any)
- func (nal *NoopAuditLogger) LogFilterEvent(eventType AuditEventType, r *http.Request, ...)
- func (nal *NoopAuditLogger) LogRateLimitEvent(r *http.Request, key string, details map[string]any)
- func (nal *NoopAuditLogger) LogSecurityEvent(event AuditEvent)
- func (nal *NoopAuditLogger) LogSuspiciousActivity(r *http.Request, activityType string, details map[string]any)
- type Option
- func APIServerPreset() []Option
- func DevelopmentPreset() []Option
- func HighSecurityPreset(cert tls.Certificate) []Option
- func MergePresets(presets ...[]Option) []Option
- func MergeWithPreset(preset []Option, opts ...Option) []Option
- func MicroservicePreset() []Option
- func ProductionPreset(cert tls.Certificate) []Option
- func TLSPreset(certFile, keyFile string, cert ...tls.Certificate) []Option
- func WebAppPreset(cert tls.Certificate) []Option
- func WithAllowedHeaders(headers map[string][]string) Option
- func WithAllowedHeadersRegex(headers map[string][]string) Option
- func WithAllowedIPs(ips ...string) Option
- func WithAllowedQueryParams(params map[string][]string) Option
- func WithAllowedQueryParamsRegex(params map[string][]string) Option
- func WithAllowedUserAgents(userAgents ...string) Option
- func WithAllowedUserAgentsRegex(patterns ...string) Option
- func WithAuditLogHeaders(include bool) Option
- func WithAuditLogger(logger AuditLogger) Option
- func WithAuth(db AuthDatabase) Option
- func WithAuthBasePath(path string) Option
- func WithAuthConfig(auth AuthConfig) Option
- func WithAuthInitialRoles(roles ...UserRole) Option
- func WithAuthInitialUsers(users ...InitialUser) Option
- func WithAuthIssuer(issuer string) Option
- func WithAuthKey(accessKey, refreshKey string) Option
- func WithAuthMemoryDatabase() Option
- func WithAuthNotRegisterRoutes(notRegisterRoutes bool) Option
- func WithAuthRefreshTokenCookieName(name string) Option
- func WithAuthToken(t string) Option
- func WithAuthTokensDuration(accessDuration, refreshDuration time.Duration) Option
- func WithBlockedHeaders(headers map[string][]string) Option
- func WithBlockedHeadersRegex(headers map[string][]string) Option
- func WithBlockedIPs(ips ...string) Option
- func WithBlockedQueryParams(params map[string][]string) Option
- func WithBlockedQueryParamsRegex(params map[string][]string) Option
- func WithBlockedUserAgents(userAgents ...string) Option
- func WithBlockedUserAgentsRegex(patterns ...string) Option
- func WithBurstSize(burstSize int) Option
- func WithCORS() Option
- func WithCORSAllowCredentials() Option
- func WithCORSAllowHeaders(headers ...string) Option
- func WithCORSAllowMethods(methods ...string) Option
- func WithCORSAllowOrigins(origins ...string) Option
- func WithCORSConfig(cors CORSConfig) Option
- func WithCORSExcludePaths(paths ...string) Option
- func WithCORSExposeHeaders(headers ...string) Option
- func WithCORSIncludePaths(paths ...string) Option
- func WithCORSMaxAge(seconds int) Option
- func WithCSRFCookieHttpOnly(httpOnly bool) Option
- func WithCSRFCookieMaxAge(maxAge int) Option
- func WithCSRFCookieName(cookieName string) Option
- func WithCSRFCookiePath(path string) Option
- func WithCSRFCookieSameSite(sameSite string) Option
- func WithCSRFCookieSecure(secure bool) Option
- func WithCSRFErrorMessage(message string) Option
- func WithCSRFProtection() Option
- func WithCSRFSafeMethods(methods ...string) Option
- func WithCSRFTokenEndpoint(endpoint string) Option
- func WithCSRFTokenName(tokenName string) Option
- func WithCacheAPI(maxAgeSeconds int) Option
- func WithCacheConfig(cache CacheConfig) Option
- func WithCacheControl(cacheControl string) Option
- func WithCacheETag(etag string) Option
- func WithCacheETagFunc(etagFunc func(r *http.Request) string) Option
- func WithCacheExcludePaths(paths ...string) Option
- func WithCacheExpires(expires string) Option
- func WithCacheExpiresTime(expires time.Time) Option
- func WithCacheHeaders() Option
- func WithCacheIncludePaths(paths ...string) Option
- func WithCacheLastModified(lastModified string) Option
- func WithCacheLastModifiedFunc(lastModifiedFunc func(r *http.Request) time.Time) Option
- func WithCacheLastModifiedTime(lastModified time.Time) Option
- func WithCacheNoCache() Option
- func WithCacheNoStore() Option
- func WithCachePrivate(maxAgeSeconds int) Option
- func WithCachePublic(maxAgeSeconds int) Option
- func WithCacheStaticAssets(maxAgeSeconds int) Option
- func WithCacheVary(vary string) Option
- func WithCertificate(cert tls.Certificate) Option
- func WithCertificateFromFile(certFilePath, keyFilePath string) Option
- func WithCertificatePtr(cert *tls.Certificate) Option
- func WithCompression() Option
- func WithCompressionConfig(compression CompressionConfig) Option
- func WithCompressionExcludePaths(paths ...string) Option
- func WithCompressionIncludePaths(paths ...string) Option
- func WithCompressionLevel(level int) Option
- func WithCompressionMinSize(size int) Option
- func WithCompressionTypes(types ...string) Option
- func WithContentSecurityPolicy(policy string) Option
- func WithCustomHeaders(headers map[string]string) Option
- func WithDefaultAuditLogger() Option
- func WithDefaultMetrics(path ...string) Option
- func WithDisableHealthEndpoint() Option
- func WithDisableRequestLogging() Option
- func WithEnableRequestSizeLimits(enable bool) Option
- func WithFilterConfig(filter FilterConfig) Option
- func WithFilterExcludePaths(paths ...string) Option
- func WithFilterIncludePaths(paths ...string) Option
- func WithFilterMessage(message string) Option
- func WithFilterStatusCode(statusCode int) Option
- func WithFilterTrustedProxies(proxies ...string) Option
- func WithHSTSHeader(maxAge int, includeSubdomains, preload bool) Option
- func WithHTTPSRedirect() Option
- func WithHTTPSRedirectConfig(config HTTPSRedirectConfig) Option
- func WithHTTPSRedirectExcludePaths(paths ...string) Option
- func WithHTTPSRedirectIncludePaths(paths ...string) Option
- func WithHTTPSRedirectTemporary() Option
- func WithHTTPSRedirectTrustedProxies(proxies ...string) Option
- func WithHealthEndpoint() Option
- func WithHealthPath(path string) Option
- func WithIdleTimeout(tm time.Duration) Option
- func WithLogFields(fields ...string) Option
- func WithLogger(l Logger) Option
- func WithMaxFileUploadSize(size int64) Option
- func WithMaxHeaderBytes(size int) Option
- func WithMaxJSONBodySize(size int64) Option
- func WithMaxMultipartMemory(size int64) Option
- func WithMaxRequestBodySize(size int64) Option
- func WithMetrics(m Metrics) Option
- func WithMetricsAndDefault(customMetrics Metrics, path ...string) Option
- func WithMetricsDefault(path ...string) Option
- func WithNoLogClientErrors() Option
- func WithNoRequestLog() Option
- func WithProxyConfig(proxy ProxyConfiguration) Option
- func WithRPM(rpm int) Option
- func WithRPS(rps int) Option
- func WithRateLimitConfig(rateLimit RateLimitConfig) Option
- func WithRateLimitExcludePaths(paths ...string) Option
- func WithRateLimitIncludePaths(paths ...string) Option
- func WithRateLimitKeyFunc(keyFunc func(r *http.Request) string) Option
- func WithRateLimitMessage(message string) Option
- func WithRateLimitStatusCode(statusCode int) Option
- func WithRateLimitTrustedProxies(proxies ...string) Option
- func WithReadHeaderTimeout(tm time.Duration) Option
- func WithReadTimeout(tm time.Duration) Option
- func WithRemoveHeaders(headers ...string) Option
- func WithRequestLogger(r RequestLogger) Option
- func WithRequestSizeLimits() Option
- func WithRequestsPerInterval(requestsPerInterval int, interval time.Duration) Option
- func WithSPAMode(dir, indexFile string) Option
- func WithSecurityConfig(security SecurityConfig) Option
- func WithSecurityExcludePaths(paths ...string) Option
- func WithSecurityHeaders() Option
- func WithSecurityIncludePaths(paths ...string) Option
- func WithSendErrorToClient() Option
- func WithStaticFileCache(maxAge int, rules ...map[string]int) Option
- func WithStaticFileConfig(config StaticFileConfig) Option
- func WithStaticFileExclusions(paths ...string) Option
- func WithStaticFiles(dir, urlPrefix string) Option
- func WithStrictRequestSizeLimits() Option
- func WithStrictSecurityHeaders() Option
- type Options
- type ProxyConfiguration
- type ProxyRule
- type RateLimitConfig
- type RateLimitConfiguration
- type RequestLogBundle
- type RequestLogger
- type RoleContextKey
- type SecurityConfig
- type SecurityConfiguration
- type Server
- func (s *Server) AddMiddlewares(middleware ...func(http.Handler) http.Handler)
- func (s *Server) AddStaticFileRoutes(cfg StaticFileConfig) error
- func (s *Server) AuthManager() *AuthManager
- func (s *Server) C(w http.ResponseWriter, r *http.Request) *Context
- func (s *Server) CONNECT(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Connect(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) ConnectWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) DELETE(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Delete(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) DeleteWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) Filter() DynamicFilterMethods
- func (s *Server) GET(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Get(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) GetWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) H(path string, h http.Handler, methods ...string) *mux.Route
- func (s *Server) HA(path string, f http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) HEAD(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) HF(path string, f http.HandlerFunc, methods ...string) *mux.Route
- func (s *Server) HFA(path string, f http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) HTTPAddress() string
- func (s *Server) HTTPSAddress() string
- func (s *Server) Handle(path string, h http.Handler, methods ...string) *mux.Route
- func (s *Server) HandleFunc(path string, f http.HandlerFunc, methods ...string) *mux.Route
- func (s *Server) HandleFuncWithAuth(path string, f http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) HandleWithAuth(path string, h http.Handler, roles ...UserRole) *mux.Route
- func (s *Server) Head(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) HeadWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) IsAuthEnabled() bool
- func (s *Server) IsHTTP() bool
- func (s *Server) IsTLS() bool
- func (s *Server) NewContext(w http.ResponseWriter, r *http.Request) *Context
- func (s *Server) OPTIONS(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Options(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) OptionsWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) PATCH(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) POST(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) PUT(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Patch(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) PatchWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) Post(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) PostWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) Put(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) PutWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) R(path ...string) *mux.Router
- func (s *Server) RemoveBasePath() *Server
- func (s *Server) Router(path ...string) *mux.Router
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Start(httpAddr, httpsAddr string) error
- func (s *Server) StartHTTP(address string) error
- func (s *Server) StartHTTPS(address string) error
- func (s *Server) StartWithShutdown(ctx context.Context, httpAddr, httpsAddr string) error
- func (s *Server) StartWithShutdownHTTP(ctx context.Context, address string) error
- func (s *Server) StartWithShutdownHTTPS(ctx context.Context, address string) error
- func (s *Server) StartWithWaitSignals(ctx context.Context, httpAddr, httpsAddr string, signals ...os.Signal) error
- func (s *Server) StartWithWaitSignalsHTTP(ctx context.Context, address string, signals ...os.Signal) error
- func (s *Server) StartWithWaitSignalsHTTPS(ctx context.Context, address string, signals ...os.Signal) error
- func (s *Server) TRACE(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) Trace(path string, h http.HandlerFunc) *mux.Route
- func (s *Server) TraceWithAuth(path string, h http.HandlerFunc, roles ...UserRole) *mux.Route
- func (s *Server) Use(middleware ...func(http.Handler) http.Handler)
- func (s *Server) WithAuth(next http.HandlerFunc, roles ...UserRole) http.HandlerFunc
- func (s *Server) WithBasePath(path string) *Server
- type ServerConfig
- type StaticFileConfig
- type StaticFilesConfiguration
- type TrafficDumpConfig
- type User
- type UserContextKey
- type UserDiff
- type UserLoginRequest
- type UserLoginResponse
- type UserRole
- type UserUpdateRequest
Examples ¶
Constants ¶
const ( IDDBField = "id" IDDBBsonField = "_id" UsernameDBField = "username" RolesDBField = "roles" PasswordHashDBField = "password_hash" RefreshTokenHashDBField = "refresh_token_hash" RefreshTokenExpiresAtDBField = "refresh_token_expires_at" )
const ( // RequestIDLogField adds request ID to logs. RequestIDLogField = "request_id" // IPLogField adds remote IP address to logs. IPLogField = "ip" // UserAgentLogField adds client's User-Agent to logs. UserAgentLogField = "user_agent" // URLLogField adds request URL to logs. URLLogField = "url" // MethodLogField adds request method to logs like GET or POST. MethodLogField = "method" // ProtoLogField adds request protocol to logs like HTTP/1.1 or HTTP/2. ProtoLogField = "proto" // ErrorLogField adds error information to logs. ErrorLogField = "error" // ErrorMessageLogField adds error message to logs. ErrorMessageLogField = "error_message" // StatusLogField adds HTTP status code to logs. StatusLogField = "status" // DurationLogField adds request duration in milliseconds to logs. DurationLogField = "duration_ms" )
const ( // GET is the HTTP GET method. GET = http.MethodGet // HEAD is the HTTP HEAD method. HEAD = http.MethodHead // POST is the HTTP POST method. POST = http.MethodPost // PUT is the HTTP PUT method. PUT = http.MethodPut // PATCH is the HTTP PATCH method. PATCH = http.MethodPatch // DELETE is the HTTP DELETE method. DELETE = http.MethodDelete // CONNECT is the HTTP CONNECT method. CONNECT = http.MethodConnect // OPTIONS is the HTTP OPTIONS method. OPTIONS = http.MethodOptions // TRACE is the HTTP TRACE method. TRACE = http.MethodTrace )
HTTP method shortcuts HTTP methods shortcuts
const ( // MIMETypeAAC defines the MIME type for AAC audio. MIMETypeAAC = "audio/aac" // MIMETypeABW defines the MIME type for AbiWord documents. MIMETypeABW = "application/x-abiword" // MIMETypeAPNG defines the MIME type for Animated Portable Network Graphics (APNG). MIMETypeAPNG = "image/apng" // MIMETypeARC defines the MIME type for Archive documents (multiple files embedded). MIMETypeARC = "application/x-freearc" // MIMETypeAVIF defines the MIME type for AVIF images. MIMETypeAVIF = "image/avif" // MIMETypeAVI defines the MIME type for AVI (Audio Video Interleave). MIMETypeAVI = "video/x-msvideo" // MIMETypeAZW defines the MIME type for Amazon Kindle eBook format. MIMETypeAZW = "application/vnd.amazon.ebook" // MIMETypeBIN defines the MIME type for any kind of binary data. MIMETypeBIN = "application/octet-stream" // MIMETypeBMP defines the MIME type for Windows OS/2 Bitmap Graphics. MIMETypeBMP = "image/bmp" // MIMETypeBZ defines the MIME type for BZip archives. MIMETypeBZ = "application/x-bzip" // MIMETypeBZ2 defines the MIME type for BZip2 archives. MIMETypeBZ2 = "application/x-bzip2" // MIMETypeCDA defines the MIME type for CD audio. MIMETypeCDA = "application/x-cdf" // MIMETypeCSH defines the MIME type for C-Shell scripts. MIMETypeCSH = "application/x-csh" // MIMETypeCSS defines the MIME type for Cascading Style Sheets (CSS). MIMETypeCSS = "text/css" // MIMETypeCSV defines the MIME type for Comma-separated values (CSV). MIMETypeCSV = "text/csv" // MIMETypeDOC defines the MIME type for Microsoft Word. MIMETypeDOC = "application/msword" // MIMETypeDOCX defines the MIME type for Microsoft Word (OpenXML). MIMETypeDOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" // MIMETypeEOT defines the MIME type for MS Embedded OpenType fonts. MIMETypeEOT = "application/vnd.ms-fontobject" // MIMETypeEPUB defines the MIME type for Electronic publications (EPUB). MIMETypeEPUB = "application/epub+zip" // MIMETypeGZ defines the MIME type for GZip Compressed Archives. MIMETypeGZ = "application/gzip" // MIMETypeGIF defines the MIME type for Graphics Interchange Format (GIF). MIMETypeGIF = "image/gif" // MIMETypeHTML defines the MIME type for HyperText Markup Language (HTML). MIMETypeHTML = "text/html" // MIMETypeICO defines the MIME type for Icon format. MIMETypeICO = "image/vnd.microsoft.icon" // MIMETypeICS defines the MIME type for iCalendar format. MIMETypeICS = "text/calendar" // MIMETypeJAR defines the MIME type for Java Archives (JAR). MIMETypeJAR = "application/java-archive" // MIMETypeJPEG defines the MIME type for JPEG images. MIMETypeJPEG = "image/jpeg" // MIMETypeJS defines the MIME type for JavaScript. MIMETypeJS = "text/javascript" // MIMETypeJSON defines the MIME type for JSON format. MIMETypeJSON = "application/json" // MIMETypeJSONLD defines the MIME type for JSON-LD format. MIMETypeJSONLD = "application/ld+json" // MIMETypeMIDI defines the MIME type for Musical Instrument Digital Interface (MIDI). MIMETypeMIDI = "audio/midi" // MIMETypeMJS defines the MIME type for JavaScript modules. MIMETypeMJS = "text/javascript" // MIMETypeMP3 defines the MIME type for MP3 audio. MIMETypeMP3 = "audio/mpeg" // MIMETypeMP4 defines the MIME type for MP4 video. MIMETypeMP4 = "video/mp4" // MIMETypeMPEG defines the MIME type for MPEG Video. MIMETypeMPEG = "video/mpeg" // MIMETypeMPKG defines the MIME type for Apple Installer Packages. MIMETypeMPKG = "application/vnd.apple.installer+xml" // MIMETypeODP defines the MIME type for OpenDocument presentation documents. MIMETypeODP = "application/vnd.oasis.opendocument.presentation" // MIMETypeODS defines the MIME type for OpenDocument spreadsheet documents. MIMETypeODS = "application/vnd.oasis.opendocument.spreadsheet" // MIMETypeODT defines the MIME type for OpenDocument text documents. MIMETypeODT = "application/vnd.oasis.opendocument.text" // MIMETypeOGA defines the MIME type for Ogg audio. MIMETypeOGA = "audio/ogg" // MIMETypeOGV defines the MIME type for Ogg video. MIMETypeOGV = "video/ogg" // MIMETypeOGX defines the MIME type for Ogg. MIMETypeOGX = "application/ogg" // MIMETypeOPUS defines the MIME type for Opus audio in Ogg container. MIMETypeOPUS = "audio/ogg" // MIMETypeOTF defines the MIME type for OpenType fonts. MIMETypeOTF = "font/otf" // MIMETypePNG defines the MIME type for Portable Network Graphics. MIMETypePNG = "image/png" // MIMETypePDF defines the MIME type for Adobe Portable Document Format (PDF). MIMETypePDF = "application/pdf" // MIMETypePHP defines the MIME type for Hypertext Preprocessor (Personal Home Page). MIMETypePHP = "application/x-httpd-php" // MIMETypePPT defines the MIME type for Microsoft PowerPoint. MIMETypePPT = "application/vnd.ms-powerpoint" // MIMETypePPTX defines the MIME type for Microsoft PowerPoint (OpenXML). MIMETypePPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation" // MIMETypeRAR defines the MIME type for RAR archives. MIMETypeRAR = "application/vnd.rar" // MIMETypeRTF defines the MIME type for Rich Text Format (RTF). MIMETypeRTF = "application/rtf" // MIMETypeSH defines the MIME type for Bourne shell scripts. MIMETypeSH = "application/x-sh" // MIMETypeSVG defines the MIME type for Scalable Vector Graphics (SVG). MIMETypeSVG = "image/svg+xml" // MIMETypeTAR defines the MIME type for Tape Archives (TAR). MIMETypeTAR = "application/x-tar" // MIMETypeTIFF defines the MIME type for Tagged Image File Format (TIFF). MIMETypeTIFF = "image/tiff" // MIMETypeTS defines the MIME type for MPEG transport stream. MIMETypeTS = "video/mp2t" // MIMETypeTTF defines the MIME type for TrueType Fonts. MIMETypeTTF = "font/ttf" // MIMETypeTXT defines the MIME type for Plain Text. MIMETypeTXT = "text/plain" // MIMETypeText is an alias for MIMETypeTXT. MIMETypeText = MIMETypeTXT // MIMETypePlain is an alias for MIMETypeTXT. MIMETypePlain = MIMETypeTXT // MIMETypeVSD defines the MIME type for Microsoft Visio. MIMETypeVSD = "application/vnd.visio" // MIMETypeWAV defines the MIME type for Waveform Audio Format. MIMETypeWAV = "audio/wav" // MIMETypeWEBA defines the MIME type for WEBM audio. MIMETypeWEBA = "audio/webm" // MIMETypeWEBM defines the MIME type for WEBM video. MIMETypeWEBM = "video/webm" // MIMETypeWEBP defines the MIME type for WEBP images. MIMETypeWEBP = "image/webp" // MIMETypeWOFF defines the MIME type for Web Open Font Format (WOFF). MIMETypeWOFF = "font/woff" // MIMETypeWOFF2 defines the MIME type for Web Open Font Format (WOFF2). MIMETypeWOFF2 = "font/woff2" // MIMETypeXHTML defines the MIME type for XHTML. MIMETypeXHTML = "application/xhtml+xml" // MIMETypeXLS defines the MIME type for Microsoft Excel. MIMETypeXLS = "application/vnd.ms-excel" // MIMETypeXLSX defines the MIME type for Microsoft Excel (OpenXML). MIMETypeXLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" // MIMETypeXML defines the MIME type for XML. MIMETypeXML = "application/xml" // MIMETypeXUL defines the MIME type for XUL. MIMETypeXUL = "application/vnd.mozilla.xul+xml" // MIMETypeZIP defines the MIME type for ZIP archives. MIMETypeZIP = "application/zip" // MIMEType3GP defines the MIME type for 3GPP audio/video containers. MIMEType3GP = "video/3gpp" // MIMEType3G2 defines the MIME type for 3GPP2 audio/video containers. MIMEType3G2 = "video/3gpp2" // MIMEType7Z defines the MIME type for 7-zip archives. MIMEType7Z = "application/x-7z-compressed" )
MIME type constants
Variables ¶
var ( // ListenAddressRegexp is used to match "ip:port" or ":port" strings or kuber domains with port. ListenAddressRegexp = regexp.MustCompile(`^[\w\-\/:@\.]*:[0-9]{1,5}$`) )
Functions ¶
func GetTLSConfig ¶
func GetTLSConfig(cert *tls.Certificate) *tls.Config
GetTLSConfig creates a secure TLS configuration for HTTPS servers using the provided certificate. The configuration follows security best practices and enables modern TLS features.
Security features enabled:
- TLS 1.2 minimum version (blocks older, insecure versions)
- HTTP/2 support with ALPN negotiation
- Server cipher suite preferences (server chooses best cipher)
- Only secure ECDHE cipher suites (perfect forward secrecy)
- P-256 elliptic curve preference (widely supported and secure)
Example usage:
// Load certificate
cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
// Create secure TLS config
tlsConfig := servex.GetTLSConfig(&cert)
// Use with HTTP server
server := &http.Server{
Addr: ":8443",
TLSConfig: tlsConfig,
Handler: myHandler,
}
server.ListenAndServeTLS("", "") // Cert already in TLS config
Example with servex:
cert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
server := servex.New(servex.WithCertificate(cert))
// GetTLSConfig is used internally by servex
Security considerations:
- Only allows TLS 1.2+ (blocks TLS 1.0, 1.1 which have vulnerabilities)
- Uses only ECDHE cipher suites for perfect forward secrecy
- Prefers server cipher suite selection for optimal security
- Enables HTTP/2 for better performance
Cipher suites included (in order of preference):
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
These cipher suites provide:
- ECDHE: Elliptic Curve Diffie-Hellman (perfect forward secrecy)
- AES-GCM: Authenticated encryption (confidentiality + integrity)
- SHA256/384: Secure hash algorithms
Parameters:
- cert: TLS certificate to use. If nil, returns nil (no TLS)
Returns:
- *tls.Config: Secure TLS configuration, or nil if cert is nil
Note: This configuration is suitable for production use and follows current security recommendations. It may reject very old clients that don't support TLS 1.2 or modern cipher suites.
func MakeRawRequest ¶
MakeRawRequest makes a raw HTTP request in a form of []byte.
Parameters:
- path: The path to register the route for
- host: The host to register the route for
- headers: The headers to register the route for
- body: The body to register the route for
Returns:
- []byte: The raw HTTP request
func MakeRawResponse ¶
MakeRawResponse makes a raw HTTP response in a form of []byte.
Parameters:
- code: The code to register the route for
- headers: The headers to register the route for
- body: The body to register the route for
Returns:
- []byte: The raw HTTP response
func ReadAndValidate ¶
ReadAndValidate reads a JSON from the request body to a variable of the provided type and validates it with size limits.
func ReadAndValidateWithLimit ¶
func ReadAndValidateWithLimit[T interface{ Validate() error }](r *http.Request, maxSize int64) (T, error)
ReadAndValidateWithLimit reads and validates a JSON from the request body with a specific size limit.
func ReadCertificate ¶
func ReadCertificate(cert, key []byte) (tls.Certificate, error)
ReadCertificate is a function that reads a TLS certificate from the given cert and key bytes and returns a tls.Certificate instance.
func ReadCertificateFromFile ¶
func ReadCertificateFromFile(certFile, keyFile string) (tls.Certificate, error)
ReadCertificateFromFile is a function that reads a TLS certificate from the given cert and key files and returns a tls.Certificate instance.
func ReadFileWithLimit ¶
func ReadFileWithLimit(r *http.Request, fileKey string, maxMemory, maxFileSize int64) ([]byte, *multipart.FileHeader, error)
ReadFileWithLimit reads a file from the request body with specific size limits.
func ReadJSON ¶
ReadJSON reads a JSON from the request body to a variable of the provided type with size limits.
func ReadJSONWithLimit ¶
ReadJSONWithLimit reads a JSON from the request body with a specific size limit.
func ReadWithLimit ¶
ReadWithLimit reads the request body with a specific size limit.
func RegisterCORSMiddleware ¶ added in v2.2.0
func RegisterCORSMiddleware(router MiddlewareRouter, opts Options)
RegisterCORSMiddleware registers a middleware that handles Cross-Origin Resource Sharing (CORS). It supports preflight requests, origin validation, method and header restrictions, credentials handling, and path-based filtering. If CORS is not enabled in the configuration, no middleware is registered.
func RegisterCSRFMiddleware ¶
func RegisterCSRFMiddleware(router MiddlewareRouter, cfg SecurityConfig)
RegisterCSRFMiddleware adds CSRF (Cross-Site Request Forgery) protection middleware. This middleware provides comprehensive CSRF protection for web applications.
func RegisterCacheControlMiddleware ¶
func RegisterCacheControlMiddleware(router MiddlewareRouter, cfg CacheConfig)
RegisterCacheControlMiddleware adds cache control headers to HTTP responses. It implements common HTTP caching headers to control browser and proxy caching behavior. If the config is empty or disabled, no middleware will be registered.
func RegisterCompressionMiddleware ¶ added in v2.2.0
func RegisterCompressionMiddleware(router MiddlewareRouter, cfg CompressionConfig)
RegisterCompressionMiddleware adds HTTP response compression middleware. It compresses response bodies using gzip or deflate encoding based on client Accept-Encoding headers. This can significantly reduce bandwidth usage and improve response times for text-based content.
func RegisterCustomHeadersMiddleware ¶
func RegisterCustomHeadersMiddleware(router MiddlewareRouter, customHeaders map[string]string)
RegisterCustomHeadersMiddleware adds custom headers to HTTP responses. This is separate from security headers to maintain separation of concerns.
func RegisterHTTPSRedirectMiddleware ¶ added in v2.1.0
func RegisterHTTPSRedirectMiddleware(router MiddlewareRouter, cfg HTTPSRedirectConfig)
RegisterHTTPSRedirectMiddleware adds HTTP to HTTPS redirection middleware to the router. This middleware automatically redirects all HTTP requests to their HTTPS equivalent to enforce secure connections across the entire application. If the config is disabled, no middleware will be registered.
func RegisterHeaderRemovalMiddleware ¶
func RegisterHeaderRemovalMiddleware(router MiddlewareRouter, headersToRemove []string)
RegisterHeaderRemovalMiddleware removes specified headers from HTTP responses. Headers are removed after the handler executes to ensure proper removal of headers that might be set by the handler.
func RegisterLocationBasedRateLimitMiddleware ¶
func RegisterLocationBasedRateLimitMiddleware(router MiddlewareRouter, locationConfigs []LocationRateLimitConfig, auditLogger ...AuditLogger) func()
RegisterLocationBasedRateLimitMiddleware adds location-based rate limiting middleware to the router. This allows different rate limit configurations for different URL paths. If no location configs are provided or none are enabled, no middleware will be registered. It returns a function that can be used to stop the cleanup routine.
The middleware will: 1. Check each location config in order for path pattern matches 2. Use the first matching config's rate limits 3. Fall back to no rate limiting if no patterns match
Example usage:
stop := RegisterLocationBasedRateLimitMiddleware(router, []LocationRateLimitConfig{
{
PathPatterns: []string{"/api/*"},
Config: RateLimitConfig{
Enabled: true,
RequestsPerInterval: 100,
Interval: time.Minute,
},
},
{
PathPatterns: []string{"/auth/login", "/auth/register"},
Config: RateLimitConfig{
Enabled: true,
RequestsPerInterval: 10,
Interval: time.Minute,
},
},
})
func RegisterLoggingMiddleware ¶
func RegisterLoggingMiddleware(router MiddlewareRouter, logger RequestLogger, metrics Metrics, noLogClientErrors ...bool)
RegisterLoggingMiddleware registers a middleware that logs incoming requests. It logs details such as request method, path, status code, duration, and any errors encountered during processing. It also integrates with a Metrics handler if provided. If the logger is nil, it defaults to a BaseRequestLogger using slog.Default(). Requests can be excluded from logging by calling ctx.NoLog() within the handler.
func RegisterProxyMiddleware ¶
func RegisterProxyMiddleware(router MiddlewareRouter, config ProxyConfiguration, logger ...Logger) error
RegisterProxyMiddleware registers the proxy middleware
Parameters:
- router: The router to register the middleware for
- config: The proxy configuration to register the middleware for
- logger: The logger to register the middleware for (optional)
Example:
RegisterProxyMiddleware(router, config, logger)
Returns:
- *ProxyManager: The proxy manager
func RegisterRateLimitMiddleware ¶
func RegisterRateLimitMiddleware(router MiddlewareRouter, cfg RateLimitConfig, auditLogger ...AuditLogger) func()
RegisterRateLimitMiddleware adds rate limiting middleware to the router. If the config is not enabled, no middleware will be registered. It returns a function that can be used to stop the cleanup routine.
Parameters:
- router: The router to register the middleware for
- cfg: The rate limit configuration to register the middleware for
- auditLogger: The audit logger to register the middleware for
Returns:
- func(): The function to stop the cleanup routine
func RegisterRecoverMiddleware ¶
func RegisterRecoverMiddleware(router MiddlewareRouter, logger ErrorLogger)
RegisterRecoverMiddleware registers a middleware that recovers from panics in HTTP handlers. If a panic occurs, it logs the error and stack trace using the provided logger (defaulting to slog.Default() if nil) and sends a 500 Internal Server Error response only if no response headers have been written yet.
func RegisterRequestSizeLimitMiddleware ¶
func RegisterRequestSizeLimitMiddleware(router MiddlewareRouter, opts Options)
RegisterRequestSizeLimitMiddleware registers a middleware that enforces request body size limits. This helps prevent DoS attacks by limiting the maximum size of request bodies. If request size limits are not enabled in options, no middleware is registered. Requests exceeding limits are rejected with 413 Request Entity Too Large.
func RegisterSecurityHeadersMiddleware ¶
func RegisterSecurityHeadersMiddleware(router MiddlewareRouter, cfg SecurityConfig)
RegisterSecurityHeadersMiddleware adds security headers to HTTP responses. It implements common security headers to protect against various attacks. If the config is empty or disabled, no middleware will be registered.
func RegisterSimpleAuthMiddleware ¶
func RegisterSimpleAuthMiddleware(router MiddlewareRouter, authToken string, opts ...Options)
RegisterSimpleAuthMiddleware registers a middleware for simple token-based authentication. It checks the "Authorization" header for a token matching the provided authToken. It supports both "Bearer <token>" and "<token>" formats. If the authToken is empty, no middleware is registered. If the header is missing or the token is invalid, it responds with 401 Unauthorized.
func RegisterStaticFileMiddleware ¶
func RegisterStaticFileMiddleware(router MiddlewareRouter, cfg StaticFileConfig)
RegisterStaticFileMiddleware sets up static file serving middleware based on the configuration. This should be called after all API routes are registered but before starting the server. It returns a cleanup function that should be called when shutting down.
func StartServer ¶
func StartServer(cfg BaseConfig, handlerSetter func(*mux.Router), opts ...Option) (shutdown func(context.Context) error, err error)
StartServer starts the server with the provided BaseConfig and [Option]s. It returns an error if there was an error starting either of the servers. You should provide a function that sets the handlers for the server to the router. It returns shutdown function so you should shutdown the server manually.
Example:
cfg := servex.BaseConfig{
HTTPS: ":8443",
CertFile: "cert.pem",
KeyFile: "key.pem",
}
shutdown, err := servex.StartServer(cfg, func(r *mux.Router) {
r.HandleFunc("/api/users", handleUsers)
r.HandleFunc("/api/health", handleHealth)
}, servex.WithAuthToken("secret-token"))
if err != nil {
log.Fatal(err)
}
defer shutdown(context.Background())
func StartServerFromConfig ¶
func StartServerFromConfig(configFile string, handlerSetter func(*mux.Router)) (shutdown func() error, err error)
StartServerFromConfig starts a server using configuration from a YAML file
func StartServerWithShutdown ¶
func StartServerWithShutdown(ctx context.Context, cfg BaseConfig, handlerSetter func(*mux.Router), opts ...Option) error
Start starts the server with the provided BaseConfig and [Option]s. It returns an error if there was an error starting either of the servers. You should provide a function that sets the handlers for the server to the router. It shutdowns the server when the context is closed (it starts a goroutine to check [Context.Done]).
Example:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cfg := servex.BaseConfig{
HTTPS: ":8443",
CertFile: "cert.pem",
KeyFile: "key.pem",
}
err := servex.StartServerWithShutdown(ctx, cfg, func(r *mux.Router) {
r.HandleFunc("/api/users", handleUsers)
r.HandleFunc("/api/health", handleHealth)
}, servex.WithAuthToken("secret-token"))
if err != nil {
log.Fatal(err)
}
// Server will automatically shutdown when ctx is cancelled
// or when the context deadline is reached
Types ¶
type AuditEvent ¶
type AuditEvent struct {
// Core event information
EventType AuditEventType `json:"event_type"`
Severity AuditSeverity `json:"severity"`
Timestamp time.Time `json:"timestamp"`
EventID string `json:"event_id"`
// Request context
RequestID string `json:"request_id,omitempty"`
UserID string `json:"user_id,omitempty"`
SessionID string `json:"session_id,omitempty"`
ClientIP string `json:"client_ip"`
UserAgent string `json:"user_agent,omitempty"`
Method string `json:"method"`
Path string `json:"path"`
Query string `json:"query,omitempty"`
Referer string `json:"referer,omitempty"`
// Security context
BlockedRule string `json:"blocked_rule,omitempty"`
RateLimitKey string `json:"ratelimit_key,omitempty"`
FilterType string `json:"filter_type,omitempty"`
FilterValue string `json:"filter_value,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
// Event details
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
Error string `json:"error,omitempty"`
// Response information
StatusCode int `json:"status_code,omitempty"`
ResponseTime int64 `json:"response_time_ms,omitempty"`
// Geographical information (if available)
Country string `json:"country,omitempty"`
Region string `json:"region,omitempty"`
City string `json:"city,omitempty"`
// Threat intelligence
ThreatLevel string `json:"threat_level,omitempty"`
ThreatSource string `json:"threat_source,omitempty"`
// Compliance tags
ComplianceTags []string `json:"compliance_tags,omitempty"`
}
AuditEvent represents a security event that should be logged for audit purposes
type AuditEventType ¶
type AuditEventType string
AuditEventType represents the type of security event being logged
const ( // Authentication Events AuditEventAuthLoginSuccess AuditEventType = "auth.login.success" AuditEventAuthLoginFailure AuditEventType = "auth.login.failure" AuditEventAuthLogout AuditEventType = "auth.logout" AuditEventAuthTokenRefresh AuditEventType = "auth.token.refresh" AuditEventAuthTokenInvalid AuditEventType = "auth.token.invalid" AuditEventAuthForbidden AuditEventType = "auth.forbidden" // Rate Limiting Events AuditEventRateLimitExceeded AuditEventType = "ratelimit.exceeded" AuditEventRateLimitBlocked AuditEventType = "ratelimit.blocked" // Filtering Events AuditEventFilterIPBlocked AuditEventType = "filter.ip.blocked" AuditEventFilterUABlocked AuditEventType = "filter.useragent.blocked" AuditEventFilterHeaderBlocked AuditEventType = "filter.header.blocked" AuditEventFilterQueryBlocked AuditEventType = "filter.query.blocked" // CSRF Events AuditEventCSRFTokenMissing AuditEventType = "csrf.token.missing" AuditEventCSRFTokenInvalid AuditEventType = "csrf.token.invalid" AuditEventCSRFAttackDetected AuditEventType = "csrf.attack.detected" // Request Security Events AuditEventSuspiciousPath AuditEventType = "request.suspicious.path" AuditEventRequestTooLarge AuditEventType = "request.too.large" AuditEventMaliciousPayload AuditEventType = "request.malicious.payload" // Admin Events AuditEventAdminAccess AuditEventType = "admin.access" AuditEventConfigChange AuditEventType = "config.change" AuditEventFilterRuleAdded AuditEventType = "filter.rule.added" AuditEventFilterRuleRemoved AuditEventType = "filter.rule.removed" // System Events AuditEventSecurityViolation AuditEventType = "security.violation" AuditEventAnomalousActivity AuditEventType = "security.anomaly" )
type AuditLogger ¶
type AuditLogger interface {
// LogSecurityEvent logs a security-related event
LogSecurityEvent(event AuditEvent)
// LogAuthenticationEvent logs authentication-related events
LogAuthenticationEvent(eventType AuditEventType, r *http.Request, userID string, success bool, details map[string]any)
// LogRateLimitEvent logs rate limiting events
LogRateLimitEvent(r *http.Request, key string, details map[string]any)
// LogFilterEvent logs request filtering events
LogFilterEvent(eventType AuditEventType, r *http.Request, filterType, filterValue, rule string)
// LogCSRFEvent logs CSRF protection events
LogCSRFEvent(eventType AuditEventType, r *http.Request, details map[string]any)
// LogSuspiciousActivity logs suspicious or anomalous activity
LogSuspiciousActivity(r *http.Request, activityType string, details map[string]any)
}
AuditLogger interface for security audit logging
type AuditSeverity ¶
type AuditSeverity string
AuditSeverity represents the severity level of an audit event
const ( AuditSeverityLow AuditSeverity = "low" AuditSeverityMedium AuditSeverity = "medium" AuditSeverityHigh AuditSeverity = "high" AuditSeverityCritical AuditSeverity = "critical" )
type AuthConfig ¶
type AuthConfig struct {
// Enabled indicates whether authentication is enabled.
Enabled bool
// Database is the interface for user data persistence.
// Must implement AuthDatabase interface for user CRUD operations.
// Set via WithAuth() or WithAuthMemoryDatabase().
//
// The database handles:
// - User creation and retrieval
// - Password hashing and verification
// - Role management
// - Session tracking
//
// Use WithAuthMemoryDatabase() for development/testing (data is lost on restart).
// Use WithAuth() with a persistent database implementation for production.
Database AuthDatabase
// JWTAccessSecret is the secret key used for signing access tokens (hex encoded).
// Set via WithAuthKey(). If empty, a random key will be generated.
//
// Security requirements:
// - Use strong, randomly generated keys
// - Different from refresh token secret
// - Store securely (environment variables, key management systems)
// - Rotate periodically in production
//
// Example: "your-32-byte-hex-encoded-access-key"
JWTAccessSecret string
// JWTRefreshSecret is the secret key used for signing refresh tokens (hex encoded).
// Set via WithAuthKey(). If empty, a random key will be generated.
//
// Security requirements:
// - Use strong, randomly generated keys
// - Different from access token secret
// - Store securely (environment variables, key management systems)
// - Rotate periodically in production
//
// Example: "your-32-byte-hex-encoded-refresh-key"
JWTRefreshSecret string
// AccessTokenDuration specifies the validity duration for access tokens.
// Set via WithAuthTokensDuration(). Defaults to 5 minutes if not set.
//
// Recommended patterns:
// - Web apps: 15-60 min
// - APIs: 5-30 min
// - Mobile apps: 30-60 min
// - High security: 5-15 min
//
// Shorter tokens improve security but require more refresh operations.
AccessTokenDuration time.Duration
// RefreshTokenDuration specifies the validity duration for refresh tokens.
// Set via WithAuthTokensDuration(). Defaults to 7 days if not set.
//
// Recommended patterns:
// - Web apps: 7-30 days
// - APIs: 1-7 days
// - Mobile apps: 30-90 days
// - High security: 1-3 days
//
// Longer refresh tokens improve user experience but increase security risk if compromised.
RefreshTokenDuration time.Duration
// IssuerNameInJWT is the issuer name included in JWT token claims.
// This helps identify which service issued the token and can be used for validation.
// Set via WithAuthIssuer(). Defaults to "testing" if not set.
//
// Use descriptive names like:
// - Application name: "user-service", "payment-api"
// - Environment-specific: "my-app-prod", "my-app-staging"
// - Domain-based: "api.mycompany.com"
//
// The issuer appears in the JWT "iss" claim and can be verified by clients.
IssuerNameInJWT string
// RefreshTokenCookieName is the name of the HTTP cookie used to store refresh tokens.
// Set via WithAuthRefreshTokenCookieName(). Defaults to "_servexrt" if not set.
//
// Cookie characteristics:
// - HttpOnly: Cannot be accessed by JavaScript
// - Secure: Only sent over HTTPS (in production)
// - SameSite: Protection against CSRF attacks
// - Expires: Set to refresh token duration
//
// Choose names that don't conflict with your application's other cookies.
RefreshTokenCookieName string
// AuthBasePath is the base path for authentication API endpoints.
// All auth routes will be registered under this path.
// Set via WithAuthBasePath(). Defaults to "/api/v1/auth" if not set.
//
// Registered endpoints under the base path:
// - POST {basePath}/register
// - POST {basePath}/login
// - POST {basePath}/refresh
// - POST {basePath}/logout
// - GET {basePath}/me
//
// Examples: "/auth", "/api/v2/auth", "/users/auth"
AuthBasePath string
// RolesOnRegister are the default roles assigned to newly registered users.
// These roles are automatically assigned when users register through the /register endpoint.
// Set via WithAuthInitialRoles().
//
// Common role patterns:
// - Basic: ["user"]
// - Hierarchical: ["user", "member", "premium"]
// - Functional: ["reader", "writer", "admin"]
//
// Users can have multiple roles. Additional roles can be assigned later
// through user management endpoints or database operations.
RolesOnRegister []UserRole
// InitialUsers is a list of initial users to be created when the server starts.
// This is useful for creating admin accounts or seeding the database with test users.
// Set via WithAuthInitialUsers().
//
// Security considerations:
// - Use strong passwords
// - Consider loading from environment variables
// - Remove or change default passwords in production
// - Limit to essential accounts only
//
// The users are created if they don't already exist in the database.
InitialUsers []InitialUser
// NotRegisterRoutes prevents automatic registration of default authentication routes.
// Set to true via WithAuthNotRegisterRoutes() when you want to implement custom auth endpoints.
//
// When enabled, you must implement your own:
// - User registration endpoint
// - Login endpoint
// - Token refresh endpoint
// - Logout endpoint
// - User profile endpoint
//
// You can still use the AuthManager methods for token generation and validation.
NotRegisterRoutes bool
// contains filtered or unexported fields
}
AuthConfig holds the JWT-based authentication configuration with user management, roles, and JWT tokens. This configuration enables a complete authentication system with automatic endpoint registration.
When authentication is enabled, the following endpoints are automatically registered:
- POST {AuthBasePath}/register - User registration
- POST {AuthBasePath}/login - User login
- POST {AuthBasePath}/refresh - Token refresh
- POST {AuthBasePath}/logout - User logout
- GET {AuthBasePath}/me - Current user info
Example configuration:
auth := AuthConfig{
Database: myAuthDatabase,
AccessTokenDuration: 15 * time.Minute,
RefreshTokenDuration: 7 * 24 * time.Hour,
AuthBasePath: "/api/v1/auth",
IssuerNameInJWT: "my-app",
RolesOnRegister: []UserRole{"user"},
}
type AuthConfiguration ¶
type AuthConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_AUTH_ENABLED"`
JWTAccessSecret string `yaml:"jwt_access_secret" json:"jwt_access_secret" env:"SERVEX_AUTH_JWT_ACCESS_SECRET"`
JWTRefreshSecret string `yaml:"jwt_refresh_secret" json:"jwt_refresh_secret" env:"SERVEX_AUTH_JWT_REFRESH_SECRET"`
AccessTokenDuration time.Duration `yaml:"access_token_duration" json:"access_token_duration" env:"SERVEX_AUTH_ACCESS_TOKEN_DURATION"`
RefreshTokenDuration time.Duration `yaml:"refresh_token_duration" json:"refresh_token_duration" env:"SERVEX_AUTH_REFRESH_TOKEN_DURATION"`
Issuer string `yaml:"issuer" json:"issuer" env:"SERVEX_AUTH_ISSUER"`
RefreshTokenCookieName string `yaml:"refresh_token_cookie_name" json:"refresh_token_cookie_name" env:"SERVEX_AUTH_REFRESH_TOKEN_COOKIE_NAME"`
BasePath string `yaml:"base_path" json:"base_path" env:"SERVEX_AUTH_BASE_PATH"`
InitialRoles []string `yaml:"initial_roles" json:"initial_roles" env:"SERVEX_AUTH_INITIAL_ROLES"`
NotRegisterRoutes bool `yaml:"not_register_routes" json:"not_register_routes" env:"SERVEX_AUTH_NOT_REGISTER_ROUTES"`
UseMemoryDatabase bool `yaml:"use_memory_database" json:"use_memory_database" env:"SERVEX_AUTH_USE_MEMORY_DATABASE"`
}
AuthConfiguration represents authentication configuration
type AuthDatabase ¶
type AuthDatabase interface {
// NewUser creates a new user in the database.
NewUser(ctx context.Context, username string, passwordHash string, roles ...UserRole) (string, error)
// FindByID finds a user by their ID.
FindByID(ctx context.Context, id string) (user User, exists bool, err error)
// FindByUsername finds a user by their username.
FindByUsername(ctx context.Context, username string) (user User, exists bool, err error)
// FindAll retrieves all users from the database.
FindAll(ctx context.Context) ([]User, error)
// UpdateUser updates a user's information in the database.
// Fields are updated only if the corresponding pointers are not nil.
UpdateUser(ctx context.Context, id string, diff *UserDiff) error
}
AuthDatabase defines the interface for interacting with the user database.
type AuthManager ¶
type AuthManager struct {
// contains filtered or unexported fields
}
AuthManager handles authentication and authorization logic.
func NewAuthManager ¶
func NewAuthManager(cfg AuthConfig, auditLogger ...AuditLogger) (*AuthManager, error)
NewAuthManager creates a new AuthManager with the provided configuration. It initializes default values for configuration fields if they are not provided.
func (*AuthManager) CreateUser ¶
func (h *AuthManager) CreateUser(ctx context.Context, username, password string, roles ...UserRole) error
CreateUser provides a programmatic way to create or update a user. If the user already exists (based on username), it updates their password and roles. If the user does not exist, it creates a new user with the provided details.
func (*AuthManager) GetAllUsersHandler ¶
func (h *AuthManager) GetAllUsersHandler(w http.ResponseWriter, r *http.Request)
GetAllUsersHandler handles the HTTP request to retrieve all users. Note: This handler is intended for administrative purposes and might require specific roles. The corresponding route registration is commented out by default. It returns a list of all users.
func (*AuthManager) GetCurrentUserHandler ¶
func (h *AuthManager) GetCurrentUserHandler(w http.ResponseWriter, r *http.Request)
GetCurrentUserHandler handles the HTTP request to retrieve the details of the currently authenticated user. It reads the user ID from the request context, validates it, and returns the user details.
func (*AuthManager) LoginHandler ¶
func (h *AuthManager) LoginHandler(w http.ResponseWriter, r *http.Request)
LoginHandler handles the HTTP request for user login. It reads the request body, validates it, and logs the user in. It sets the auth cookie and returns the user login response.
func (*AuthManager) LogoutHandler ¶
func (h *AuthManager) LogoutHandler(w http.ResponseWriter, r *http.Request)
LogoutHandler handles the HTTP request for user logout. It invalidates the refresh token associated with the current session. It sets the logout cookie and returns a no content response.
func (*AuthManager) RefreshHandler ¶
func (h *AuthManager) RefreshHandler(w http.ResponseWriter, r *http.Request)
RefreshHandler handles the HTTP request for refreshing access tokens using a refresh token cookie. It reads the refresh token cookie, validates it, and refreshes the access token. It sets the auth cookie and returns the user login response.
func (*AuthManager) RegisterHandler ¶
func (h *AuthManager) RegisterHandler(w http.ResponseWriter, r *http.Request)
RegisterHandler handles the HTTP request for user registration. It reads the request body, validates it, and registers a new user. It sets the auth cookie and returns the user login response.
func (*AuthManager) RegisterRoutes ¶
func (h *AuthManager) RegisterRoutes(r *mux.Router)
RegisterRoutes registers the authentication-related HTTP routes on the provided router. It registers the following routes: - /register - POST - Register a new user - /login - POST - Login a user - /refresh - POST - Refresh an access token - /logout - POST - Logout a user - /me - GET - Get the current user
func (*AuthManager) UpdateUserRoleHandler ¶
func (h *AuthManager) UpdateUserRoleHandler(w http.ResponseWriter, r *http.Request)
UpdateUserRoleHandler handles the HTTP request to update a user's roles. Note: This handler is intended for administrative purposes and might require specific roles. The corresponding route registration is commented out by default.
func (*AuthManager) WithAuth ¶
func (m *AuthManager) WithAuth(next http.HandlerFunc, roles ...UserRole) http.HandlerFunc
WithAuth is an HTTP middleware that enforces authentication and authorization. It checks for a valid JWT access token in the Authorization header. If roles are provided, it verifies that the authenticated user has at least one of the required roles. The user ID and roles are added to the request context.
type Backend ¶
type Backend struct {
// URL is the backend server URL
URL string `yaml:"url" json:"url"`
// Weight for weighted load balancing (default: 1)
Weight int `yaml:"weight" json:"weight"`
// HealthCheckPath for health checking (optional)
HealthCheckPath string `yaml:"health_check_path" json:"health_check_path"`
// HealthCheckInterval for health checking (default: 30s)
HealthCheckInterval time.Duration `yaml:"health_check_interval" json:"health_check_interval"`
// MaxConnections limits concurrent connections to this backend (0 = unlimited)
MaxConnections int `yaml:"max_connections" json:"max_connections"`
// contains filtered or unexported fields
}
Backend represents a backend server
type BaseConfig ¶
type BaseConfig struct {
// HTTP is the address to start the HTTP listener on.
//
// Format: "host:port" where host is optional
// Examples:
// - ":8080" - Listen on all interfaces, port 8080
// - "localhost:8080" - Listen on localhost only
// - "0.0.0.0:8080" - Explicitly listen on all interfaces
// - "192.168.1.100:8080" - Listen on specific IP
//
// Leave empty to disable HTTP listener.
HTTP string `yaml:"http" json:"http" env:"SERVER_HTTP"`
// HTTPS is the address to start the HTTPS listener on.
//
// Format: "host:port" where host is optional
// Examples:
// - ":8443" - Listen on all interfaces, port 8443
// - "localhost:8443" - Listen on localhost only
// - "0.0.0.0:8443" - Explicitly listen on all interfaces
// - "192.168.1.100:8443" - Listen on specific IP
//
// Requires CertFile and KeyFile to be set for TLS.
// Leave empty to disable HTTPS listener.
HTTPS string `yaml:"https" json:"https" env:"SERVER_HTTPS"`
// CertFile is the path to the TLS certificate file for HTTPS.
//
// The file should contain the PEM-encoded certificate chain.
// Examples:
// - "/etc/ssl/certs/server.crt"
// - "./certs/certificate.pem"
// - "/path/to/fullchain.pem" (Let's Encrypt style)
//
// Required when HTTPS is enabled.
// Must be readable by the application.
CertFile string `yaml:"cert_file" json:"cert_file" env:"SERVER_CERT_FILE"`
// KeyFile is the path to the TLS private key file for HTTPS.
//
// The file should contain the PEM-encoded private key.
// Examples:
// - "/etc/ssl/private/server.key"
// - "./certs/private.pem"
// - "/path/to/privkey.pem" (Let's Encrypt style)
//
// Required when HTTPS is enabled.
// Must be readable by the application and kept secure.
// Should have restricted file permissions (e.g., 600).
KeyFile string `yaml:"key_file" json:"key_file" env:"SERVER_KEY_FILE"`
// AuthToken is a simple bearer token for API authentication.
//
// When set, the server will check for "Authorization: Bearer <token>"
// headers on protected routes.
//
// Examples:
// - "sk-1234567890abcdef" - API key style
// - "secret-development-token" - Development token
// - Load from environment: os.Getenv("API_SECRET")
//
// Security considerations:
// - Use strong, randomly generated tokens
// - Rotate tokens periodically
// - Never commit tokens to source control
// - Use environment variables in production
//
// For more advanced authentication, use the JWT authentication system instead.
AuthToken string `yaml:"auth_token" json:"auth_token" env:"SERVER_AUTH_TOKEN"`
}
BaseConfig represents the base configuration for a server that can be loaded from configuration files (YAML/JSON) or environment variables. This provides a simple way to configure servers without using the functional options pattern.
The struct tags enable automatic loading from:
- YAML files (yaml tag)
- JSON files (json tag)
- Environment variables (env tag)
Example YAML configuration:
# server.yaml http: ":8080" https: ":8443" cert_file: "/path/to/cert.pem" key_file: "/path/to/key.pem" auth_token: "secret-api-key"
Example JSON configuration:
{
"http": ":8080",
"https": ":8443",
"cert_file": "/path/to/cert.pem",
"key_file": "/path/to/key.pem",
"auth_token": "secret-api-key"
}
Example environment variables:
export SERVER_HTTP=":8080" export SERVER_HTTPS=":8443" export SERVER_CERT_FILE="/path/to/cert.pem" export SERVER_KEY_FILE="/path/to/key.pem" export SERVER_AUTH_TOKEN="secret-api-key"
Example usage:
// Load from file
var config BaseConfig
data, _ := os.ReadFile("server.yaml")
yaml.Unmarshal(data, &config)
// Validate configuration
if err := config.Validate(); err != nil {
log.Fatal(err)
}
// Convert to servex options
var opts []servex.Option
if config.AuthToken != "" {
opts = append(opts, servex.WithAuthToken(config.AuthToken))
}
if config.CertFile != "" && config.KeyFile != "" {
opts = append(opts, servex.WithCertificateFromFile(config.CertFile, config.KeyFile))
}
server := servex.New(opts...)
server.Start(config.HTTP, config.HTTPS)
Use this when:
- Loading configuration from external files
- Using environment-based configuration
- Deploying with container orchestration
- Following 12-factor app principles
- Need simple, declarative configuration
func (*BaseConfig) Validate ¶
func (c *BaseConfig) Validate() error
Validate checks if the BaseConfig contains valid configuration values. It ensures that addresses are properly formatted and at least one listener is configured.
Validation rules:
- At least one of HTTP or HTTPS must be set (not both empty)
- HTTP address must match the format "host:port" if set
- HTTPS address must match the format "host:port" if set
- Host can be empty (defaults to all interfaces)
- Port must be valid (1-65535)
Example valid configurations:
// HTTP only
config := BaseConfig{HTTP: ":8080"}
err := config.Validate() // nil
// HTTPS only
config := BaseConfig{
HTTPS: ":8443",
CertFile: "cert.pem",
KeyFile: "key.pem",
}
err := config.Validate() // nil
// Both HTTP and HTTPS
config := BaseConfig{
HTTP: ":8080",
HTTPS: ":8443",
CertFile: "cert.pem",
KeyFile: "key.pem",
}
err := config.Validate() // nil
Example invalid configurations:
// No listeners configured
config := BaseConfig{}
err := config.Validate() // "at least one of http or https should be set"
// Invalid HTTP address format
config := BaseConfig{HTTP: "invalid-address"}
err := config.Validate() // "invalid http address"
// Invalid HTTPS address format
config := BaseConfig{
HTTP: ":8080",
HTTPS: "not-a-valid:address:format",
}
err := config.Validate() // "invalid https address"
Note: This method only validates address formats. It does not check:
- Whether the ports are available
- Whether certificate files exist or are valid
- Whether the application has permission to bind to the ports
- Whether the certificate and key files match
These runtime checks happen when the server actually starts.
Returns nil if the configuration is valid, or an error describing what is invalid about the configuration.
type BaseRequestLogger ¶
type BaseRequestLogger struct {
Logger
// FieldsToInclude specifies which fields to include in logs.
// If empty, all available fields will be logged (default behavior).
// Use the exported *LogField constants to specify fields.
FieldsToInclude []string
}
func (*BaseRequestLogger) Log ¶
func (l *BaseRequestLogger) Log(r RequestLogBundle)
type CORSConfig ¶ added in v2.2.0
type CORSConfig struct {
// Enabled determines whether CORS middleware is active.
// Must be set to true for any CORS headers to be applied.
// Set via WithCORS(), WithCORSAllowOrigins(), or WithCORSConfig().
Enabled bool
// AllowOrigins is a list of origins that are allowed to access the resource.
// Origins should include the protocol, domain, and port (if not standard).
// Set via WithCORSAllowOrigins().
//
// Examples:
// - []string{"*"}: Allow all origins (not recommended for production with credentials)
// - []string{"https://example.com"}: Allow specific origin
// - []string{"https://app.example.com", "https://admin.example.com"}: Multiple origins
// - []string{"http://localhost:3000", "http://localhost:8080"}: Development origins
//
// Security considerations:
// - Use specific origins instead of "*" when possible
// - Never use "*" with AllowCredentials: true
// - Include protocol (https://) and port if non-standard
//
// If empty, defaults to "*" (all origins allowed).
AllowOrigins []string
// AllowMethods is a list of HTTP methods that are allowed for cross-origin requests.
// Set via WithCORSAllowMethods().
//
// Common values:
// - []string{GET, POST, PUT, DELETE, OPTIONS}: Full REST API
// - []string{GET, POST, OPTIONS}: Read and create operations
// - []string{GET, OPTIONS}: Read-only API
//
// Notes:
// - OPTIONS is automatically included for preflight requests
// - HEAD and GET are considered "simple" methods by browsers
// - Other methods trigger preflight requests
//
// If empty, defaults to common REST methods: GET, POST, PUT, DELETE, OPTIONS.
AllowMethods []string
// AllowHeaders is a list of headers that are allowed in cross-origin requests.
// Set via WithCORSAllowHeaders().
//
// Common headers:
// - []string{"Content-Type", "Authorization"}: Basic API headers
// - []string{"Content-Type", "Authorization", "X-Requested-With"}: AJAX headers
// - []string{"*"}: Allow all headers (less secure)
//
// Standard headers that don't require explicit allowance:
// - Accept, Accept-Language, Content-Language
// - Content-Type (for simple values like text/plain, application/x-www-form-urlencoded)
//
// Custom headers and complex Content-Type values need explicit allowance.
//
// If empty, defaults to common headers: Content-Type, Authorization, X-Requested-With.
AllowHeaders []string
// ExposeHeaders is a list of headers that are exposed to the client.
// These headers can be accessed by JavaScript in the browser.
// Set via WithCORSExposeHeaders().
//
// Common headers to expose:
// - []string{"Content-Length", "Content-Range"}: File download information
// - []string{"X-Total-Count", "X-Page-Count"}: Pagination metadata
// - []string{"Location"}: Resource creation location
//
// By default, only simple response headers are exposed to clients.
// Custom headers need to be explicitly listed here to be accessible.
//
// If empty, no additional headers are exposed beyond the defaults.
ExposeHeaders []string
// AllowCredentials indicates whether credentials (cookies, HTTP authentication, client-side SSL certificates)
// are allowed to be included in cross-origin requests.
// Set via WithCORSAllowCredentials().
//
// Security implications:
// - When true, browsers include cookies and authorization headers
// - Cannot use "*" for AllowOrigins when this is true
// - Enables authenticated cross-origin requests
// - Increases CSRF risk if not properly handled
//
// Use cases:
// - APIs that use session cookies for authentication
// - Applications with cross-origin authenticated requests
// - Single sign-on systems
//
// Default: false (safer for public APIs)
AllowCredentials bool
// MaxAge is the maximum number of seconds that the results of a preflight request can be cached.
// This affects how long browsers cache CORS preflight responses.
// Set via WithCORSMaxAge().
//
// Common values:
// - 3600: 1 hour (good for development)
// - 86400: 1 day (good for production)
// - 0: No caching (forces preflight for every request)
//
// Benefits of longer caching:
// - Fewer preflight requests (better performance)
// - Reduced server load
//
// Benefits of shorter caching:
// - Faster policy changes take effect
// - Better for development
//
// Default: 3600 seconds (1 hour) if not set.
MaxAge int
// ExcludePaths are paths that should be excluded from CORS headers.
// Requests to these paths will not have CORS headers applied.
// Set via WithCORSExcludePaths().
//
// Common exclusions:
// - "/internal/*": Internal endpoints not meant for browsers
// - "/admin/*": Admin endpoints with different CORS needs
// - "/webhooks/*": Webhook endpoints that don't need CORS
//
// Path matching supports wildcards (*) for pattern matching.
// Use when different endpoints need different CORS policies.
ExcludePaths []string
// IncludePaths are paths that should have CORS headers applied.
// If set, only requests to these paths will receive CORS headers.
// Set via WithCORSIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to receive CORS headers
// 2. Paths in ExcludePaths are then excluded from CORS headers
//
// Use cases:
// - Apply CORS only to API endpoints: "/api/*"
// - CORS for specific services: "/auth/*", "/users/*"
// - Public endpoints only: "/public/*"
//
// Path matching supports wildcards (*) for pattern matching.
// Leave empty to apply CORS to all paths (default behavior).
IncludePaths []string
}
CORSConfig holds configuration for Cross-Origin Resource Sharing (CORS). This enables web applications running at one domain to access resources from another domain. This is essential for modern web applications, SPAs, and APIs that serve different frontends.
Example configuration:
corsConfig := CORSConfig{
Enabled: true,
AllowOrigins: []string{"https://example.com", "https://app.example.com"},
AllowMethods: []string{GET, POST, PUT, DELETE, OPTIONS},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 3600,
}
type CORSConfiguration ¶ added in v2.2.0
type CORSConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_CORS_ENABLED"`
AllowOrigins []string `yaml:"allow_origins" json:"allow_origins" env:"SERVEX_CORS_ALLOW_ORIGINS"`
AllowMethods []string `yaml:"allow_methods" json:"allow_methods" env:"SERVEX_CORS_ALLOW_METHODS"`
AllowHeaders []string `yaml:"allow_headers" json:"allow_headers" env:"SERVEX_CORS_ALLOW_HEADERS"`
ExposeHeaders []string `yaml:"expose_headers" json:"expose_headers" env:"SERVEX_CORS_EXPOSE_HEADERS"`
AllowCredentials bool `yaml:"allow_credentials" json:"allow_credentials" env:"SERVEX_CORS_ALLOW_CREDENTIALS"`
MaxAge int `yaml:"max_age" json:"max_age" env:"SERVEX_CORS_MAX_AGE"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_CORS_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_CORS_INCLUDE_PATHS"`
}
CORSConfiguration represents CORS configuration
type CacheConfig ¶
type CacheConfig struct {
// Enabled determines whether cache control headers middleware is active.
// Must be set to true for any cache control headers to be applied.
// Set via WithCacheControl(), WithCacheHeaders(), or WithCacheConfig().
//
// When disabled, no cache control headers will be added to responses,
// even if individual header values are configured.
Enabled bool
// CacheControl sets the Cache-Control header to control caching behavior.
// This is the primary header for controlling HTTP caching.
// Set via WithCacheControl() or WithCacheConfig().
//
// Common values:
// - "no-cache": Must revalidate before using cached copy
// - "no-store": Do not cache at all (sensitive data)
// - "public, max-age=3600": Public cache for 1 hour
// - "private, max-age=900": Private cache for 15 minutes
// - "public, max-age=31536000, immutable": Cache for 1 year (static assets)
//
// Format: "directive1, directive2, directive3=value"
//
// Common directives:
// - public/private: Who can cache
// - max-age=<seconds>: Cache lifetime
// - no-cache: Must revalidate
// - no-store: Never cache
// - must-revalidate: Revalidate when stale
// - immutable: Content never changes
CacheControl string
// Expires sets the Expires header with an absolute expiration time.
// This provides a fallback for older HTTP/1.0 clients that don't support Cache-Control.
// Modern clients prefer Cache-Control over Expires.
// Set via WithCacheExpires(), WithCacheExpiresTime(), or WithCacheConfig().
//
// Format: HTTP date format (RFC 7231)
// Examples:
// - "Wed, 21 Oct 2025 07:28:00 GMT"
// - Generated from time.Now().Add(duration).Format(http.TimeFormat)
//
// Note: If both Cache-Control max-age and Expires are present,
// Cache-Control takes precedence in HTTP/1.1 clients.
Expires string
// ETag sets the ETag header for cache validation.
// ETags allow clients to validate cached content without downloading.
// Set via WithCacheETag() or WithCacheConfig().
//
// For dynamic ETags that change per request, use ETagFunc instead.
//
// ETag formats:
// - Strong ETag: `"version123"` (content identical)
// - Weak ETag: `W/"version123"` (content equivalent)
//
// Use cases:
// - Static files: Hash of file content
// - Dynamic content: Hash of data or version
// - APIs: Resource version or last modified timestamp
//
// Examples:
// - `"33a64df551"` (hash-based)
// - `"v1.2.3"` (version-based)
// - `W/"Tue, 15 Nov 1994 12:45:26 GMT"` (weak, timestamp-based)
ETag string
// ETagFunc is a function that generates ETags dynamically per request.
// This allows for request-specific or content-specific ETags.
// Takes precedence over the static ETag field if both are set.
// Set via WithCacheETagFunc().
//
// Example:
// ETagFunc: func(r *http.Request) string {
// return `"` + getUserID(r) + "-" + getContentVersion() + `"`
// }
//
// Use cases:
// - User-specific content hashing
// - Content-based ETags (hash of response data)
// - Request-dependent versioning
// - Dynamic resource validation
ETagFunc func(r *http.Request) string
// LastModified sets the Last-Modified header for cache validation.
// This indicates when the resource was last changed.
// Set via WithCacheLastModified(), WithCacheLastModifiedTime(), or WithCacheConfig().
//
// For dynamic LastModified times that change per request, use LastModifiedFunc instead.
//
// Format: HTTP date format (RFC 7231)
// Examples:
// - "Wed, 21 Oct 2015 07:28:00 GMT"
// - Generated from time.Format(http.TimeFormat)
//
// Use cases:
// - Static files: File modification time
// - Dynamic content: Data update timestamp
// - APIs: Resource last update time
//
// Benefits:
// - Enables conditional requests (If-Modified-Since)
// - Reduces bandwidth for unchanged resources
// - Improves cache efficiency
LastModified string
// LastModifiedFunc is a function that generates Last-Modified times dynamically per request.
// This allows for request-specific or content-specific modification times.
// Takes precedence over the static LastModified field if both are set.
// Set via WithCacheLastModifiedFunc().
//
// Example:
// LastModifiedFunc: func(r *http.Request) time.Time {
// return getContentModTime(r.URL.Path)
// }
//
// Use cases:
// - File-based LastModified times
// - Database record modification times
// - Request-dependent timestamps
// - Dynamic resource validation
LastModifiedFunc func(r *http.Request) time.Time
// Vary sets the Vary header to specify which request headers affect caching.
// This tells caches that the response varies based on certain request headers.
// Set via WithCacheVary() or WithCacheConfig().
//
// Common values:
// - "Accept-Encoding": Different compression formats
// - "User-Agent": Different responses for different browsers
// - "Accept": Different content types (JSON vs XML)
// - "Authorization": Different responses for authenticated users
// - "Accept-Language": Different languages
//
// Multiple headers: "Accept-Encoding, User-Agent, Accept-Language"
//
// Use cases:
// - Content negotiation (compression, format, language)
// - User-specific content
// - Authentication-dependent responses
//
// Important: Only include headers that actually affect the response
// to avoid cache fragmentation.
Vary string
// ExcludePaths are paths that should be excluded from cache control headers.
// Requests to these paths will not have cache control headers applied.
// Set via WithCacheExcludePaths().
//
// Common exclusions:
// - Dynamic APIs: "/api/*", "/graphql"
// - User-specific content: "/user/*", "/profile/*"
// - Authentication: "/auth/*", "/login", "/logout"
// - Admin interfaces: "/admin/*"
// - Real-time endpoints: "/ws/*", "/stream/*"
//
// Path matching supports wildcards (*) for pattern matching.
// Use when different endpoints need different caching strategies.
ExcludePaths []string
// IncludePaths are paths that should have cache control headers applied.
// If set, only requests to these paths will receive cache control headers.
// Set via WithCacheIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to receive cache headers
// 2. Paths in ExcludePaths are then excluded from cache headers
//
// Use cases:
// - Cache only static assets: "/static/*", "/assets/*"
// - Cache specific API endpoints: "/api/public/*"
// - Cache documentation: "/docs/*"
//
// Path matching supports wildcards (*) for pattern matching.
// Useful for applying cache headers only to specific content types.
IncludePaths []string
}
CacheConfig represents cache control configuration for HTTP responses.
type CacheConfiguration ¶
type CacheConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_CACHE_ENABLED"`
CacheControl string `yaml:"cache_control" json:"cache_control" env:"SERVEX_CACHE_CONTROL"`
Expires string `yaml:"expires" json:"expires" env:"SERVEX_CACHE_EXPIRES"`
ETag string `yaml:"etag" json:"etag" env:"SERVEX_CACHE_ETAG"`
LastModified string `yaml:"last_modified" json:"last_modified" env:"SERVEX_CACHE_LAST_MODIFIED"`
Vary string `yaml:"vary" json:"vary" env:"SERVEX_CACHE_VARY"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_CACHE_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_CACHE_INCLUDE_PATHS"`
}
CacheConfiguration represents cache control configuration
type CompressionConfig ¶ added in v2.2.0
type CompressionConfig struct {
// Enabled determines whether response compression is active.
// Must be set to true for compression to be applied.
// Set via WithCompression() or WithCompressionConfig().
Enabled bool
// Level sets the compression level for gzip encoding.
// Valid range: 1-9 where 1 is fastest and 9 is best compression.
// Set via WithCompressionLevel().
//
// Recommended values:
// - 1: Fastest compression, lower CPU usage
// - 6: Default balance of speed and compression (recommended)
// - 9: Best compression, higher CPU usage
//
// Default: 6 if not set.
Level int
// MinSize is the minimum response size in bytes to trigger compression.
// Responses smaller than this size will not be compressed.
// Set via WithCompressionMinSize().
//
// Common values:
// - 1024: 1KB (good default)
// - 512: Compress smaller responses
// - 4096: Only compress larger responses
// - 0: Compress all responses regardless of size
//
// Default: 1024 bytes if not set.
MinSize int
// Types is a list of MIME types that should be compressed.
// Only responses with these content types will be compressed.
// Set via WithCompressionTypes().
//
// Common MIME types for compression:
// - "text/html": HTML pages
// - "text/css": CSS stylesheets
// - "application/javascript": JavaScript files
// - "application/json": JSON API responses
// - "text/xml": XML responses
// - "text/plain": Plain text
// - "image/svg+xml": SVG images
//
// If empty, defaults to common text-based types.
Types []string
// ExcludePaths are paths that should be excluded from compression.
// Responses for these paths will not be compressed regardless of other settings.
// Set via WithCompressionExcludePaths().
//
// Common exclusions:
// - "/api/binary/*": Binary API endpoints
// - "/downloads/*": File download endpoints
// - "/images/*": Image files (already compressed)
// - "/videos/*": Video files (already compressed)
//
// Path matching supports wildcards (*) for pattern matching.
ExcludePaths []string
// IncludePaths are paths that should have compression applied.
// If set, only responses for these paths will be compressed.
// Set via WithCompressionIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to be considered for compression
// 2. Paths in ExcludePaths are then excluded from compression
//
// Use cases:
// - Compress only API endpoints: "/api/*"
// - Compress only static assets: "/static/*"
// - Compress specific content: "/docs/*", "/help/*"
//
// Path matching supports wildcards (*) for pattern matching.
// Leave empty to apply compression to all paths (default behavior).
IncludePaths []string
}
CompressionConfig holds the HTTP response compression configuration. This configuration enables automatic compression of response bodies using gzip or deflate encoding based on client Accept-Encoding headers.
Example configuration:
compression := CompressionConfig{
Enabled: true,
Level: 6,
MinSize: 1024,
Types: []string{"text/html", "application/json", "text/css", "application/javascript"},
ExcludePaths: []string{"/api/binary/*", "/downloads/*"},
}
type CompressionConfiguration ¶ added in v2.2.0
type CompressionConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_COMPRESSION_ENABLED"`
Level int `yaml:"level" json:"level" env:"SERVEX_COMPRESSION_LEVEL"`
MinSize int `yaml:"min_size" json:"min_size" env:"SERVEX_COMPRESSION_MIN_SIZE"`
Types []string `yaml:"types" json:"types" env:"SERVEX_COMPRESSION_TYPES"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_COMPRESSION_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_COMPRESSION_INCLUDE_PATHS"`
}
CompressionConfiguration represents HTTP response compression configuration
type Config ¶
type Config struct {
// Server contains basic server configuration
Server ServerConfig `yaml:"server" json:"server"`
// Auth contains authentication configuration
Auth AuthConfiguration `yaml:"auth" json:"auth"`
// RateLimit contains rate limiting configuration
RateLimit RateLimitConfiguration `yaml:"rate_limit" json:"rate_limit"`
// Filter contains request filtering configuration
Filter FilterConfiguration `yaml:"filter" json:"filter"`
// Security contains security headers configuration
Security SecurityConfiguration `yaml:"security" json:"security"`
// Cache contains cache control configuration
Cache CacheConfiguration `yaml:"cache" json:"cache"`
// Compression contains HTTP response compression configuration
Compression CompressionConfiguration `yaml:"compression" json:"compression"`
// Logging contains logging configuration
Logging LoggingConfiguration `yaml:"logging" json:"logging"`
// CORS contains Cross-Origin Resource Sharing configuration
CORS CORSConfiguration `yaml:"cors" json:"cors"`
// StaticFiles contains static file serving configuration
StaticFiles StaticFilesConfiguration `yaml:"static_files" json:"static_files"`
// Proxy contains reverse proxy configuration
Proxy ProxyConfiguration `yaml:"proxy" json:"proxy"`
}
Config represents a comprehensive configuration structure that can be loaded from YAML files and environment variables. It includes all major servex options.
Example YAML configuration:
# server.yaml server: http: ":8080" https: ":8443" cert_file: "/path/to/cert.pem" key_file: "/path/to/key.pem" read_timeout: "30s" idle_timeout: "120s" auth_token: "secret-api-key" enable_health_endpoint: true health_path: "/health" auth: enabled: true issuer: "my-app" access_token_duration: "15m" refresh_token_duration: "7d" base_path: "/api/v1/auth" initial_roles: ["user"] rate_limit: enabled: true requests_per_interval: 100 interval: "1m" burst_size: 20 status_code: 429 message: "Rate limit exceeded" security: enabled: true content_security_policy: "default-src 'self'" x_frame_options: "DENY" strict_transport_security: "max-age=31536000" Example environment variables: export SERVEX_SERVER_HTTP=":8080" export SERVEX_SERVER_HTTPS=":8443" export SERVEX_SERVER_AUTH_TOKEN="secret-key" export SERVEX_AUTH_ENABLED="true" export SERVEX_RATE_LIMIT_ENABLED="true" export SERVEX_RATE_LIMIT_REQUESTS_PER_INTERVAL="100"
func LoadConfig ¶
LoadConfig loads configuration from a YAML file and then overlays environment variables
func LoadConfigFromEnv ¶
LoadConfigFromEnv loads configuration from environment variables
func LoadConfigFromFile ¶
LoadConfigFromFile loads configuration from a YAML file
func (*Config) ToBaseConfig ¶
func (c *Config) ToBaseConfig() BaseConfig
ToBaseConfig converts the Config to BaseConfig for simple server configuration
type Context ¶
Context provides a convenient wrapper around http.ResponseWriter and *http.Request with additional utilities for common HTTP operations.
Context simplifies common tasks such as:
- Reading and parsing request data (JSON, files, form values)
- Writing responses (JSON, files, error responses)
- Extracting client information (IP, headers, cookies)
- Managing request lifecycle (logging, error handling)
The Context is designed to be used within HTTP handlers and provides type-safe methods with built-in security features like size limits and input validation.
Example usage:
func userHandler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
var user User
if err := ctx.ReadJSON(&user); err != nil {
ctx.BadRequest(err, "Invalid JSON")
return
}
// Process user...
ctx.JSON(map[string]string{"status": "created"})
}
func C ¶
C creates a new Context for the HTTP request and response.
This is a convenient shortcut for NewContext() and is the most common way to create a Context in HTTP handlers.
Parameters:
- w: The HTTP response writer
- r: The HTTP request
- opts: Optional server options for configuration (usually omitted in handlers)
Example:
func apiHandler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
userID := ctx.Path("id")
if userID == "" {
ctx.BadRequest(nil, "Missing user ID")
return
}
ctx.JSON(map[string]string{"user_id": userID})
}
func NewContext ¶
NewContext creates a new Context for the HTTP request and response.
Parameters:
- w: The HTTP response writer
- r: The HTTP request
- opts: Optional server options for configuration
Example:
func apiHandler(w http.ResponseWriter, r *http.Request) {
ctx := servex.NewContext(w, r)
userID := ctx.Path("id")
if userID == "" {
ctx.BadRequest(nil, "Missing user ID")
return
}
ctx.JSON(map[string]string{"user_id": userID})
}
func (*Context) APIVersion ¶
APIVersion returns the API version of the handler from the path. It returns an empty string if not found. Example:
// Route definition: server.GET("/api/v1/users", handler)
// Request: GET /api/v1/users
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
version := ctx.APIVersion() // "v1"
}
func (*Context) BadGateway ¶
BadGateway handles an error by returning an HTTP error response with status code 502. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) BadRequest ¶
BadRequest handles an error by returning an HTTP error response with status code 400. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) Body ¶
Body returns the request body as bytes with default size limit. Be careful with this method as it reads the entire body into memory. Use ReadWithLimit for better control over memory usage. Example:
// Request: POST /api/users
// Body: {"name": "John", "age": 30}
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
body := ctx.Body() // []byte(`{"name": "John", "age": 30}`)
}
func (*Context) ClientIP ¶
ClientIP returns the real client IP address, considering proxy headers. It checks common proxy headers in order of preference and validates IP addresses. Falls back to RemoteAddr if no valid IP is found in headers.
Headers checked (in order):
- CF-Connecting-IP (Cloudflare)
- True-Client-IP (Akamai, Cloudflare)
- X-Real-IP (nginx)
- X-Forwarded-For (first valid IP)
- X-Client-IP
- X-Forwarded
- X-Cluster-Client-IP
- Forwarded (RFC 7239)
Example:
clientIP := servex.C(w, r).ClientIP()
func (*Context) ClientIPWithTrustedProxies ¶
ClientIPWithTrustedProxies returns the real client IP address, but only trusts proxy headers if the request comes from a trusted proxy network. This is more secure when you know which proxies to trust.
Example:
trustedNets := []string{"10.0.0.0/8", "172.16.0.0/12"}
clientIP := servex.C(w, r).ClientIPWithTrustedProxies(trustedNets)
func (*Context) Conflict ¶
Conflict handles an error by returning an HTTP error response with status code 409. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) Error ¶
Error handles errors by sending standardized HTTP error responses.
This method provides consistent error handling across your application with proper logging integration and optional client error exposure. It formats error messages and manages error context for middleware.
Features:
- Consistent error response format
- Integration with logging middleware
- Configurable error exposure to clients
- Support for formatted error messages
- Automatic HTTP status code handling
Parameters:
- err: The underlying error (logged but not always exposed to client)
- code: HTTP status code (400, 401, 404, 500, etc.)
- msg: User-friendly error message (can include format verbs)
- fields: Optional key-value pairs for additional error context
The response format is JSON: {"message": "error description", "field1": "value1", "field2": "value2"}
Example:
// Simple error
ctx.Error(err, 400, "Invalid request")
// Formatted error message
ctx.Error(err, 404, "User not found", "user_id", userID) -> {"message": "User not found", "user_id": "123"}
// Use helper methods for common cases
ctx.BadRequest(err, "Invalid JSON payload")
ctx.NotFound(err, "Resource not found")
ctx.InternalServerError(err, "Database connection failed", "database_name", "users") -> {"message": "Database connection failed", "database_name": "users"}
Note: Do not modify the ResponseWriter after calling this method. This method should typically be followed by a return statement.
func (*Context) Forbidden ¶
Forbidden handles an error by returning an HTTP error response with status code 403. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) FormValue ¶
FormValue returns the value of the form field for the given key. Example:
// Request: POST /api/users
// Form: name=John&age=30
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
name := ctx.FormValue("name") // "John"
age := ctx.FormValue("age") // "30"
}
func (*Context) Header ¶
Header returns the value of the request header with the given name. If multiple values are present, they are joined with a comma and space ", ". Example:
// Request: GET /api/users
// Header: X-API-Key: abc, def
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
apiKey := ctx.Header("X-API-Key") // "abc, def"
}
func (*Context) InternalServerError ¶
InternalServerError handles an error by returning an HTTP error response with status code 500. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) JSON ¶
JSON is an alias for Context.Response with 200 code.
func (*Context) MethodNotAllowed ¶ added in v2.1.0
MethodNotAllowed handles an error by returning an HTTP error response with status code 405. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
It sends a 'Method not allowed' error response.
It is a shortcut for Context.Error.
func (*Context) NoLog ¶
func (ctx *Context) NoLog()
NoLog marks to not log the request after returning from the handler.
func (*Context) NotAcceptable ¶
NotAcceptable handles an error by returning an HTTP error response with status code 406. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) NotFound ¶
NotFound handles an error by returning an HTTP error response with status code 404. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) NotImplemented ¶
NotImplemented handles an error by returning an HTTP error response with status code 501. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) ParseUnixFromQuery ¶
func (*Context) Path ¶
Path returns the value of a URL path parameter.
Path parameters are variables embedded in the URL path pattern, defined using curly braces in route definitions. They are extracted when the route matches the incoming request.
Parameters:
- key: The name of the path parameter (without curly braces)
Returns the value extracted from the URL path, or an empty string if the parameter doesn't exist in the route.
Example:
// Route definition: server.GET("/users/{id}/posts/{postID}", handler)
// Request: GET /users/123/posts/456
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
userID := ctx.Path("id") // "123"
postID := ctx.Path("postID") // "456"
missing := ctx.Path("foo") // ""
ctx.JSON(map[string]string{
"user_id": userID,
"post_id": postID,
})
}
func (*Context) PreconditionFailed ¶ added in v2.1.0
MethodConflict handles an error by returning an HTTP error response with status code 409. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) Query ¶
Query returns the value of a URL query parameter.
Query parameters are the key-value pairs that appear after the "?" in a URL. For example, in "GET /users?page=2&limit=10", this method can extract "page" and "limit" values.
Parameters:
- key: The name of the query parameter
Returns the first value associated with the key, or an empty string if the parameter doesn't exist.
Example:
// URL: /api/users?page=2&limit=10&sort=name
page := ctx.Query("page") // "2"
limit := ctx.Query("limit") // "10"
sort := ctx.Query("sort") // "name"
missing := ctx.Query("foo") // ""
func (*Context) Read ¶
Read reads the request body with size limit to prevent DoS attacks. It is a shortcut for ReadWithLimit with configured default size. Example:
// Request: POST /api/users
// Body: {"name": "John", "age": 30}
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
body, err := ctx.Read() // []byte(`{"name": "John", "age": 30}`)
}
func (*Context) ReadAndValidate ¶
ReadAndValidate reads a JSON from the request body to the provided variable and validates it with size limits. You should provide a pointer to the variable. Example:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func (u *User) Validate() error {
if u.Name == "" {
return errors.New("name is required")
}
return nil
}
func createUser(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
var user User
if err := ctx.ReadAndValidate(&user); err != nil {
ctx.BadRequest(err, "Invalid JSON payload")
return
}
// Process user...
ctx.JSON(map[string]string{"status": "created"})
}
func (*Context) ReadAndValidateWithLimit ¶
func (ctx *Context) ReadAndValidateWithLimit(body interface{ Validate() error }, maxSize int64) error
ReadAndValidateWithLimit reads a JSON from the request body to the provided variable and validates it with size limits. You should provide a pointer to the variable. Example:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func (u *User) Validate() error {
if u.Name == "" {
return errors.New("name is required")
}
return nil
}
func createUser(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
var user User
if err := ctx.ReadAndValidateWithLimit(&user, 1024); err != nil {
ctx.BadRequest(err, "Invalid JSON payload")
return
}
// Process user...
ctx.JSON(map[string]string{"status": "created"})
}
func (*Context) ReadFile ¶
ReadFile reads a file from the request body with configurable size limits.
Parameters:
- fileKey: The key of the file in the request
Example:
// Request: POST /api/users
// Form: file=user.txt
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
file, header, err := ctx.ReadFile("file") // []byte(`user.txt`), *multipart.FileHeader, nil
}
func (*Context) ReadFileWithLimit ¶
func (ctx *Context) ReadFileWithLimit(fileKey string, maxMemory, maxFileSize int64) ([]byte, *multipart.FileHeader, error)
ReadFileWithLimit reads a file from the request body with specific size limits.
Parameters:
- fileKey: The key of the file in the request
- maxMemory: The maximum memory to use for the file
- maxFileSize: The maximum size of the file
Example:
// Request: POST /api/users
// Form: file=user.txt
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
file, header, err := ctx.ReadFileWithLimit("file", 1024, 1024) // []byte(`user.txt`), *multipart.FileHeader, nil
}
func (*Context) ReadJSON ¶
ReadJSON reads and parses JSON from the request body into the provided variable.
The method automatically applies size limits to prevent DoS attacks and validates that the content is valid JSON. You must provide a pointer to the variable where the JSON should be unmarshaled.
Features:
- Automatic size limiting (configurable via WithMaxJSONBodySize)
- Memory-safe reading with io.LimitReader
- Detailed error messages for debugging
Parameters:
- body: Pointer to the variable where JSON will be unmarshaled
Example:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func createUser(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
var user User
if err := ctx.ReadJSON(&user); err != nil {
ctx.BadRequest(err, "Invalid JSON payload")
return
}
// Process user...
ctx.JSON(map[string]string{"status": "created"})
}
func (*Context) ReadJSONWithLimit ¶
ReadJSONWithLimit reads and parses JSON from the request body into the provided variable.
The method applies size limits to prevent DoS attacks and validates that the content is valid JSON. You must provide a pointer to the variable where the JSON should be unmarshaled.
Features:
- Automatic size limiting (configurable via WithMaxJSONBodySize)
- Memory-safe reading with io.LimitReader
- Detailed error messages for debugging
Parameters:
- body: Pointer to the variable where JSON will be unmarshaled
Example:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func createUser(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
var user User
if err := ctx.ReadJSONWithLimit(&user, 1024); err != nil {
ctx.BadRequest(err, "Invalid JSON payload")
return
}
// Process user...
ctx.JSON(map[string]string{"status": "created"})
}
func (*Context) ReadWithLimit ¶
ReadWithLimit reads the request body with a specific size limit. Example:
// Request: POST /api/users
// Body: {"name": "John", "age": 30}
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
body, err := ctx.ReadWithLimit(1024) // []byte(`{"name": "John", "age": 30}`)
}
func (*Context) Redirect ¶ added in v2.1.0
Redirect performs an HTTP redirect to the specified URL with the given status code. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
- code: HTTP status code (301, 302, 303, 307, 308)
Example:
// Temporary redirect
ctx.Redirect("/login", 302)
// Permanent redirect
ctx.Redirect("https://example.com/new-path", 301)
func (*Context) RedirectNotModified ¶ added in v2.1.0
func (ctx *Context) RedirectNotModified()
RedirectNotModified performs a "Not Modified" redirect (HTTP 304) to indicate that the resource has not been modified since the last request. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
This is typically used with conditional requests (If-Modified-Since, If-None-Match).
Example:
if !isModified {
ctx.RedirectNotModified()
return
}
func (*Context) RedirectPermanent ¶ added in v2.1.0
RedirectPermanent performs a permanent redirect (HTTP 301) to the specified URL. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
Example:
ctx.RedirectPermanent("https://example.com/new-path")
func (*Context) RedirectPermanentPreserveMethod ¶ added in v2.1.0
RedirectPermanentPreserveMethod performs a permanent redirect (HTTP 308) to the specified URL. Unlike 301, this guarantees that the request method and body will be preserved. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
Example:
ctx.RedirectPermanentPreserveMethod("https://example.com/api/v2/users")
func (*Context) RedirectSeeOther ¶ added in v2.1.0
RedirectSeeOther performs a "See Other" redirect (HTTP 303) to the specified URL. This is typically used after a POST request to redirect to a GET endpoint. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
Example:
// After processing a form submission
ctx.RedirectSeeOther("/success")
func (*Context) RedirectTemporary ¶ added in v2.1.0
RedirectTemporary performs a temporary redirect (HTTP 302) to the specified URL. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
Example:
ctx.RedirectTemporary("/login")
func (*Context) RedirectTemporaryPreserveMethod ¶ added in v2.1.0
RedirectTemporaryPreserveMethod performs a temporary redirect (HTTP 307) to the specified URL. Unlike 302, this guarantees that the request method and body will be preserved. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- url: The URL to redirect to
Example:
ctx.RedirectTemporaryPreserveMethod("/api/v2/users")
func (*Context) RedirectToHTTPS ¶ added in v2.1.0
RedirectToHTTPS redirects the current HTTP request to its HTTPS equivalent. This method preserves the host, path, and query parameters while changing the scheme to HTTPS. It uses a permanent redirect (HTTP 301) by default to encourage browsers and search engines to update their links to use HTTPS. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- permanent: If true, uses HTTP 301 (permanent redirect). If false, uses HTTP 302 (temporary redirect)
Example:
// In a middleware or handler
if ctx.r.TLS == nil && ctx.r.Header.Get("X-Forwarded-Proto") != "https" {
ctx.RedirectToHTTPS(true) // Permanent redirect
return
}
// Temporary redirect (useful during testing)
ctx.RedirectToHTTPS(false)
func (*Context) RedirectToHTTPSPermanent ¶ added in v2.1.0
func (ctx *Context) RedirectToHTTPSPermanent()
RedirectToHTTPSPermanent redirects the current HTTP request to its HTTPS equivalent using a permanent redirect (HTTP 301). This is a convenience method for the most common HTTPS redirect scenario. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Example:
// In a middleware
if ctx.r.TLS == nil {
ctx.RedirectToHTTPSPermanent()
return
}
func (*Context) RedirectToHTTPSTemporary ¶ added in v2.1.0
func (ctx *Context) RedirectToHTTPSTemporary()
RedirectToHTTPSTemporary redirects the current HTTP request to its HTTPS equivalent using a temporary redirect (HTTP 302). This is useful during development or testing when you don't want browsers to cache the redirect. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Example:
// During development/testing
if ctx.r.TLS == nil {
ctx.RedirectToHTTPSTemporary()
return
}
func (*Context) RemoteAddr ¶
RemoteAddr returns the remote address of the request. This is the direct connection address and may be a proxy IP. For real client IP detection, use ClientIP() instead.
func (*Context) RequestEntityTooLarge ¶ added in v2.1.0
RequestEntityTooLarge handles an error by returning an HTTP error response with status code 413. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) Response ¶
Response writes an HTTP response with the specified status code and optional body.
This is the primary method for sending responses. It automatically handles content type detection, header setting, and proper HTTP response formatting.
Supported body types:
- []byte: Written directly with detected content type
- string: Written as text/plain with UTF-8 charset
- any other type: Marshaled to JSON with application/json content type
- nil: Sends only status code with no body
Features:
- Automatic Content-Type header setting
- Content-Length header calculation
- JSON marshaling with error handling
- Memory-efficient for large responses
Parameters:
- code: HTTP status code (e.g., 200, 404, 500)
- bodyRaw: Optional response body (supports multiple types)
Example:
// JSON response
ctx.Response(200, map[string]string{"message": "success"})
// String response
ctx.Response(200, "Hello, World!")
// Byte response (e.g., file content)
ctx.Response(200, fileBytes)
// Status-only response
ctx.Response(204)
Note: Do not modify the ResponseWriter after calling this method. This method should typically be the last operation in your handler.
func (*Context) ResponseFile ¶
ResponseFile writes the file to the http.ResponseWriter. It sets the Content-Type header to the provided mime type. It sets the Content-Disposition header to "attachment; filename=" + filename (safely sanitized). It sets the Content-Length header to the length of the body. Parameters:
- filename: The name of the file
- mimeType: The mime type of the file
- body: The body of the file
Example:
// Request: GET /api/users/123/avatar.png
// Response: 200 OK
// Content-Type: image/png
// Content-Disposition: attachment; filename="avatar.png"
// Content-Length: 12345
// Body: file content
func handler(w http.ResponseWriter, r *http.Request) {
ctx := servex.C(w, r)
ctx.ResponseFile("avatar.png", "image/png", fileBytes)
}
func (*Context) ServiceUnavailable ¶
ServiceUnavailable handles an error by returning an HTTP error response with status code 503. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) SetContentType ¶
SetContentType sets the Content-Type header.
func (*Context) SetCookie ¶
SetCookie sets the cookie with the given name, value, maxAge, secure and httpOnly. maxAge is the time in seconds until the cookie expires. If maxAge < 0, the cookie is deleted. secure specifies if the cookie should only be transmitted over HTTPS. httpOnly prevents the cookie from being accessed through JavaScript, enhancing security against XSS attacks.
func (*Context) SetDeleteCookie ¶
SetDeleteCookie sets the cookie with the given name to be deleted.
func (*Context) SetHeader ¶
SetHeader sets the value of the response header with the given name. If multiple values are provided, they are added to the header.
func (*Context) SetRawCookie ¶
SetRawCookie sets the cookie with the given http.Cookie.
func (*Context) TooManyRequests ¶
TooManyRequests handles an error by returning an HTTP error response with status code 429. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) Unauthorized ¶
Unauthorized handles an error by returning an HTTP error response with status code 401. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) UnprocessableEntity ¶
StatusUnprocessableEntity handles an error by returning an HTTP error response with status code 422. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
func (*Context) UnsupportedMediaType ¶ added in v2.1.0
UnsupportedMediaType handles an error by returning an HTTP error response with status code 415. You should not modify the http.ResponseWriter after calling this method. You will probably want to return from your handler after calling this method.
Parameters:
- err: The error to log and send to the client
- msg: The error message to send to the client
- fields: Optional fields for the error message
It is a shortcut for Context.Error.
type DefaultAuditLogger ¶
type DefaultAuditLogger struct {
Logger Logger
// Configuration for audit logging
IncludeHeaders bool
SensitiveHeaders []string // Headers to exclude from logging for privacy
MaxDetailSize int // Maximum size of detail fields
EnableGeoLocation bool // Enable geographical context (requires external service)
}
DefaultAuditLogger implements AuditLogger using the standard logger interface
func NewDefaultAuditLogger ¶
func NewDefaultAuditLogger(logger Logger) *DefaultAuditLogger
NewDefaultAuditLogger creates a new default audit logger
func (*DefaultAuditLogger) LogAuthenticationEvent ¶
func (al *DefaultAuditLogger) LogAuthenticationEvent(eventType AuditEventType, r *http.Request, userID string, success bool, details map[string]any)
LogAuthenticationEvent logs authentication-related events
func (*DefaultAuditLogger) LogCSRFEvent ¶
func (al *DefaultAuditLogger) LogCSRFEvent(eventType AuditEventType, r *http.Request, details map[string]any)
LogCSRFEvent logs CSRF protection events
func (*DefaultAuditLogger) LogFilterEvent ¶
func (al *DefaultAuditLogger) LogFilterEvent(eventType AuditEventType, r *http.Request, filterType, filterValue, rule string)
LogFilterEvent logs request filtering events
func (*DefaultAuditLogger) LogRateLimitEvent ¶
func (al *DefaultAuditLogger) LogRateLimitEvent(r *http.Request, key string, details map[string]any)
LogRateLimitEvent logs rate limiting events
func (*DefaultAuditLogger) LogSecurityEvent ¶
func (al *DefaultAuditLogger) LogSecurityEvent(event AuditEvent)
LogSecurityEvent logs a structured security event
func (*DefaultAuditLogger) LogSuspiciousActivity ¶
func (al *DefaultAuditLogger) LogSuspiciousActivity(r *http.Request, activityType string, details map[string]any)
LogSuspiciousActivity logs suspicious or anomalous activity
type DynamicFilterMethods ¶
type DynamicFilterMethods interface {
// IP Management
AddBlockedIP(ip string) error
RemoveBlockedIP(ip string) error
AddAllowedIP(ip string) error
RemoveAllowedIP(ip string) error
IsIPBlocked(ip string) bool
GetBlockedIPs() []string
GetAllowedIPs() []string
// User-Agent Management
AddBlockedUserAgent(userAgent string) error
RemoveBlockedUserAgent(userAgent string) error
AddAllowedUserAgent(userAgent string) error
RemoveAllowedUserAgent(userAgent string) error
IsUserAgentBlocked(userAgent string) bool
GetBlockedUserAgents() []string
GetAllowedUserAgents() []string
// Clear all rules
ClearAllBlockedIPs() error
ClearAllAllowedIPs() error
ClearAllBlockedUserAgents() error
ClearAllAllowedUserAgents() error
}
DynamicFilterMethods provides methods to modify filter rules at runtime. These methods are thread-safe and allow dynamic adaptation of filtering rules.
type ErrorLogger ¶
type ErrorResponse ¶
type ErrorResponse struct {
Message string `json:"message"`
}
ErrorResponse represents a JSON for an error response.
type Filter ¶
type Filter struct {
// contains filtered or unexported fields
}
Filter holds the compiled filtering logic and patterns. This struct is responsible for all filtering logic.
func RegisterFilterMiddleware ¶
func RegisterFilterMiddleware(router MiddlewareRouter, cfg FilterConfig, auditLogger ...AuditLogger) (*Filter, error)
RegisterFilterMiddleware adds request filtering middleware to the router. If the config has no filters configured, no middleware will be registered. Returns the created filter instance for dynamic modification, or nil if no filter was created.
Example ¶
// Create a new router
router := mux.NewRouter()
// Configure filtering
filterConfig := FilterConfig{
// Only allow requests from specific IP ranges
AllowedIPs: []string{"192.168.1.0/24", "10.0.0.1"},
// Block known bad bots
BlockedUserAgents: []string{
"BadCrawler/1.0",
},
BlockedUserAgentsRegex: []string{
".*[Bb]ot.*",
".*[Ss]pider.*",
},
// Require API key in specific header
AllowedHeadersRegex: map[string][]string{
"X-API-Key": {"key-.*"},
},
// Block requests with debug parameter
BlockedQueryParams: map[string][]string{
"debug": {"true", "1"},
},
// Don't filter health check endpoint
ExcludePaths: []string{"/health"},
// Custom response for blocked requests
StatusCode: http.StatusUnauthorized,
Message: "Access denied by security policy",
}
// Register the filter middleware
RegisterFilterMiddleware(router, filterConfig)
// Add your routes
router.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Users API")
})
router.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "OK")
})
func RegisterLocationBasedFilterMiddleware ¶
func RegisterLocationBasedFilterMiddleware(router MiddlewareRouter, locationConfigs []LocationFilterConfig, auditLogger ...AuditLogger) (*Filter, error)
RegisterLocationBasedFilterMiddleware adds location-based filtering middleware to the router. This allows different filter configurations for different URL paths. If no location configs are provided or none are enabled, no middleware will be registered.
The middleware will: 1. Check each location config in order for path pattern matches 2. Use the first matching config's filter rules 3. Fall back to no filtering if no patterns match
Example usage:
err := RegisterLocationBasedFilterMiddleware(router, []LocationFilterConfig{
{
PathPatterns: []string{"/api/*"},
Config: FilterConfig{
AllowedIPs: []string{"192.168.1.0/24"},
StatusCode: http.StatusForbidden,
Message: "API access restricted",
},
},
{
PathPatterns: []string{"/admin/*"},
Config: FilterConfig{
AllowedIPs: []string{"10.0.0.0/8"},
BlockedUserAgents: []string{"Bot", "Crawler"},
StatusCode: http.StatusForbidden,
Message: "Admin access denied",
},
},
}, auditLogger)
func (*Filter) AddAllowedIP ¶
AddAllowedIP dynamically adds an IP address or CIDR range to the allowed list. This method is thread-safe and takes effect immediately.
func (*Filter) AddAllowedUserAgent ¶
AddAllowedUserAgent dynamically adds a User-Agent string to the allowed list. This method is thread-safe and takes effect immediately.
func (*Filter) AddBlockedIP ¶
AddBlockedIP dynamically adds an IP address or CIDR range to the blocked list. This method is thread-safe and takes effect immediately.
Example:
// Block a specific IP that accessed a honeypot
err := filter.AddBlockedIP("192.168.1.100")
// Block an entire subnet
err := filter.AddBlockedIP("10.0.0.0/24")
func (*Filter) AddBlockedUserAgent ¶
AddBlockedUserAgent dynamically adds a User-Agent string to the blocked list. This method is thread-safe and takes effect immediately.
Example:
// Block a specific bot after it accessed a honeypot
err := filter.AddBlockedUserAgent("BadBot/1.0")
func (*Filter) ClearAllAllowedIPs ¶
ClearAllAllowedIPs removes all allowed IP addresses. This method is thread-safe and takes effect immediately.
func (*Filter) ClearAllAllowedUserAgents ¶
ClearAllAllowedUserAgents removes all allowed User-Agent strings. This method is thread-safe and takes effect immediately.
func (*Filter) ClearAllBlockedIPs ¶
ClearAllBlockedIPs removes all blocked IP addresses. This method is thread-safe and takes effect immediately.
func (*Filter) ClearAllBlockedUserAgents ¶
ClearAllBlockedUserAgents removes all blocked User-Agent strings. This method is thread-safe and takes effect immediately.
func (*Filter) GetAllowedIPs ¶
GetAllowedIPs returns a copy of the current allowed IP list. This method is thread-safe.
func (*Filter) GetAllowedUserAgents ¶
GetAllowedUserAgents returns a copy of the current allowed User-Agent list. This method is thread-safe.
func (*Filter) GetBlockedIPs ¶
GetBlockedIPs returns a copy of the current blocked IP list. This method is thread-safe.
func (*Filter) GetBlockedUserAgents ¶
GetBlockedUserAgents returns a copy of the current blocked User-Agent list. This method is thread-safe.
func (*Filter) IsIPBlocked ¶
IsIPBlocked checks if an IP address is currently blocked. This method is thread-safe.
func (*Filter) IsUserAgentBlocked ¶
IsUserAgentBlocked checks if a User-Agent string is currently blocked. This method is thread-safe.
func (*Filter) RemoveAllowedIP ¶
RemoveAllowedIP dynamically removes an IP address or CIDR range from the allowed list. This method is thread-safe and takes effect immediately.
func (*Filter) RemoveAllowedUserAgent ¶
RemoveAllowedUserAgent dynamically removes a User-Agent string from the allowed list. This method is thread-safe and takes effect immediately.
func (*Filter) RemoveBlockedIP ¶
RemoveBlockedIP dynamically removes an IP address or CIDR range from the blocked list. This method is thread-safe and takes effect immediately.
func (*Filter) RemoveBlockedUserAgent ¶
RemoveBlockedUserAgent dynamically removes a User-Agent string from the blocked list. This method is thread-safe and takes effect immediately.
type FilterBlockReason ¶
type FilterBlockReason struct {
Type AuditEventType // The audit event type for this block
Value string // The specific value that caused the block
Rule string // The rule that caused the block
}
FilterBlockReason represents the reason why a request was blocked
type FilterConfig ¶
type FilterConfig struct {
// AllowedIPs is a list of IP addresses or CIDR ranges that are allowed.
// Only requests from these IPs will be allowed. All other IPs are blocked.
// Set via WithAllowedIPs().
//
// IP formats supported:
// - Single IP: "192.168.1.100"
// - CIDR range: "10.0.0.0/8", "192.168.1.0/24"
// - IPv6: "2001:db8::1", "2001:db8::/32"
//
// Use cases:
// - Restrict admin interfaces to office IPs
// - Allow only partner/client IPs
// - Internal-only APIs
// - Development/staging environment protection
//
// If empty, all IPs are allowed unless blocked by BlockedIPs.
AllowedIPs []string
// BlockedIPs is a list of IP addresses or CIDR ranges that are blocked.
// Requests from these IPs will be denied with the configured status code.
// Set via WithBlockedIPs().
//
// IP formats supported:
// - Single IP: "192.168.1.100"
// - CIDR range: "10.0.0.0/8", "192.168.1.0/24"
// - IPv6: "2001:db8::1", "2001:db8::/32"
//
// Use cases:
// - Block known malicious IPs
// - Prevent competitor scraping
// - Geographic restrictions
// - Temporary IP bans
//
// Note: BlockedIPs takes precedence over AllowedIPs.
// If an IP is in both lists, it will be blocked.
BlockedIPs []string
// AllowedUserAgents is a list of exact User-Agent strings that are allowed.
// Only requests with these exact User-Agent headers will be allowed.
// Set via WithAllowedUserAgents().
//
// For pattern matching instead of exact strings, use AllowedUserAgentsRegex.
//
// Use cases:
// - Restrict API to your apps only
// - Block automated scrapers
// - Allow only supported browsers
// - Partner API access control
//
// If empty, all User-Agents are allowed unless blocked by BlockedUserAgents.
AllowedUserAgents []string
// AllowedUserAgentsRegex is a list of regex patterns for allowed User-Agents.
// Only requests with User-Agent headers matching these patterns will be allowed.
// Set via WithAllowedUserAgentsRegex().
//
// Regex features:
// - Use standard Go regex syntax
// - Case-sensitive matching
// - ^ and $ for exact matching
// - \d+ for version numbers
// - | for alternatives
//
// This is more flexible than AllowedUserAgents for version-aware filtering.
//
// Examples:
// - `Chrome/\d+\.\d+` - Any Chrome browser
// - `^MyApp/\d+\.\d+ \((iOS|Android)\)$` - Your app with any version
AllowedUserAgentsRegex []string
// BlockedUserAgents is a list of exact User-Agent strings that are blocked.
// Requests with these exact User-Agent headers will be denied.
// Set via WithBlockedUserAgents().
//
// For pattern matching instead of exact strings, use BlockedUserAgentsRegex.
//
// Use cases:
// - Block automated scrapers
// - Prevent bot traffic
// - Block specific tools
// - Temporary user-agent bans
//
// Note: BlockedUserAgents takes precedence over AllowedUserAgents.
BlockedUserAgents []string
// BlockedUserAgentsRegex is a list of regex patterns for blocked User-Agents.
// Requests with User-Agent headers matching these patterns will be denied.
// Set via WithBlockedUserAgentsRegex().
//
// Regex features:
// - (?i) for case-insensitive matching
// - Use standard Go regex syntax
// - ^ and $ for exact matching
// - | for alternatives
//
// Examples:
// - `(?i)(bot|crawler|spider|scraper)` - Block all bots and crawlers
// - `^(curl|wget|python-requests)` - Block command line tools
//
// Note: BlockedUserAgentsRegex takes precedence over AllowedUserAgentsRegex.
BlockedUserAgentsRegex []string
// AllowedHeaders is a map of header names to exact allowed values.
// Only requests with headers matching the specified exact values will be allowed.
// Set via WithAllowedHeaders().
//
// Header matching:
// - Header names are case-insensitive
// - Values must match exactly (case-sensitive)
// - Multiple allowed values per header
// - All specified headers must be present
//
// Use cases:
// - API version enforcement
// - Content-Type validation
// - Custom authentication schemes
// - Partner-specific headers
//
// For pattern matching instead of exact values, use AllowedHeadersRegex.
AllowedHeaders map[string][]string
// AllowedHeadersRegex is a map of header names to regex patterns for allowed values.
// Only requests with headers matching the specified patterns will be allowed.
// Set via WithAllowedHeadersRegex().
//
// Regex features:
// - Header names are case-insensitive
// - Use standard Go regex syntax
// - ^ and $ for exact matching
// - Multiple patterns per header (OR logic)
//
// Examples:
// - "Authorization": [`^Bearer [A-Za-z0-9+/=]+$`] - Any Bearer token
// - "X-API-Version": [`^v\d+\.\d+$`] - Semantic versioning
//
// This is more flexible than AllowedHeaders for pattern-based validation.
AllowedHeadersRegex map[string][]string
// BlockedHeaders is a map of header names to exact blocked values.
// Requests with headers matching the specified exact values will be denied.
// Set via WithBlockedHeaders().
//
// Header matching:
// - Header names are case-insensitive
// - Values must match exactly (case-sensitive)
// - Multiple blocked values per header
// - Any matching header causes blocking
//
// Use cases:
// - Block deprecated API versions
// - Security header filtering
// - Malicious request detection
// - Legacy client blocking
//
// Note: BlockedHeaders takes precedence over AllowedHeaders.
BlockedHeaders map[string][]string
// BlockedHeadersRegex is a map of header names to regex patterns for blocked values.
// Requests with headers matching the specified patterns will be denied.
// Set via WithBlockedHeadersRegex().
//
// Regex features:
// - Header names are case-insensitive
// - (?i) for case-insensitive pattern matching
// - Use standard Go regex syntax
// - Multiple patterns per header (OR logic)
//
// Examples:
// - "X-Forwarded-For": [`(10\.0\.0\.|192\.168\.)`] - Block internal IPs
// - "User-Agent": [`(?i)(bot|crawler|spider)`] - Block bots
//
// Note: BlockedHeadersRegex takes precedence over AllowedHeadersRegex.
BlockedHeadersRegex map[string][]string
// AllowedQueryParams is a map of query parameter names to exact allowed values.
// Only requests with query parameters matching the specified exact values will be allowed.
// Set via WithAllowedQueryParams().
//
// Parameter matching:
// - Parameter names are case-sensitive
// - Values must match exactly (case-sensitive)
// - Multiple allowed values per parameter
// - All specified parameters must be present
//
// Use cases:
// - API parameter validation
// - Prevent SQL injection via query params
// - Business logic validation
// - Feature flag enforcement
//
// For pattern matching instead of exact values, use AllowedQueryParamsRegex.
AllowedQueryParams map[string][]string
// AllowedQueryParamsRegex is a map of query parameter names to regex patterns for allowed values.
// Only requests with query parameters matching the specified patterns will be allowed.
// Set via WithAllowedQueryParamsRegex().
//
// Regex features:
// - Parameter names are case-sensitive
// - Use standard Go regex syntax
// - ^ and $ for exact matching
// - Multiple patterns per parameter (OR logic)
//
// Examples:
// - "id": [`^\d+$`] - Numeric IDs only
// - "email": [`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`] - Email format
// - "uuid": [`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`] - UUID format
//
// This is more flexible than AllowedQueryParams for format validation.
AllowedQueryParamsRegex map[string][]string
// BlockedQueryParams is a map of query parameter names to exact blocked values.
// Requests with query parameters matching the specified exact values will be denied.
// Set via WithBlockedQueryParams().
//
// Parameter matching:
// - Parameter names are case-sensitive
// - Values must match exactly (case-sensitive)
// - Multiple blocked values per parameter
// - Any matching parameter causes blocking
//
// Use cases:
// - Security parameter filtering
// - Debug mode blocking in production
// - Malicious query detection
// - Legacy parameter deprecation
//
// Note: BlockedQueryParams takes precedence over AllowedQueryParams.
BlockedQueryParams map[string][]string
// BlockedQueryParamsRegex is a map of query parameter names to regex patterns for blocked values.
// Requests with query parameters matching the specified patterns will be denied.
// Set via WithBlockedQueryParamsRegex().
//
// Regex features:
// - Parameter names are case-sensitive
// - (?i) for case-insensitive pattern matching
// - Use standard Go regex syntax
// - Multiple patterns per parameter (OR logic)
//
// Examples:
// - "search": [`(?i)(union|select|drop|delete|insert|update)`] - Block SQL injection
// - "callback": [`(?i)(<script|javascript:|vbscript:)`] - Block script injection
// - "query": [`.{1000,}`] - Block excessive length
//
// Note: BlockedQueryParamsRegex takes precedence over AllowedQueryParamsRegex.
BlockedQueryParamsRegex map[string][]string
// ExcludePaths are paths that should be excluded from request filtering.
// Requests to these paths will bypass all filtering rules.
// Set via WithFilterExcludePaths().
//
// Common exclusions:
// - Health checks: "/health", "/ping"
// - Public APIs: "/public/*", "/api/public/*"
// - Documentation: "/docs/*", "/swagger/*"
// - Static assets: "/static/*", "/assets/*"
// - Monitoring: "/metrics", "/status"
//
// Path matching supports wildcards (*) for pattern matching.
// Excluded paths bypass ALL filtering rules (IP, User-Agent, headers, query params).
ExcludePaths []string
// IncludePaths are paths that should be included in request filtering.
// If set, only requests to these paths will be subject to filtering rules.
// Set via WithFilterIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to be filtered
// 2. Paths in ExcludePaths are then excluded from filtering
//
// Use cases:
// - Protect only sensitive endpoints
// - Apply filtering to specific API versions
// - Filter only external-facing endpoints
// - Granular security control
//
// Path matching supports wildcards (*) for pattern matching.
IncludePaths []string
// StatusCode is the HTTP status code returned when requests are blocked by filters.
// Set via WithFilterStatusCode(). Default is 403 (Forbidden) if not set.
//
// Common status codes:
// - 403 Forbidden (recommended) - Clear about blocking
// - 404 Not Found - Hides endpoint existence
// - 401 Unauthorized - Suggests authentication needed
// - 429 Too Many Requests - Can mislead attackers
//
// Choose based on your security strategy and user experience needs.
StatusCode int
// Message is the response body returned when requests are blocked by filters.
// Set via WithFilterMessage(). Default is "Request blocked by security filter" if not set.
//
// Best practices:
// - Be clear but not too specific about the filter
// - Include contact information for legitimate users
// - Avoid revealing security implementation details
// - Keep messages user-friendly
//
// The message is returned as plain text in the response body.
Message string
// TrustedProxies is a list of trusted proxy IP addresses or CIDR ranges
// for accurate client IP detection in filtering.
// Set via WithFilterTrustedProxies().
//
// How it works:
// - Without trusted proxies: Uses r.RemoteAddr (proxy IP) for IP filtering
// - With trusted proxies: Uses X-Forwarded-For or X-Real-IP headers
//
// Common proxy ranges:
// - AWS ALB: Check AWS documentation for current ranges
// - Cloudflare: Use Cloudflare's published IP ranges
// - Internal load balancers: Your internal network ranges
// - Docker networks: 172.16.0.0/12, 10.0.0.0/8
//
// Security considerations:
// - Only list IPs you actually trust
// - Malicious clients can spoof X-Forwarded-For headers
// - Ensure proxy properly validates and forwards real client IPs
TrustedProxies []string
}
FilterConfig holds configuration for request filtering middleware. This enables filtering requests based on IP addresses, User-Agents, headers, and query parameters.
Request filtering helps protect your server from:
- Malicious IP addresses
- Bot and scraper traffic
- Invalid or dangerous requests
- Geographic restrictions
- Content-based attacks
Example configuration:
filter := FilterConfig{
AllowedIPs: []string{"192.168.1.0/24", "10.0.0.0/8"},
BlockedUserAgents: []string{"BadBot", "Scraper"},
AllowedHeaders: map[string][]string{
"X-API-Version": {"v1", "v2"},
},
StatusCode: 403,
Message: "Access denied by security filter",
}
This is a pure data structure without any logic - the filtering logic is implemented in the middleware that uses this configuration.
type FilterConfiguration ¶
type FilterConfiguration struct {
AllowedIPs []string `yaml:"allowed_ips" json:"allowed_ips" env:"SERVEX_FILTER_ALLOWED_IPS"`
BlockedIPs []string `yaml:"blocked_ips" json:"blocked_ips" env:"SERVEX_FILTER_BLOCKED_IPS"`
AllowedUserAgents []string `yaml:"allowed_user_agents" json:"allowed_user_agents" env:"SERVEX_FILTER_ALLOWED_USER_AGENTS"`
AllowedUserAgentsRegex []string `yaml:"allowed_user_agents_regex" json:"allowed_user_agents_regex" env:"SERVEX_FILTER_ALLOWED_USER_AGENTS_REGEX"`
BlockedUserAgents []string `yaml:"blocked_user_agents" json:"blocked_user_agents" env:"SERVEX_FILTER_BLOCKED_USER_AGENTS"`
BlockedUserAgentsRegex []string `yaml:"blocked_user_agents_regex" json:"blocked_user_agents_regex" env:"SERVEX_FILTER_BLOCKED_USER_AGENTS_REGEX"`
AllowedHeaders map[string][]string `yaml:"allowed_headers" json:"allowed_headers"`
AllowedHeadersRegex map[string][]string `yaml:"allowed_headers_regex" json:"allowed_headers_regex"`
BlockedHeaders map[string][]string `yaml:"blocked_headers" json:"blocked_headers"`
BlockedHeadersRegex map[string][]string `yaml:"blocked_headers_regex" json:"blocked_headers_regex"`
AllowedQueryParams map[string][]string `yaml:"allowed_query_params" json:"allowed_query_params"`
AllowedQueryParamsRegex map[string][]string `yaml:"allowed_query_params_regex" json:"allowed_query_params_regex"`
BlockedQueryParams map[string][]string `yaml:"blocked_query_params" json:"blocked_query_params"`
BlockedQueryParamsRegex map[string][]string `yaml:"blocked_query_params_regex" json:"blocked_query_params_regex"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_FILTER_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_FILTER_INCLUDE_PATHS"`
StatusCode int `yaml:"status_code" json:"status_code" env:"SERVEX_FILTER_STATUS_CODE"`
Message string `yaml:"message" json:"message" env:"SERVEX_FILTER_MESSAGE"`
TrustedProxies []string `yaml:"trusted_proxies" json:"trusted_proxies" env:"SERVEX_FILTER_TRUSTED_PROXIES"`
}
FilterConfiguration represents request filtering configuration
type HTTPSRedirectConfig ¶ added in v2.1.0
type HTTPSRedirectConfig struct {
// Enabled determines whether HTTP to HTTPS redirection is active.
// Must be set to true for automatic HTTPS redirection to work.
// Set via WithHTTPSRedirect() or WithHTTPSRedirectPermanent().
Enabled bool
// Permanent determines the type of redirect to use.
// If true, uses HTTP 301 (permanent redirect) for better SEO.
// If false, uses HTTP 302 (temporary redirect) for testing/development.
// Set via WithHTTPSRedirect() or WithHTTPSRedirectPermanent().
//
// Recommended values:
// - Production: true (301 permanent redirect)
// - Development/Testing: false (302 temporary redirect)
//
// Default: true (permanent redirect)
Permanent bool
// TrustedProxies is a list of trusted proxy IP addresses or CIDR ranges
// for accurate HTTP/HTTPS detection when behind load balancers or proxies.
// Set via WithHTTPSRedirectTrustedProxies().
//
// When behind proxies, the server cannot detect HTTPS from r.TLS alone.
// This setting allows checking X-Forwarded-Proto and similar headers
// only when the request comes from trusted proxy IPs.
//
// Common proxy ranges:
// - AWS ALB: Check AWS documentation for current ranges
// - Cloudflare: Use Cloudflare's published IP ranges
// - Internal load balancers: Your internal network ranges
// - Docker networks: 172.16.0.0/12, 10.0.0.0/8
//
// Security note: Only list IPs you actually trust. Malicious clients
// can spoof X-Forwarded-Proto headers if the proxy IP is trusted.
TrustedProxies []string
// ExcludePaths are paths that should be excluded from HTTPS redirection.
// Requests to these paths will not be redirected to HTTPS.
// Set via WithHTTPSRedirectExcludePaths().
//
// Common exclusions:
// - Health checks: "/health", "/ping" (for load balancers that use HTTP)
// - Let's Encrypt challenges: "/.well-known/acme-challenge/*"
// - Development endpoints: "/debug/*"
// - Legacy integrations that require HTTP: "/legacy/*"
//
// Path matching supports wildcards (*) for pattern matching.
// Use sparingly - most paths should use HTTPS for security.
ExcludePaths []string
// IncludePaths are paths that should be included in HTTPS redirection.
// If set, only requests to these paths will be redirected to HTTPS.
// Set via WithHTTPSRedirectIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to be considered for redirection
// 2. Paths in ExcludePaths are then excluded from redirection
//
// Use cases:
// - Gradual HTTPS migration: Start with specific paths
// - Mixed HTTP/HTTPS applications: Only secure sensitive areas
// - Testing HTTPS setup: Limit scope during testing
//
// Path matching supports wildcards (*) for pattern matching.
// Leave empty to redirect all paths (recommended for production).
IncludePaths []string
}
HTTPSRedirectConfig holds configuration for automatic HTTP to HTTPS redirection. This enables server-level enforcement of HTTPS connections by automatically redirecting all HTTP requests to their HTTPS equivalent.
Security benefits:
- Enforces encrypted connections
- Prevents accidental plain-text transmission
- Improves SEO rankings (search engines prefer HTTPS)
- Required for modern web features (Service Workers, Geolocation, etc.)
Example configuration:
httpsRedirect := HTTPSRedirectConfig{
Enabled: true,
Permanent: true,
TrustedProxies: []string{"10.0.0.0/8", "172.16.0.0/12"},
ExcludePaths: []string{"/health", "/.well-known/*"},
}
type HTTPSRedirectConfiguration ¶ added in v2.2.0
type HTTPSRedirectConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_SERVER_HTTPS_REDIRECT_ENABLED"`
Permanent bool `yaml:"permanent" json:"permanent" env:"SERVEX_SERVER_HTTPS_REDIRECT_PERMANENT"`
TrustedProxies []string `yaml:"trusted_proxies" json:"trusted_proxies" env:"SERVEX_SERVER_HTTPS_REDIRECT_TRUSTED_PROXIES"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_SERVER_HTTPS_REDIRECT_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_SERVER_HTTPS_REDIRECT_INCLUDE_PATHS"`
}
HTTPSRedirectConfiguration represents HTTPS redirection configuration
type HealthCheckConfig ¶
type HealthCheckConfig struct {
// Enabled indicates if health checking is enabled
Enabled bool `yaml:"enabled" json:"enabled"`
// DefaultInterval for health checks
DefaultInterval time.Duration `yaml:"default_interval" json:"default_interval"`
// Timeout for health check requests
Timeout time.Duration `yaml:"timeout" json:"timeout"`
// RetryCount before marking backend as unhealthy
RetryCount int `yaml:"retry_count" json:"retry_count"`
}
HealthCheckConfig configures health checking
type InitialUser ¶
type InitialUser struct {
// Username is the unique username for the user.
// This will be used for login and user identification.
//
// Requirements:
// - Must be unique across all users
// - Should follow your application's username policy
// - Cannot be empty
//
// Examples: "admin", "testuser", "service-account"
Username string
// Password is the plain text password for the user.
// The password will be automatically hashed before storing in the database.
//
// Security considerations:
// - Use strong passwords (consider password generators)
// - Minimum 8 characters recommended
// - Include mix of letters, numbers, and symbols
// - Never commit passwords to source control
// - Consider loading from environment variables
//
// Example: os.Getenv("ADMIN_PASSWORD") or "SecurePassword123!"
Password string
// Roles are the roles assigned to the user upon creation.
// These roles determine the user's permissions and access levels.
//
// Common roles:
// - "admin": Full system access
// - "user": Standard user access
// - "moderator": Content management access
// - "api": API-only access
//
// Users can have multiple roles for fine-grained permissions.
// Additional roles can be assigned later through user management.
Roles []UserRole
}
InitialUser represents a user to be created during server startup. This is used with AuthConfig.InitialUsers to seed the database with admin accounts or test users. Set via WithAuthInitialUsers().
Example usage:
initialUsers := []InitialUser{
{
Username: "admin",
Password: "secure-admin-password",
Roles: []UserRole{"admin", "user"},
},
{
Username: "testuser",
Password: "test-password",
Roles: []UserRole{"user"},
},
}
Security considerations:
- Use strong, unique passwords
- Consider loading passwords from environment variables
- Remove or change default passwords in production
- Limit to essential accounts only
type LoadBalancingStrategy ¶
type LoadBalancingStrategy string
LoadBalancingStrategy defines the load balancing algorithm
const ( // RoundRobinStrategy cycles through backends in order RoundRobinStrategy LoadBalancingStrategy = "round_robin" // WeightedRoundRobinStrategy cycles through backends based on weights WeightedRoundRobinStrategy LoadBalancingStrategy = "weighted_round_robin" // LeastConnectionsStrategy routes to backend with fewest active connections LeastConnectionsStrategy LoadBalancingStrategy = "least_connections" // RandomStrategy routes to a random backend RandomStrategy LoadBalancingStrategy = "random" // WeightedRandomStrategy routes to a random backend based on weights WeightedRandomStrategy LoadBalancingStrategy = "weighted_random" // IPHashStrategy routes based on client IP hash (session affinity) IPHashStrategy LoadBalancingStrategy = "ip_hash" )
type LocationFilterConfig ¶
type LocationFilterConfig struct {
// PathPatterns are the URL path patterns this config applies to.
// Supports wildcards using filepath.Match syntax (e.g., "/api/*", "/admin/*").
// If multiple patterns are provided, any match will apply this config.
//
// Examples:
// - ["/api/*"] - All API endpoints
// - ["/admin/*", "/dashboard/*"] - Admin and dashboard areas
// - ["/auth/login", "/auth/register"] - Specific auth endpoints
// - ["/upload/*"] - File upload endpoints
PathPatterns []string
// Config is the filter configuration to apply for matching paths.
// This contains all the filtering settings like allowed/blocked IPs,
// user agents, headers, query parameters, etc.
Config FilterConfig
}
LocationFilterConfig defines a filter configuration for specific locations. This allows different filter rules to be applied to different URL paths.
type LocationRateLimitConfig ¶
type LocationRateLimitConfig struct {
// PathPatterns are the URL path patterns this config applies to.
// Supports wildcards using filepath.Match syntax (e.g., "/api/*", "/admin/*").
// If multiple patterns are provided, any match will apply this config.
//
// Examples:
// - ["/api/*"] - All API endpoints
// - ["/admin/*", "/dashboard/*"] - Admin and dashboard areas
// - ["/auth/login", "/auth/register"] - Specific auth endpoints
// - ["/upload/*"] - File upload endpoints
PathPatterns []string
// Config is the rate limit configuration to apply for matching paths.
// This contains all the rate limiting settings like requests per interval,
// burst size, status codes, etc.
Config RateLimitConfig
}
LocationRateLimitConfig defines a rate limit configuration for specific locations. This allows different rate limits to be applied to different URL paths.
type Logger ¶
type Logger interface {
// Debug is using to log successful requests.
Debug(msg string, fields ...any)
// Info is using to log 'http(s) server started'
Info(msg string, fields ...any)
// Error is using to log request errors, panics, serve errors and shutodwn in StartContext errors
Error(msg string, fields ...any)
}
Logger is an interface for logger to log messages.
type LoggingConfiguration ¶
type LoggingConfiguration struct {
DisableRequestLogging bool `yaml:"disable_request_logging" json:"disable_request_logging" env:"SERVEX_LOGGING_DISABLE_REQUEST_LOGGING"`
NoLogClientErrors bool `yaml:"no_log_client_errors" json:"no_log_client_errors" env:"SERVEX_LOGGING_NO_LOG_CLIENT_ERRORS"`
LogFields []string `yaml:"log_fields" json:"log_fields" env:"SERVEX_LOGGING_LOG_FIELDS"`
}
LoggingConfiguration represents logging configuration
type MemoryAuthDatabase ¶
type MemoryAuthDatabase struct {
// contains filtered or unexported fields
}
MockAuthDatabase provides a mock implementation of the AuthDatabase interface for testing.
func NewMemoryAuthDatabase ¶
func NewMemoryAuthDatabase() *MemoryAuthDatabase
func (*MemoryAuthDatabase) FindAll ¶
func (db *MemoryAuthDatabase) FindAll(ctx context.Context) ([]User, error)
func (*MemoryAuthDatabase) FindByUsername ¶
func (*MemoryAuthDatabase) UpdateUser ¶
type Metrics ¶
type Metrics interface {
// HandleRequest is called on each request to collect metrics.
HandleRequest(r *http.Request)
// HandleResponse is called on each response to collect metrics.
HandleResponse(r *http.Request, w http.ResponseWriter, statusCode int, duration time.Duration)
}
Metrics is an interface for collecting metrics on each request. [Metrics.HandleRequest] is called on each request. [Metrics.HandleResponse] is called on each response.
type MiddlewareRouter ¶
type MiddlewareRouter interface {
// Use adds one or more middleware functions to the router.
// Middleware functions are executed in the order they are added.
Use(middleware ...mux.MiddlewareFunc)
}
MiddlewareRouter represents a router that supports adding middleware functions. This interface is typically implemented by router packages like gorilla/mux and allows servex to register its middleware functions with different router implementations.
The middleware functions registered through this interface provide essential features like logging, security headers, rate limiting, authentication, and more.
type NoopAuditLogger ¶
type NoopAuditLogger struct{}
NoopAuditLogger is a no-op implementation of AuditLogger
func (*NoopAuditLogger) LogAuthenticationEvent ¶
func (nal *NoopAuditLogger) LogAuthenticationEvent(eventType AuditEventType, r *http.Request, userID string, success bool, details map[string]any)
func (*NoopAuditLogger) LogCSRFEvent ¶
func (nal *NoopAuditLogger) LogCSRFEvent(eventType AuditEventType, r *http.Request, details map[string]any)
func (*NoopAuditLogger) LogFilterEvent ¶
func (nal *NoopAuditLogger) LogFilterEvent(eventType AuditEventType, r *http.Request, filterType, filterValue, rule string)
func (*NoopAuditLogger) LogRateLimitEvent ¶
func (*NoopAuditLogger) LogSecurityEvent ¶
func (nal *NoopAuditLogger) LogSecurityEvent(event AuditEvent)
func (*NoopAuditLogger) LogSuspiciousActivity ¶
type Option ¶
type Option func(*Options)
func APIServerPreset ¶
func APIServerPreset() []Option
APIServerPreset returns options for a typical REST API server. Features: JWT auth support, API rate limiting, security headers, CORS-friendly, request size limits, compression.
func DevelopmentPreset ¶
func DevelopmentPreset() []Option
DevelopmentPreset returns options suitable for development environment. Features: basic logging, no security restrictions, no rate limiting, detailed error reporting.
func HighSecurityPreset ¶
func HighSecurityPreset(cert tls.Certificate) []Option
HighSecurityPreset returns options for high-security applications. Features: strict security headers, CSRF protection, request filtering, comprehensive rate limiting, audit logging.
func MergePresets ¶ added in v2.2.0
MergePresets merges multiple presets into a single slice of options.
func MergeWithPreset ¶ added in v2.2.0
MergeWithPreset merges a preset with additional options.
func MicroservicePreset ¶
func MicroservicePreset() []Option
MicroservicePreset returns options for microservice environments. Features: minimal security (behind gateway), fast timeouts, health checks, size limits.
func ProductionPreset ¶
func ProductionPreset(cert tls.Certificate) []Option
ProductionPreset returns options suitable for production environment. Features: security headers, CSRF protection, rate limiting, request logging, health endpoints, metrics, compression.
func TLSPreset ¶ added in v2.2.0
func TLSPreset(certFile, keyFile string, cert ...tls.Certificate) []Option
TLSPreset returns options for quick SSL/TLS setup. Provide cert object or cert and key files.
func WebAppPreset ¶
func WebAppPreset(cert tls.Certificate) []Option
WebAppPreset returns options for serving web applications. Features: web security headers, CSRF protection, content protection, static file friendly, size limits, compression.
func WithAllowedHeaders ¶
WithAllowedHeaders restricts requests based on header values. Only requests with headers matching the specified exact values will be allowed.
Example:
// Require specific API version
server := servex.New(servex.WithAllowedHeaders(map[string][]string{
"X-API-Version": {"v1", "v2"},
"Content-Type": {"application/json"},
}))
// Require authentication header
server := servex.New(servex.WithAllowedHeaders(map[string][]string{
"Authorization": {"Bearer token1", "Bearer token2"},
}))
Header matching:
- Header names are case-insensitive
- Values must match exactly (case-sensitive)
- Multiple allowed values per header
- All specified headers must be present
Use cases:
- API version enforcement
- Content-Type validation
- Custom authentication schemes
- Partner-specific headers
For pattern matching instead of exact values, use WithAllowedHeadersRegex().
func WithAllowedHeadersRegex ¶
WithAllowedHeadersRegex restricts requests based on header regex patterns. Only requests with headers matching the specified patterns will be allowed.
Example:
// Allow any Bearer token
server := servex.New(servex.WithAllowedHeadersRegex(map[string][]string{
"Authorization": {`^Bearer [A-Za-z0-9+/=]+$`},
}))
// Allow semantic versioning
server := servex.New(servex.WithAllowedHeadersRegex(map[string][]string{
"X-API-Version": {`^v\d+\.\d+$`}, // v1.0, v2.1, etc.
}))
// Validate custom headers
server := servex.New(servex.WithAllowedHeadersRegex(map[string][]string{
"X-Request-ID": {`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`},
}))
Regex features:
- Header names are case-insensitive
- Use standard Go regex syntax
- ^ and $ for exact matching
- Multiple patterns per header (OR logic)
This is more flexible than WithAllowedHeaders() for pattern-based validation.
func WithAllowedIPs ¶
WithAllowedIPs restricts access to specific IP addresses or CIDR ranges. Only requests from these IPs will be allowed. All other IPs are blocked.
Example:
// Allow specific office IPs
server := servex.New(servex.WithAllowedIPs(
"192.168.1.0/24", // Office network
"203.0.113.100", // VPN gateway
"10.0.0.0/8", // Internal network
))
// Allow only localhost
server := servex.New(servex.WithAllowedIPs("127.0.0.1", "::1"))
IP formats supported:
- Single IP: "192.168.1.100"
- CIDR range: "10.0.0.0/8", "192.168.1.0/24"
- IPv6: "2001:db8::1", "2001:db8::/32"
Use cases:
- Restrict admin interfaces to office IPs
- Allow only partner/client IPs
- Internal-only APIs
- Development/staging environment protection
If empty, all IPs are allowed unless blocked by WithBlockedIPs().
func WithAllowedQueryParams ¶
WithAllowedQueryParams restricts requests based on query parameter values. Only requests with query parameters matching the specified exact values will be allowed.
Example:
// Require specific API version
server := servex.New(servex.WithAllowedQueryParams(map[string][]string{
"version": {"v1", "v2"},
"format": {"json", "xml"},
}))
// Require valid sort parameters
server := servex.New(servex.WithAllowedQueryParams(map[string][]string{
"sort": {"name", "date", "price"},
"order": {"asc", "desc"},
}))
Parameter matching:
- Parameter names are case-sensitive
- Values must match exactly (case-sensitive)
- Multiple allowed values per parameter
- All specified parameters must be present
Use cases:
- API parameter validation
- Prevent SQL injection via query params
- Business logic validation
- Feature flag enforcement
For pattern matching instead of exact values, use WithAllowedQueryParamsRegex().
func WithAllowedQueryParamsRegex ¶
WithAllowedQueryParamsRegex restricts requests based on query parameter regex patterns. Only requests with query parameters matching the specified patterns will be allowed.
Example:
// Allow numeric IDs only
server := servex.New(servex.WithAllowedQueryParamsRegex(map[string][]string{
"id": {`^\d+$`},
"page": {`^[1-9]\d*$`}, // Positive integers only
}))
// Validate email format
server := servex.New(servex.WithAllowedQueryParamsRegex(map[string][]string{
"email": {`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`},
}))
// Allow UUID format
server := servex.New(servex.WithAllowedQueryParamsRegex(map[string][]string{
"uuid": {`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`},
}))
Regex features:
- Parameter names are case-sensitive
- Use standard Go regex syntax
- ^ and $ for exact matching
- Multiple patterns per parameter (OR logic)
This is more flexible than WithAllowedQueryParams() for format validation.
func WithAllowedUserAgents ¶
WithAllowedUserAgents restricts access to specific User-Agent strings. Only requests with these exact User-Agent headers will be allowed.
Example:
// Allow only your mobile app server := servex.New(servex.WithAllowedUserAgents( "MyApp/1.0 (iOS)", "MyApp/1.0 (Android)", )) // Allow specific browsers server := servex.New(servex.WithAllowedUserAgents( "Mozilla/5.0 Chrome/120.0.0.0", "Mozilla/5.0 Safari/537.36", ))
For pattern matching instead of exact strings, use WithAllowedUserAgentsRegex().
Use cases:
- Restrict API to your apps only
- Block automated scrapers
- Allow only supported browsers
- Partner API access control
If empty, all User-Agents are allowed unless blocked by WithBlockedUserAgents().
func WithAllowedUserAgentsRegex ¶
WithAllowedUserAgentsRegex restricts access using User-Agent regex patterns. Only requests with User-Agent headers matching these patterns will be allowed.
Example:
// Allow any Chrome browser server := servex.New(servex.WithAllowedUserAgentsRegex( `Chrome/\d+\.\d+`, )) // Allow your app with any version server := servex.New(servex.WithAllowedUserAgentsRegex( `^MyApp/\d+\.\d+ \((iOS|Android)\)$`, )) // Allow major browsers server := servex.New(servex.WithAllowedUserAgentsRegex( `(Chrome|Firefox|Safari|Edge)/\d+`, ))
Regex features:
- Use standard Go regex syntax
- Case-sensitive matching
- ^ and $ for exact matching
- \d+ for version numbers
- | for alternatives
This is more flexible than WithAllowedUserAgents() for version-aware filtering.
func WithAuditLogHeaders ¶
WithAuditLogHeaders configures whether to include HTTP headers in audit logs. This should be used carefully as headers may contain sensitive information.
Example:
// Include headers in audit logs (for detailed security analysis) server := servex.New( servex.WithDefaultAuditLogger(), servex.WithAuditLogHeaders(true), )
When enabled, the audit logger will include non-sensitive headers in security events. Sensitive headers like Authorization, Cookie, X-API-Key are always excluded.
func WithAuditLogger ¶
func WithAuditLogger(logger AuditLogger) Option
WithAuditLogger sets a custom audit logger for security events. The audit logger is used to log authentication events, rate limiting violations, filter blocks, CSRF attacks, and other security-related events.
Example:
// Custom audit logger that sends to external SIEM
type SIEMAuditLogger struct {
client *siem.Client
}
func (s *SIEMAuditLogger) LogSecurityEvent(event servex.AuditEvent) {
s.client.SendEvent(event)
}
server := servex.New(
servex.WithAuditLogger(&SIEMAuditLogger{client: siemClient}),
)
Use for:
- Integration with Security Information and Event Management (SIEM) systems
- Custom audit log formatting and routing
- Compliance with specific regulatory requirements
- Integration with threat intelligence platforms
func WithAuth ¶
func WithAuth(db AuthDatabase) Option
WithAuth enables JWT-based authentication with a custom database implementation. This activates the full authentication system with user management, roles, and JWT tokens.
The database must implement the AuthDatabase interface for user persistence.
Example:
// Custom database implementation
type MyAuthDB struct {
users map[string]*User
}
func (db *MyAuthDB) CreateUser(ctx context.Context, user User) error {
// Implementation
}
// ... implement other AuthDatabase methods
server := servex.New(servex.WithAuth(&MyAuthDB{}))
This automatically registers these endpoints:
- POST /api/v1/auth/register - User registration
- POST /api/v1/auth/login - User login
- POST /api/v1/auth/refresh - Token refresh
- POST /api/v1/auth/logout - User logout
- GET /api/v1/auth/me - Current user info
Use this for:
- Multi-user applications
- Role-based access control
- Persistent user data
- Production authentication systems
func WithAuthBasePath ¶
WithAuthBasePath sets the base path for authentication API endpoints. All auth routes will be registered under this path.
Example:
// Custom auth path
server := servex.New(servex.WithAuthBasePath("/auth"))
// Endpoints: /auth/login, /auth/register, etc.
// API versioned path
server := servex.New(servex.WithAuthBasePath("/api/v2/auth"))
// Endpoints: /api/v2/auth/login, /api/v2/auth/register, etc.
Default is "/api/v1/auth" if not set.
Registered endpoints under the base path:
- POST {basePath}/register
- POST {basePath}/login
- POST {basePath}/refresh
- POST {basePath}/logout
- GET {basePath}/me
func WithAuthConfig ¶
func WithAuthConfig(auth AuthConfig) Option
WithAuthConfig sets the complete authentication configuration at once. This allows fine-grained control over all authentication settings.
Example:
authConfig := servex.AuthConfig{
Enabled: true,
Database: myDB,
AccessTokenDuration: 15 * time.Minute,
RefreshTokenDuration: 7 * 24 * time.Hour,
AuthBasePath: "/auth",
IssuerNameInJWT: "my-app",
RefreshTokenCookieName: "_refresh",
RolesOnRegister: []servex.UserRole{"user"},
InitialUsers: []servex.InitialUser{
{Username: "admin", Password: "secure-password", Roles: []servex.UserRole{"admin"}},
},
}
server := servex.New(servex.WithAuthConfig(authConfig))
Use this when you need to configure multiple authentication settings at once or when loading configuration from files or environment variables.
func WithAuthInitialRoles ¶
WithAuthInitialRoles sets the default roles assigned to newly registered users. These roles are automatically assigned when users register through the /register endpoint.
Example:
// All new users get "user" role
server := servex.New(servex.WithAuthInitialRoles(servex.UserRole("user")))
// Multiple default roles
server := servex.New(servex.WithAuthInitialRoles(
servex.UserRole("user"),
servex.UserRole("customer"),
))
Common role patterns:
- Basic: "user"
- Hierarchical: "user", "member", "premium"
- Functional: "reader", "writer", "admin"
Users can have multiple roles. Additional roles can be assigned later through user management endpoints or database operations.
func WithAuthInitialUsers ¶
func WithAuthInitialUsers(users ...InitialUser) Option
WithAuthInitialUsers creates initial users in the database when the server starts. This is useful for creating admin accounts or seeding the database with test users.
Example:
// Create admin user on startup
server := servex.New(
servex.WithAuthMemoryDatabase(),
servex.WithAuthInitialUsers(servex.InitialUser{
Username: "admin",
Password: "secure-admin-password",
Roles: []servex.UserRole{"admin", "user"},
}),
)
// Multiple initial users
server := servex.New(
servex.WithAuthMemoryDatabase(),
servex.WithAuthInitialUsers(
servex.InitialUser{
Username: "admin",
Password: "admin-pass",
Roles: []servex.UserRole{"admin"},
},
servex.InitialUser{
Username: "testuser",
Password: "test-pass",
Roles: []servex.UserRole{"user"},
},
),
)
Security considerations:
- Use strong passwords
- Consider loading from environment variables
- Remove or change default passwords in production
- Limit to essential accounts only
The users are created if they don't already exist in the database.
func WithAuthIssuer ¶
WithAuthIssuer sets the issuer name included in JWT token claims. This helps identify which service issued the token and can be used for validation.
Example:
// Set application name as issuer
server := servex.New(servex.WithAuthIssuer("my-api-service"))
// Environment-specific issuer
issuer := fmt.Sprintf("my-app-%s", os.Getenv("ENVIRONMENT"))
server := servex.New(servex.WithAuthIssuer(issuer))
The issuer appears in the JWT "iss" claim and can be verified by clients. Default is "testing" if not set.
Use descriptive names like:
- Application name: "user-service", "payment-api"
- Environment-specific: "my-app-prod", "my-app-staging"
- Domain-based: "api.mycompany.com"
func WithAuthKey ¶
WithAuthKey sets the JWT signing keys for access and refresh tokens. Keys should be hex-encoded strings. If empty, random keys will be generated.
Example:
// Use specific keys (recommended for production)
accessKey := "your-32-byte-hex-encoded-access-key"
refreshKey := "your-32-byte-hex-encoded-refresh-key"
server := servex.New(servex.WithAuthKey(accessKey, refreshKey))
// Generate random keys (development only)
server := servex.New(servex.WithAuthKey("", ""))
Key requirements:
- Use strong, randomly generated keys
- Access and refresh keys should be different
- Store keys securely (environment variables, key management systems)
- Rotate keys periodically in production
Security considerations:
- Never hardcode keys in source code
- Use environment variables or secure configuration
- Different keys for different environments
- Consider key rotation strategies
func WithAuthMemoryDatabase ¶
func WithAuthMemoryDatabase() Option
WithAuthMemoryDatabase enables JWT authentication with an in-memory user database. This is convenient for development, testing, and applications that don't need persistent user data.
WARNING: All users and sessions will be lost when the application restarts. NOT RECOMMENDED FOR PRODUCTION USE.
Example:
// Development server with auth
server := servex.New(
servex.WithAuthMemoryDatabase(),
servex.WithAuthInitialUsers(servex.InitialUser{
Username: "admin",
Password: "admin123",
Roles: []servex.UserRole{"admin"},
}),
)
This automatically registers the same endpoints as WithAuth().
Use this for:
- Development and testing
- Prototypes and demos
- Applications with temporary users
- Learning and experimentation
For production, implement a persistent database and use WithAuth() instead.
func WithAuthNotRegisterRoutes ¶
WithAuthNotRegisterRoutes prevents automatic registration of default authentication routes. Use this when you want to implement custom authentication endpoints or integrate with existing authentication systems.
Example:
// Disable default auth routes
server := servex.New(
servex.WithAuthMemoryDatabase(),
servex.WithAuthNotRegisterRoutes(true),
)
// Register custom auth routes
server.HandleFunc("/custom/login", myCustomLoginHandler)
server.HandleFunc("/custom/register", myCustomRegisterHandler)
When enabled, you must implement your own:
- User registration endpoint
- Login endpoint
- Token refresh endpoint
- Logout endpoint
- User profile endpoint
You can still use the AuthManager methods for token generation and validation. This gives you full control over request/response formats and business logic.
func WithAuthRefreshTokenCookieName ¶
WithAuthRefreshTokenCookieName sets the name of the HTTP cookie used to store refresh tokens. The refresh token cookie is httpOnly and secure, providing protection against XSS attacks.
Example:
// Custom cookie name
server := servex.New(servex.WithAuthRefreshTokenCookieName("_my_refresh_token"))
// Short name for bandwidth
server := servex.New(servex.WithAuthRefreshTokenCookieName("_rt"))
Default is "_servexrt" if not set.
Cookie characteristics:
- HttpOnly: Cannot be accessed by JavaScript
- Secure: Only sent over HTTPS (in production)
- SameSite: Protection against CSRF attacks
- Expires: Set to refresh token duration
Choose names that don't conflict with your application's other cookies.
func WithAuthToken ¶
WithAuthToken enables simple token-based authentication using the Authorization header. When set, the server will check for "Authorization: Bearer <token>" headers on protected routes and compare against this token.
Example:
// Enable simple token auth
server := servex.New(servex.WithAuthToken("my-secret-api-key"))
// Client usage:
// curl -H "Authorization: Bearer my-secret-api-key" http://localhost:8080/api/protected
Use this for:
- Simple API authentication
- Service-to-service communication
- Development and testing
For more advanced authentication with user management, JWT tokens, and roles, use WithAuth() or WithAuthMemoryDatabase() instead.
Note: This is a simple string comparison. For production use with multiple users or complex authorization, consider using the full JWT authentication system.
func WithAuthTokensDuration ¶
WithAuthTokensDuration sets the validity duration for access and refresh tokens. Access tokens should be short-lived for security, while refresh tokens can be longer.
Example:
// Typical web application server := servex.New(servex.WithAuthTokensDuration( 15*time.Minute, // Access token: 15 minutes 7*24*time.Hour, // Refresh token: 7 days )) // High-security application server := servex.New(servex.WithAuthTokensDuration( 5*time.Minute, // Access token: 5 minutes 24*time.Hour, // Refresh token: 1 day )) // Development environment server := servex.New(servex.WithAuthTokensDuration( 1*time.Hour, // Access token: 1 hour 30*24*time.Hour, // Refresh token: 30 days ))
Recommended patterns:
- Web apps: 15-60 min access, 7-30 days refresh
- APIs: 5-30 min access, 1-7 days refresh
- Mobile apps: 30-60 min access, 30-90 days refresh
- High security: 5-15 min access, 1-3 days refresh
Shorter access tokens improve security but require more refresh operations.
func WithBlockedHeaders ¶
WithBlockedHeaders blocks requests based on header values. Requests with headers matching the specified exact values will be denied.
Example:
// Block suspicious headers
server := servex.New(servex.WithBlockedHeaders(map[string][]string{
"X-Forwarded-For": {"malicious-proxy-ip"},
"User-Agent": {"BadBot/1.0"},
}))
// Block old API versions
server := servex.New(servex.WithBlockedHeaders(map[string][]string{
"X-API-Version": {"v0.1", "v0.2"},
}))
Header matching:
- Header names are case-insensitive
- Values must match exactly (case-sensitive)
- Multiple blocked values per header
- Any matching header causes blocking
Use cases:
- Block deprecated API versions
- Security header filtering
- Malicious request detection
- Legacy client blocking
Note: BlockedHeaders takes precedence over AllowedHeaders.
func WithBlockedHeadersRegex ¶
WithBlockedHeadersRegex blocks requests based on header regex patterns. Requests with headers matching the specified patterns will be denied.
Example:
// Block requests with suspicious X-Forwarded-For
server := servex.New(servex.WithBlockedHeadersRegex(map[string][]string{
"X-Forwarded-For": {`(10\.0\.0\.|192\.168\.)`}, // Block internal IPs
}))
// Block old user agents
server := servex.New(servex.WithBlockedHeadersRegex(map[string][]string{
"User-Agent": {`(?i)(bot|crawler|spider)`},
}))
Regex features:
- Header names are case-insensitive
- (?i) for case-insensitive pattern matching
- Use standard Go regex syntax
- Multiple patterns per header (OR logic)
Note: BlockedHeadersRegex takes precedence over AllowedHeadersRegex.
func WithBlockedIPs ¶
WithBlockedIPs blocks access from specific IP addresses or CIDR ranges. Requests from these IPs will be denied with a 403 Forbidden response.
Example:
// Block known malicious IPs
server := servex.New(servex.WithBlockedIPs(
"203.0.113.0/24", // Known spam network
"198.51.100.50", // Specific malicious IP
"192.0.2.0/24", // Blocked range
))
// Block competitors from scraping
server := servex.New(servex.WithBlockedIPs("competitor-ip-range"))
IP formats supported:
- Single IP: "192.168.1.100"
- CIDR range: "10.0.0.0/8", "192.168.1.0/24"
- IPv6: "2001:db8::1", "2001:db8::/32"
Use cases:
- Block known malicious IPs
- Prevent competitor scraping
- Geographic restrictions
- Temporary IP bans
Note: BlockedIPs takes precedence over AllowedIPs. If an IP is in both lists, it will be blocked.
func WithBlockedQueryParams ¶
WithBlockedQueryParams blocks requests based on query parameter values. Requests with query parameters matching the specified exact values will be denied.
Example:
// Block dangerous parameters
server := servex.New(servex.WithBlockedQueryParams(map[string][]string{
"debug": {"true", "1"},
"admin": {"true", "1"},
}))
// Block SQL injection attempts
server := servex.New(servex.WithBlockedQueryParams(map[string][]string{
"id": {"'; DROP TABLE users; --"},
}))
Parameter matching:
- Parameter names are case-sensitive
- Values must match exactly (case-sensitive)
- Multiple blocked values per parameter
- Any matching parameter causes blocking
Use cases:
- Security parameter filtering
- Debug mode blocking in production
- Malicious query detection
- Legacy parameter deprecation
Note: BlockedQueryParams takes precedence over AllowedQueryParams.
func WithBlockedQueryParamsRegex ¶
WithBlockedQueryParamsRegex blocks requests based on query parameter regex patterns. Requests with query parameters matching the specified patterns will be denied.
Example:
// Block SQL injection patterns
server := servex.New(servex.WithBlockedQueryParamsRegex(map[string][]string{
"search": {`(?i)(union|select|drop|delete|insert|update)`},
}))
// Block script injection
server := servex.New(servex.WithBlockedQueryParamsRegex(map[string][]string{
"callback": {`(?i)(<script|javascript:|vbscript:)`},
}))
// Block excessive length
server := servex.New(servex.WithBlockedQueryParamsRegex(map[string][]string{
"query": {`.{1000,}`}, // Block queries longer than 1000 chars
}))
Regex features:
- Parameter names are case-sensitive
- (?i) for case-insensitive pattern matching
- Use standard Go regex syntax
- Multiple patterns per parameter (OR logic)
Note: BlockedQueryParamsRegex takes precedence over AllowedQueryParamsRegex.
func WithBlockedUserAgents ¶
WithBlockedUserAgents blocks access from specific User-Agent strings. Requests with these exact User-Agent headers will be denied.
Example:
// Block common bots server := servex.New(servex.WithBlockedUserAgents( "Googlebot", "Bingbot", "facebookexternalhit", "Twitterbot", )) // Block scrapers server := servex.New(servex.WithBlockedUserAgents( "curl/7.68.0", "wget", "python-requests", "scrapy", ))
For pattern matching instead of exact strings, use WithBlockedUserAgentsRegex().
Use cases:
- Block automated scrapers
- Prevent bot traffic
- Block specific tools
- Temporary user-agent bans
Note: BlockedUserAgents takes precedence over AllowedUserAgents.
func WithBlockedUserAgentsRegex ¶
WithBlockedUserAgentsRegex blocks access using User-Agent regex patterns. Requests with User-Agent headers matching these patterns will be denied.
Example:
// Block all bots and crawlers server := servex.New(servex.WithBlockedUserAgentsRegex( `(?i)(bot|crawler|spider|scraper)`, )) // Block command line tools server := servex.New(servex.WithBlockedUserAgentsRegex( `^(curl|wget|python-requests)`, )) // Block old browser versions server := servex.New(servex.WithBlockedUserAgentsRegex( `MSIE [1-9]\.`, // IE 9 and below ))
Regex features:
- (?i) for case-insensitive matching
- Use standard Go regex syntax
- ^ and $ for exact matching
- | for alternatives
Note: BlockedUserAgentsRegex takes precedence over AllowedUserAgentsRegex.
func WithBurstSize ¶
WithBurstSize sets the maximum burst size for rate limiting. This allows clients to exceed the normal rate limit temporarily by "bursting".
Example:
// 10 RPS with burst of 50 requests server := servex.New( servex.WithRPS(10), servex.WithBurstSize(50), ) // No bursting allowed server := servex.New( servex.WithRPS(10), servex.WithBurstSize(1), )
How it works:
- Clients can make up to burstSize requests immediately
- After bursting, they must wait for tokens to refill
- Tokens refill at the configured rate (RPS/RPM)
Use cases:
- Handle traffic spikes gracefully
- Allow batch operations
- Improve user experience for bursty clients
- Balance performance with protection
If not set, defaults to the requests per interval value.
func WithCORS ¶ added in v2.2.0
func WithCORS() Option
WithCORS enables CORS with permissive defaults suitable for development. This allows all origins, methods, and headers with credentials disabled.
Example:
// Enable CORS with permissive defaults
server := servex.New(servex.WithCORS())
// Equivalent to:
server := servex.New(servex.WithCORSConfig(servex.CORSConfig{
Enabled: true,
AllowOrigins: []string{"*"},
AllowMethods: []string{GET, POST, PUT, DELETE, OPTIONS},
AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"},
AllowCredentials: false,
MaxAge: 3600,
}))
Security considerations:
- This is permissive and suitable for development
- For production, use specific origins with WithCORSAllowOrigins()
- Never use this with credentials in production
For production use, configure specific origins:
server := servex.New(
servex.WithCORS(),
servex.WithCORSAllowOrigins("https://myapp.com"),
servex.WithCORSAllowCredentials(true),
)
func WithCORSAllowCredentials ¶ added in v2.2.0
func WithCORSAllowCredentials() Option
WithCORSAllowCredentials enables sending credentials (cookies, auth headers) in CORS requests. When enabled, browsers will include credentials in cross-origin requests.
Example:
// Enable credentials for authenticated API
server := servex.New(
servex.WithCORSAllowOrigins("https://app.example.com"),
servex.WithCORSAllowCredentials(true),
)
// Session-based authentication with cookies
server := servex.New(
servex.WithCORSAllowOrigins("https://frontend.example.com"),
servex.WithCORSAllowCredentials(true),
servex.WithCORSAllowHeaders("Content-Type", "X-CSRF-Token"),
)
Security requirements when enabled:
- Cannot use "*" for AllowOrigins (must specify exact origins)
- Increases CSRF attack surface (implement CSRF protection)
- Consider implementing additional security measures
Use cases:
- Session-based authentication with cookies
- APIs that require Authorization headers
- Single sign-on (SSO) systems
- Applications with cross-domain user sessions
This automatically enables CORS if not already enabled.
func WithCORSAllowHeaders ¶ added in v2.2.0
WithCORSAllowHeaders sets the allowed headers for CORS requests. This specifies which headers can be sent in cross-origin requests.
Example:
// API with authentication and custom headers
server := servex.New(servex.WithCORSAllowHeaders(
"Content-Type",
"Authorization",
"X-API-Key",
"X-Requested-With",
))
// Basic web application headers
server := servex.New(servex.WithCORSAllowHeaders(
"Content-Type",
"Authorization",
"X-CSRF-Token",
))
// Allow all headers (less secure but convenient for development)
server := servex.New(servex.WithCORSAllowHeaders("*"))
Common header combinations:
- Basic API: Content-Type, Authorization
- Web app: Content-Type, Authorization, X-Requested-With, X-CSRF-Token
- File upload: Content-Type, Authorization, X-Filename
- Custom API: Content-Type, Authorization, X-API-Key, X-Client-Version
Standard headers that don't need explicit allowance:
- Accept, Accept-Language, Content-Language
- Content-Type (for simple values)
This automatically enables CORS if not already enabled.
func WithCORSAllowMethods ¶ added in v2.2.0
WithCORSAllowMethods sets the allowed HTTP methods for CORS requests. This specifies which HTTP methods are allowed in cross-origin requests.
Example:
// Full REST API support server := servex.New(servex.WithCORSAllowMethods( GET, POST, PUT, DELETE, PATCH, OPTIONS, )) // Read-only API server := servex.New(servex.WithCORSAllowMethods(GET, "HEAD", OPTIONS)) // Create and read operations only server := servex.New(servex.WithCORSAllowMethods(GET, POST, OPTIONS))
Common method combinations:
- REST API: GET, POST, PUT, DELETE, PATCH, OPTIONS
- Read-only: GET, HEAD, OPTIONS
- Read/Create: GET, POST, OPTIONS
- File API: GET, POST, PUT, DELETE, OPTIONS
Notes:
- OPTIONS is automatically handled for preflight requests
- GET and HEAD are "simple" methods that don't trigger preflight
- Other methods (POST, PUT, DELETE, PATCH) trigger preflight requests
This automatically enables CORS if not already enabled.
func WithCORSAllowOrigins ¶ added in v2.2.0
WithCORSAllowOrigins sets the allowed origins for CORS requests. This specifies which domains are allowed to make cross-origin requests to your server.
Example:
// Allow specific origins server := servex.New(servex.WithCORSAllowOrigins( "https://myapp.com", "https://admin.myapp.com", )) // Development setup with local origins server := servex.New(servex.WithCORSAllowOrigins( "http://localhost:3000", "http://localhost:8080", "https://dev.myapp.com", )) // Production API serving multiple frontends server := servex.New(servex.WithCORSAllowOrigins( "https://app.example.com", "https://admin.example.com", "https://mobile.example.com", ))
Security best practices:
- Always specify exact origins in production
- Include protocol (https://) and port if non-standard
- Never use "*" with credentials enabled
- Use environment variables for different environments
This automatically enables CORS if not already enabled.
func WithCORSConfig ¶ added in v2.2.0
func WithCORSConfig(cors CORSConfig) Option
WithCORSConfig sets the complete CORS configuration. This allows fine-grained control over all CORS settings at once.
Example:
corsConfig := servex.CORSConfig{
Enabled: true,
AllowOrigins: []string{"https://example.com", "https://app.example.com"},
AllowMethods: []string{GET, POST, PUT, DELETE, OPTIONS},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 3600,
}
server := servex.New(servex.WithCORSConfig(corsConfig))
Use this when you need to configure multiple CORS settings at once or when loading configuration from files or environment variables.
func WithCORSExcludePaths ¶ added in v2.2.0
WithCORSExcludePaths sets paths that should be excluded from CORS headers. Requests to these paths will not have CORS headers applied.
Example:
// Exclude internal and admin endpoints
server := servex.New(
servex.WithCORS(),
servex.WithCORSExcludePaths("/internal/*", "/admin/*"),
)
// Exclude non-browser endpoints
server := servex.New(
servex.WithCORS(),
servex.WithCORSExcludePaths("/webhooks/*", "/api/internal/*"),
)
Common exclusions:
- Internal APIs: "/internal/*", "/private/*"
- Admin interfaces: "/admin/*", "/management/*"
- Webhooks: "/webhooks/*", "/callbacks/*"
- Health checks: "/health", "/ping", "/metrics"
- Server-to-server: "/api/internal/*"
Path matching supports wildcards (*) for pattern matching. Use when different endpoints need different CORS policies or when some endpoints should not be accessible to browsers.
This automatically enables CORS if not already enabled.
func WithCORSExposeHeaders ¶ added in v2.2.0
WithCORSExposeHeaders sets which response headers are exposed to client-side JavaScript. This allows browsers to access specific response headers in cross-origin requests.
Example:
// Expose pagination headers server := servex.New(servex.WithCORSExposeHeaders( "X-Total-Count", "X-Page-Count", "X-Per-Page", )) // Expose file download headers server := servex.New(servex.WithCORSExposeHeaders( "Content-Length", "Content-Range", "Content-Disposition", )) // Expose custom API metadata server := servex.New(servex.WithCORSExposeHeaders( "X-Rate-Limit-Remaining", "X-Rate-Limit-Reset", "Location", ))
Common headers to expose:
- Pagination: X-Total-Count, X-Page-Count, X-Per-Page
- Rate limiting: X-Rate-Limit-Remaining, X-Rate-Limit-Reset
- File operations: Content-Length, Content-Range, Content-Disposition
- Resource creation: Location
- API metadata: X-API-Version, X-Request-ID
This automatically enables CORS if not already enabled.
func WithCORSIncludePaths ¶ added in v2.2.0
WithCORSIncludePaths sets paths that should have CORS headers applied. If set, only requests to these paths will receive CORS headers.
Example:
// CORS only for API endpoints
server := servex.New(
servex.WithCORS(),
servex.WithCORSIncludePaths("/api/*"),
)
// CORS for specific services
server := servex.New(
servex.WithCORS(),
servex.WithCORSIncludePaths("/api/public/*", "/auth/*"),
)
// CORS for user-facing endpoints only
server := servex.New(
servex.WithCORS(),
servex.WithCORSIncludePaths("/app/*", "/public/*"),
)
Use cases:
- Mixed application: Only API endpoints need CORS
- Gradual CORS adoption: Start with specific endpoints
- Security: Limit CORS to necessary endpoints only
- Performance: Reduce header overhead on internal endpoints
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to receive CORS headers
- Paths in ExcludePaths are then excluded from CORS headers
Path matching supports wildcards (*) for pattern matching. Leave empty to apply CORS to all paths (default behavior).
This automatically enables CORS if not already enabled.
func WithCORSMaxAge ¶ added in v2.2.0
WithCORSMaxAge sets how long browsers can cache CORS preflight responses. This reduces the number of preflight requests by caching the CORS policy.
Example:
// Cache for 1 hour (good for development) server := servex.New(servex.WithCORSMaxAge(3600)) // Cache for 1 day (good for production) server := servex.New(servex.WithCORSMaxAge(86400)) // No caching (force preflight for every request) server := servex.New(servex.WithCORSMaxAge(0)) // Cache for 1 week (very stable API) server := servex.New(servex.WithCORSMaxAge(604800))
Common values:
- Development: 3600 (1 hour) - allows quick policy changes
- Production: 86400 (1 day) - good balance of performance and flexibility
- Stable API: 604800 (1 week) - maximum performance
- Testing: 0 - no caching for immediate policy changes
Benefits of longer caching:
- Fewer preflight requests (better performance)
- Reduced server load
- Better user experience
Benefits of shorter caching:
- Policy changes take effect quickly
- Better for development and testing
- More responsive to security updates
This automatically enables CORS if not already enabled.
func WithCSRFCookieHttpOnly ¶
WithCSRFCookieHttpOnly sets whether the CSRF cookie is HTTP-only.
Example:
// Maximum security (recommended for server-side apps)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieHttpOnly(true),
servex.WithCSRFTokenEndpoint("/csrf-token"),
)
// JavaScript accessible (for SPAs)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieHttpOnly(false),
)
Security considerations:
- true: More secure, prevents XSS token theft, requires server-side token injection
- false: JavaScript can read the token, but vulnerable to XSS attacks
When HttpOnly is true:
- Use WithCSRFTokenEndpoint() to provide tokens to JavaScript
- Inject tokens into HTML templates server-side
- Maximum protection against XSS token theft
When HttpOnly is false:
- JavaScript can read document.cookie to get the token
- Useful for SPAs and AJAX-heavy applications
- Consider additional XSS protections
func WithCSRFCookieMaxAge ¶
WithCSRFCookieMaxAge sets the maximum age for the CSRF cookie in seconds.
Example:
// Short-lived session (1 hour) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFCookieMaxAge(3600), ) // Daily session (24 hours) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFCookieMaxAge(86400), ) // Session cookie (expires when browser closes) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFCookieMaxAge(0), )
Common values:
- 3600: 1 hour (short-lived, more secure)
- 86400: 1 day (balance of security and usability)
- 604800: 1 week (longer sessions)
- 0: Session cookie (expires when browser closes)
Shorter durations improve security but may affect user experience. Choose based on your application's session management requirements.
func WithCSRFCookieName ¶
WithCSRFCookieName sets the name for the CSRF cookie.
Example:
// Use standard cookie name
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieName("csrf_token"),
)
// Use Angular style (readable by JavaScript)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieName("XSRF-TOKEN"),
servex.WithCSRFCookieHttpOnly(false),
)
// Use Express.js style
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieName("_csrf"),
)
Common cookie names:
- "csrf_token": Standard, secure
- "XSRF-TOKEN": Angular compatible
- "_csrf": Express.js style
- "csrftoken": Django style
Choose names that don't conflict with your application's other cookies.
func WithCSRFCookiePath ¶
WithCSRFCookiePath sets the path attribute for the CSRF cookie.
Example:
// Cookie available for entire site
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookiePath("/"),
)
// Cookie only for application section
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookiePath("/app"),
)
// Cookie only for API endpoints
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookiePath("/api"),
)
Common paths:
- "/": Cookie available for entire site (default)
- "/app": Cookie only for application section
- "/api": Cookie only for API endpoints
Use specific paths to limit cookie scope and improve security. The cookie will only be sent for requests under the specified path.
func WithCSRFCookieSameSite ¶
WithCSRFCookieSameSite sets the SameSite attribute for the CSRF cookie.
Example:
// Maximum protection (may break some legitimate usage)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieSameSite("Strict"),
)
// Balanced protection (recommended)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieSameSite("Lax"),
)
// Cross-site requests allowed (requires Secure=true)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieSameSite("None"),
servex.WithCSRFCookieSecure(true),
)
SameSite options:
- "Strict": Maximum protection, blocks all cross-site requests
- "Lax": Good protection with better usability (recommended)
- "None": Allows cross-site requests, requires Secure=true
"Lax" provides good CSRF protection while maintaining usability for most applications.
func WithCSRFCookieSecure ¶
WithCSRFCookieSecure sets whether the CSRF cookie requires HTTPS.
Example:
// Production HTTPS setup server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFCookieSecure(true), ) // Development HTTP setup server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFCookieSecure(false), )
Security recommendations:
- true: Required for production HTTPS sites
- false: Only for development with HTTP
The Secure flag is automatically set to true when SameSite="None". For production applications, always use HTTPS and set this to true.
func WithCSRFErrorMessage ¶
WithCSRFErrorMessage sets the message returned when CSRF validation fails.
Example:
// Generic message (recommended for security)
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFErrorMessage("Invalid request. Please refresh and try again."),
)
// More specific message
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFErrorMessage("CSRF token missing or invalid"),
)
// User-friendly message
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFErrorMessage("Security validation failed. Please reload the page."),
)
Best practices:
- Keep messages generic to avoid information disclosure
- Include guidance for legitimate users
- Consider localization for international applications
- Avoid revealing technical implementation details
The message is returned as plain text in the response body with a 403 Forbidden status.
func WithCSRFProtection ¶
func WithCSRFProtection() Option
WithCSRFProtection enables CSRF (Cross-Site Request Forgery) protection with default settings. This provides protection against CSRF attacks for web applications.
Example:
// Enable CSRF protection with defaults server := servex.New(servex.WithCSRFProtection()) // Combined with other security features server := servex.New( servex.WithStrictSecurityHeaders(), servex.WithCSRFProtection(), )
Default settings:
- Token name: "X-CSRF-Token"
- Cookie name: "csrf_token"
- Cookie HttpOnly: true (recommended for security)
- Cookie SameSite: "Lax"
- Safe methods: GET, HEAD, OPTIONS, TRACE
Use cases:
- Web applications with forms
- Single Page Applications (SPAs)
- Any application accepting requests from browsers
- APIs that need CSRF protection
For custom CSRF settings, use WithCSRFConfig() instead.
func WithCSRFSafeMethods ¶
WithCSRFSafeMethods sets the HTTP methods that bypass CSRF validation.
Example:
// Default safe methods (recommended) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFSafeMethods(GET, "HEAD", OPTIONS, "TRACE"), ) // More restrictive (only GET and HEAD) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFSafeMethods(GET, "HEAD"), ) // Allow additional methods (use with caution) server := servex.New( servex.WithCSRFProtection(), servex.WithCSRFSafeMethods(GET, "HEAD", OPTIONS, "TRACE", "PROPFIND"), )
Default safe methods: GET, HEAD, OPTIONS, TRACE
These methods are considered safe because they shouldn't have side effects. All other methods (POST, PUT, PATCH, DELETE) will require CSRF tokens.
Only modify this if you have specific requirements or use non-standard HTTP methods. Adding methods like POST to safe methods defeats the purpose of CSRF protection.
func WithCSRFTokenEndpoint ¶
WithCSRFTokenEndpoint enables an endpoint to retrieve CSRF tokens via AJAX.
Example:
// Standard CSRF token endpoint
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFTokenEndpoint("/csrf-token"),
)
// Custom endpoint path
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFTokenEndpoint("/api/csrf"),
)
// For SPAs with HttpOnly cookies
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFCookieHttpOnly(true),
servex.WithCSRFTokenEndpoint("/api/v1/csrf-token"),
)
The endpoint will:
- Use GET method
- Return JSON: {"csrf_token": "abc123..."}
- Set the CSRF cookie
- Bypass CSRF validation (safe since it's read-only)
Use cases:
- SPAs that need to fetch tokens dynamically
- AJAX applications with HttpOnly cookies
- Mobile apps that need CSRF tokens
- Dynamic forms that load after page load
func WithCSRFTokenName ¶
WithCSRFTokenName sets the name for the CSRF token in headers and form fields.
Example:
// Use Rails/Django style token name
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFTokenName("X-CSRF-Token"),
)
// Use Angular style token name
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFTokenName("X-XSRF-TOKEN"),
)
// Use form field name
server := servex.New(
servex.WithCSRFProtection(),
servex.WithCSRFTokenName("csrf_token"),
)
Common token names:
- "X-CSRF-Token": Rails, Django, standard header
- "X-XSRF-TOKEN": Angular default
- "csrf_token": Common form field name
- "_token": Laravel style
The middleware will look for the token in:
- Request header with this name
- Form field with this name
- URL query parameter with this name (fallback)
func WithCacheAPI ¶
WithCacheAPI sets up cache control for API endpoints with the specified max age. This applies cache headers optimized for API responses. The cache control will be set to "public, max-age=<maxAgeSeconds>". Recommended for stable API responses that don't change frequently.
func WithCacheConfig ¶
func WithCacheConfig(cache CacheConfig) Option
WithCacheConfig sets the cache control configuration for HTTP responses. This allows you to configure all cache-related settings at once.
Example:
cacheConfig := servex.CacheConfig{
Enabled: true,
CacheControl: "public, max-age=3600",
Vary: "Accept-Encoding",
}
server := servex.New(servex.WithCacheConfig(cacheConfig))
Use this when you need to configure multiple cache settings or when loading configuration from external sources like config files.
func WithCacheControl ¶
WithCacheControl enables cache control headers and sets the Cache-Control header value. This is the most common way to enable basic caching.
Example:
// Cache static assets for 1 hour
server := servex.New(servex.WithCacheControl("public, max-age=3600"))
// Disable caching for sensitive data
server := servex.New(servex.WithCacheControl("no-store"))
// Private cache for user-specific content
server := servex.New(servex.WithCacheControl("private, max-age=900"))
Common Cache-Control values:
- "no-cache": Must revalidate before using cached copy
- "no-store": Do not cache at all (sensitive data)
- "public, max-age=3600": Public cache for 1 hour
- "private, max-age=900": Private cache for 15 minutes
- "public, max-age=31536000, immutable": Cache for 1 year (static assets)
func WithCacheETag ¶
WithCacheETag sets the ETag header for cache validation. ETags allow clients to validate cached content without downloading.
Example:
// Static ETag based on content version
server := servex.New(servex.WithCacheETag(`"v1.2.3"`))
// Weak ETag based on timestamp
server := servex.New(servex.WithCacheETag(`W/"Tue, 15 Nov 1994 12:45:26 GMT"`))
// Combined with Cache-Control
server := servex.New(
servex.WithCacheControl("public, max-age=0, must-revalidate"),
servex.WithCacheETag(`"33a64df551"`),
)
ETag formats:
- Strong ETag: `"version123"` (content identical)
- Weak ETag: `W/"version123"` (content equivalent)
Use ETags when you want clients to validate cached content efficiently.
func WithCacheETagFunc ¶
WithCacheETagFunc sets a dynamic ETag generation function. The function is called for each request to generate request-specific ETags.
Example:
// Generate ETag based on user ID and content version
server := servex.New(servex.WithCacheETagFunc(func(r *http.Request) string {
userID := getUserID(r)
version := getContentVersion()
return `"` + userID + "-" + version + `"`
}))
// Generate ETag based on request path
server := servex.New(servex.WithCacheETagFunc(func(r *http.Request) string {
hash := sha256.Sum256([]byte(r.URL.Path))
return `"` + hex.EncodeToString(hash[:8]) + `"`
}))
// Weak ETag based on timestamp
server := servex.New(servex.WithCacheETagFunc(func(r *http.Request) string {
return `W/"` + time.Now().Format("20060102150405") + `"`
}))
Use for content that varies per request or needs dynamic validation.
func WithCacheExcludePaths ¶
WithCacheExcludePaths sets paths that should be excluded from cache control headers. Requests to these paths will not have cache control headers applied.
Example:
// Exclude dynamic endpoints from caching
server := servex.New(
servex.WithCacheControl("public, max-age=3600"),
servex.WithCacheExcludePaths("/api/*", "/user/*", "/admin/*"),
)
// Exclude authentication and real-time endpoints
server := servex.New(
servex.WithCacheHeaders(),
servex.WithCacheExcludePaths("/auth/*", "/ws/*", "/stream/*"),
)
Common exclusions:
- Dynamic APIs: "/api/*", "/graphql"
- User-specific content: "/user/*", "/profile/*"
- Authentication: "/auth/*", "/login", "/logout"
- Admin interfaces: "/admin/*"
- Real-time endpoints: "/ws/*", "/stream/*"
Path matching supports wildcards (*) for pattern matching.
func WithCacheExpires ¶
WithCacheExpires sets the Expires header for cache control. This provides a fallback for older HTTP/1.0 clients.
Example:
// Set expiration time
expireTime := time.Now().Add(1 * time.Hour).Format(http.TimeFormat)
server := servex.New(servex.WithCacheExpires(expireTime))
// Combined with Cache-Control
server := servex.New(
servex.WithCacheControl("public, max-age=3600"),
servex.WithCacheExpires(time.Now().Add(1*time.Hour).Format(http.TimeFormat)),
)
Note: Modern clients prefer Cache-Control over Expires. Use this only for compatibility with older clients or as a fallback.
func WithCacheExpiresTime ¶
WithCacheExpiresTime sets the Expires header using a time.Time value. This automatically formats the time using HTTP time format (RFC 7231).
Example:
// Set expiration time to 1 hour from now
server := servex.New(servex.WithCacheExpiresTime(time.Now().Add(time.Hour)))
// Set expiration to a specific time
expireTime := time.Date(2024, 12, 31, 23, 59, 59, 0, time.UTC)
server := servex.New(servex.WithCacheExpiresTime(expireTime))
// Combined with Cache-Control
server := servex.New(
servex.WithCacheControl("public, max-age=3600"),
servex.WithCacheExpiresTime(time.Now().Add(time.Hour)),
)
This is more convenient than WithCacheExpires() when working with time.Time values.
func WithCacheHeaders ¶
func WithCacheHeaders() Option
WithCacheHeaders enables cache control headers with basic settings. This sets common cache control headers for typical web applications.
Example:
// Enable basic caching with common defaults server := servex.New(servex.WithCacheHeaders())
This sets:
- Cache-Control: "public, max-age=3600" (1 hour)
- Vary: "Accept-Encoding" (for compression)
Use this for quick setup with sensible defaults. For custom settings, use WithCacheControl() or WithCacheConfig() instead.
func WithCacheIncludePaths ¶
WithCacheIncludePaths sets paths that should have cache control headers applied. If set, only requests to these paths will receive cache control headers.
Example:
// Cache only static assets
server := servex.New(
servex.WithCacheControl("public, max-age=31536000, immutable"),
servex.WithCacheIncludePaths("/static/*", "/assets/*", "/images/*"),
)
// Cache specific API endpoints
server := servex.New(
servex.WithCacheControl("public, max-age=300"),
servex.WithCacheIncludePaths("/api/public/*", "/docs/*"),
)
Use cases:
- Cache only static assets: "/static/*", "/assets/*"
- Cache specific API endpoints: "/api/public/*"
- Cache documentation: "/docs/*"
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to receive cache headers
- Paths in ExcludePaths are then excluded from cache headers
Path matching supports wildcards (*) for pattern matching.
func WithCacheLastModified ¶
WithCacheLastModified sets the Last-Modified header for cache validation. This indicates when the resource was last changed.
Example:
// Set last modified time
lastMod := time.Now().AddDate(0, 0, -1).Format(http.TimeFormat)
server := servex.New(servex.WithCacheLastModified(lastMod))
// Combined with Cache-Control
server := servex.New(
servex.WithCacheControl("public, max-age=0, must-revalidate"),
servex.WithCacheLastModified(time.Now().Format(http.TimeFormat)),
)
Benefits:
- Enables conditional requests (If-Modified-Since)
- Reduces bandwidth for unchanged resources
- Works well with ETags for cache validation
func WithCacheLastModifiedFunc ¶
WithCacheLastModifiedFunc sets a dynamic Last-Modified generation function. The function is called for each request to generate request-specific modification times.
Example:
// Get modification time from file system
server := servex.New(servex.WithCacheLastModifiedFunc(func(r *http.Request) time.Time {
filePath := "./static" + r.URL.Path
if info, err := os.Stat(filePath); err == nil {
return info.ModTime()
}
return time.Now()
}))
// Get modification time from database
server := servex.New(servex.WithCacheLastModifiedFunc(func(r *http.Request) time.Time {
resourceID := getResourceID(r)
return getResourceModTime(resourceID)
}))
// Use current time for dynamic content
server := servex.New(servex.WithCacheLastModifiedFunc(func(r *http.Request) time.Time {
return time.Now().Truncate(time.Minute) // Round to minute for better caching
}))
Use for content where modification time varies per request or resource.
func WithCacheLastModifiedTime ¶
WithCacheLastModifiedTime sets the Last-Modified header using a time.Time value. This automatically formats the time using HTTP time format (RFC 7231).
Example:
// Set last modified to file modification time
fileInfo, _ := os.Stat("static/app.js")
server := servex.New(servex.WithCacheLastModifiedTime(fileInfo.ModTime()))
// Set last modified to application start time
server := servex.New(servex.WithCacheLastModifiedTime(time.Now()))
// Combined with Cache-Control for conditional requests
server := servex.New(
servex.WithCacheControl("public, max-age=0, must-revalidate"),
servex.WithCacheLastModifiedTime(time.Now().AddDate(0, 0, -1)),
)
This is more convenient than WithCacheLastModified() when working with time.Time values.
func WithCacheNoCache ¶
func WithCacheNoCache() Option
WithCacheNoCache enables cache control with no-cache directive. Forces caches to revalidate with the origin server before using cached content.
Example:
// API endpoints that change frequently server := servex.New(servex.WithCacheNoCache()) // Combined with ETag for efficient revalidation server := servex.New( servex.WithCacheNoCache(), servex.WithCacheETag(`"v1.2.3"`), )
Use for:
- API responses that may change
- Dynamic content that should be revalidated
- Content where freshness is important
This sets Cache-Control to "no-cache, must-revalidate".
func WithCacheNoStore ¶
func WithCacheNoStore() Option
WithCacheNoStore disables all caching for sensitive content. Prevents any caching of the response by browsers, proxies, or CDNs.
Example:
// Sensitive user data
server := servex.New(servex.WithCacheNoStore())
// Apply only to sensitive endpoints
server := servex.New(
servex.WithCacheNoStore(),
servex.WithCacheIncludePaths("/api/private/*", "/user/settings"),
)
Use for:
- Personal user data
- Authentication endpoints
- Payment information
- Confidential content
This sets Cache-Control to "no-store, no-cache, must-revalidate".
func WithCachePrivate ¶
WithCachePrivate enables private caching with the specified max-age in seconds. Allows only browsers to cache the content, not intermediary proxies or CDNs.
Example:
// Cache user-specific data for 15 minutes (900 seconds)
server := servex.New(servex.WithCachePrivate(900))
// Cache user profile for 5 minutes (300 seconds)
server := servex.New(servex.WithCachePrivate(300))
// Cache personalized content
server := servex.New(
servex.WithCachePrivate(1800), // 30 minutes
servex.WithCacheIncludePaths("/api/user/*"),
)
Use for:
- User-specific content
- Personalized responses
- Content that varies by authentication
- Semi-sensitive data
This sets Cache-Control to "private, max-age=<seconds>".
func WithCachePublic ¶
WithCachePublic enables public caching with the specified max-age in seconds. Allows both browsers and intermediary proxies/CDNs to cache the content.
Example:
// Cache static assets for 1 hour (3600 seconds)
server := servex.New(servex.WithCachePublic(3600))
// Cache API responses for 5 minutes (300 seconds)
server := servex.New(servex.WithCachePublic(300))
// Cache static assets for 1 year with immutable content
server := servex.New(
servex.WithCachePublic(31536000), // 1 year
servex.WithCacheIncludePaths("/static/*"),
)
Use for:
- Static assets (CSS, JS, images)
- Public API responses
- Documentation
- Content that doesn't vary by user
This sets Cache-Control to "public, max-age=<seconds>".
func WithCacheStaticAssets ¶
WithCacheStaticAssets enables optimized caching for static assets. Sets long-term public caching with immutable directive for maximum performance.
Example:
// Cache static assets for 1 year (default)
server := servex.New(
servex.WithCacheStaticAssets(0), // Uses default 1 year
servex.WithCacheIncludePaths("/static/*", "/assets/*"),
)
// Cache static assets for 6 months
server := servex.New(
servex.WithCacheStaticAssets(15552000), // 6 months
servex.WithCacheIncludePaths("/js/*", "/css/*", "/images/*"),
)
// Perfect for versioned static assets
server := servex.New(
servex.WithCacheStaticAssets(0),
servex.WithCacheIncludePaths("/static/v*/", "/assets/build/*"),
servex.WithCacheVary("Accept-Encoding"),
)
Use for:
- Versioned static files (CSS, JS, images)
- Build artifacts with hashes in filenames
- Content that never changes once deployed
- CDN-optimized assets
This sets Cache-Control to "public, max-age=<seconds>, immutable". If maxAgeSeconds is 0, defaults to 31536000 (1 year).
func WithCacheVary ¶
WithCacheVary sets the Vary header to specify which request headers affect caching. This tells caches that the response varies based on certain request headers.
Example:
// Content varies by compression
server := servex.New(servex.WithCacheVary("Accept-Encoding"))
// Content varies by multiple headers
server := servex.New(servex.WithCacheVary("Accept-Encoding, User-Agent, Accept-Language"))
// Combined with Cache-Control
server := servex.New(
servex.WithCacheControl("public, max-age=3600"),
servex.WithCacheVary("Accept-Encoding"),
)
Common Vary values:
- "Accept-Encoding": Different compression formats
- "User-Agent": Different responses for different browsers
- "Accept": Different content types (JSON vs XML)
- "Authorization": Different responses for authenticated users
- "Accept-Language": Different languages
Important: Only include headers that actually affect the response to avoid cache fragmentation.
func WithCertificate ¶
func WithCertificate(cert tls.Certificate) Option
WithCertificate sets the TLS certificate for the server from a pre-loaded tls.Certificate. This enables HTTPS support on the server. You must start the server with an HTTPS address for the certificate to be used.
Example:
cert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
options.Certificate = &cert
server := servex.New(servex.WithCertificate(cert))
server.Start("", ":8443") // HTTPS only
Use this when you have already loaded the certificate in memory, perhaps for certificate rotation or when loading from embedded files.
func WithCertificateFromFile ¶
WithCertificateFromFile configures the server to load TLS certificate from files. This enables HTTPS support on the server. The certificate files will be loaded when the server starts. You must start the server with an HTTPS address for the certificate to be used.
Parameters:
- certFilePath: Path to the PEM-encoded certificate file
- keyFilePath: Path to the PEM-encoded private key file
Example:
// Load certificate from files
server := servex.New(servex.WithCertificateFromFile("server.crt", "server.key"))
server.Start(":8080", ":8443") // Both HTTP and HTTPS
// HTTPS only server
server := servex.New(servex.WithCertificateFromFile("cert.pem", "key.pem"))
server.Start("", ":8443") // HTTPS only
This is the most common way to configure TLS certificates. Ensure the files are readable by the application and contain valid PEM-encoded data.
func WithCertificatePtr ¶
func WithCertificatePtr(cert *tls.Certificate) Option
WithCertificatePtr sets the TLS certificate for the server from a pointer to tls.Certificate. This enables HTTPS support on the server. You must start the server with an HTTPS address for the certificate to be used.
Example:
cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
server := servex.New(servex.WithCertificatePtr(&cert))
server.Start("", ":8443") // HTTPS only
Use this when you need to pass a certificate pointer, useful when sharing certificate instances or when the certificate is managed externally.
func WithCompression ¶ added in v2.2.0
func WithCompression() Option
WithCompression enables HTTP response compression with sensible defaults. This automatically compresses text-based responses using gzip encoding.
Default configuration:
- Compression level: 6 (balanced speed/compression)
- Minimum size: 1KB
- Types: HTML, CSS, JS, JSON, XML, plain text, SVG
- All paths included unless specifically excluded
Example:
// Enable compression with defaults server, _ := servex.New(servex.WithCompression()) // Enable compression with custom minimum size server, _ := servex.New( servex.WithCompression(), servex.WithCompressionMinSize(512), )
Benefits:
- Reduces bandwidth usage by 60-80% for text content
- Improves page load times
- Lower hosting costs
- Better user experience
func WithCompressionConfig ¶ added in v2.2.0
func WithCompressionConfig(compression CompressionConfig) Option
WithCompressionConfig sets the complete compression configuration. This provides full control over all compression settings.
Example:
compressionConfig := servex.CompressionConfig{
Enabled: true,
Level: 6,
MinSize: 1024,
Types: []string{"text/html", "application/json", "text/css"},
ExcludePaths: []string{"/api/binary/*"},
}
server, _ := servex.New(servex.WithCompressionConfig(compressionConfig))
For simpler setups, consider using WithCompression() instead.
func WithCompressionExcludePaths ¶ added in v2.2.0
WithCompressionExcludePaths sets paths that should be excluded from compression. Responses for these paths will not be compressed regardless of other settings.
Parameters:
- paths: List of path patterns to exclude (supports wildcards with *)
Common exclusions:
- "/api/binary/*": Binary API endpoints
- "/downloads/*": File download endpoints
- "/images/*": Image files (already compressed)
- "/videos/*": Video files (already compressed)
Example:
// Exclude binary and media endpoints
server, _ := servex.New(
servex.WithCompression(),
servex.WithCompressionExcludePaths("/api/binary/*", "/downloads/*", "/media/*"),
)
Path matching supports wildcards (*) for pattern matching.
func WithCompressionIncludePaths ¶ added in v2.2.0
WithCompressionIncludePaths sets paths that should have compression applied. If set, only responses for these paths will be compressed.
Parameters:
- paths: List of path patterns to include (supports wildcards with *)
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to be considered for compression
- Paths in ExcludePaths are then excluded from compression
Example:
// Compress only API and static assets
server, _ := servex.New(
servex.WithCompression(),
servex.WithCompressionIncludePaths("/api/*", "/static/*"),
)
// Compress specific content areas
server, _ := servex.New(
servex.WithCompression(),
servex.WithCompressionIncludePaths("/docs/*", "/help/*", "/blog/*"),
)
Path matching supports wildcards (*) for pattern matching. Leave empty to apply compression to all paths (default behavior).
func WithCompressionLevel ¶ added in v2.2.0
WithCompressionLevel sets the compression level for gzip encoding. Higher levels provide better compression but use more CPU.
Valid range: 1-9
- 1: Fastest compression, lower CPU usage
- 6: Default balance (recommended)
- 9: Best compression, higher CPU usage
Example:
// Fast compression for high-traffic servers server, _ := servex.New( servex.WithCompression(), servex.WithCompressionLevel(1), ) // Maximum compression for bandwidth-constrained environments server, _ := servex.New( servex.WithCompression(), servex.WithCompressionLevel(9), )
func WithCompressionMinSize ¶ added in v2.2.0
WithCompressionMinSize sets the minimum response size to trigger compression. Responses smaller than this size will not be compressed.
Parameters:
- size: Minimum size in bytes (0 to compress all responses)
Example:
// Only compress responses larger than 2KB server, _ := servex.New( servex.WithCompression(), servex.WithCompressionMinSize(2048), ) // Compress all responses regardless of size server, _ := servex.New( servex.WithCompression(), servex.WithCompressionMinSize(0), )
Considerations:
- Small responses may not benefit from compression
- Compression adds CPU overhead
- Network overhead for small responses may negate benefits
func WithCompressionTypes ¶ added in v2.2.0
WithCompressionTypes sets the MIME types that should be compressed. Only responses with these content types will be compressed.
Parameters:
- types: List of MIME types to compress
Common types:
- "text/html": HTML pages
- "text/css": CSS stylesheets
- "application/javascript": JavaScript files
- "application/json": JSON API responses
- "text/xml": XML responses
- "text/plain": Plain text files
- "image/svg+xml": SVG images
Example:
// Compress only JSON and HTML
server, _ := servex.New(
servex.WithCompression(),
servex.WithCompressionTypes("application/json", "text/html"),
)
// Add additional types to defaults
server, _ := servex.New(
servex.WithCompression(),
servex.WithCompressionTypes("application/pdf", "text/csv"),
)
func WithContentSecurityPolicy ¶
WithContentSecurityPolicy sets the Content-Security-Policy header to prevent XSS attacks. CSP controls which resources (scripts, styles, images, etc.) can be loaded by the browser.
Example:
// Basic CSP allowing only same-origin resources
server := servex.New(servex.WithContentSecurityPolicy("default-src 'self'"))
// CSP allowing external CDNs
server := servex.New(servex.WithContentSecurityPolicy(
"default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'",
))
// CSP for API-only server (no resources)
server := servex.New(servex.WithContentSecurityPolicy("default-src 'none'"))
Common CSP directives:
- default-src: Default policy for all resource types
- script-src: JavaScript sources
- style-src: CSS sources
- img-src: Image sources
- connect-src: AJAX, WebSocket, EventSource sources
- font-src: Font sources
- object-src: Plugin sources (usually set to 'none')
- media-src: Video/audio sources
- frame-src: Iframe sources
Common values:
- 'self': Same origin as the document
- 'none': No resources allowed
- 'unsafe-inline': Allow inline scripts/styles (not recommended)
- 'unsafe-eval': Allow eval() (not recommended)
- https://example.com: Specific domains
Security note: CSP is one of the most effective defenses against XSS attacks. Start with a restrictive policy and gradually allow necessary resources.
func WithCustomHeaders ¶
WithCustomHeaders sets custom HTTP headers that will be added to all responses. These headers are applied after security headers and can override them.
Example:
// Add custom API headers
server := servex.New(servex.WithCustomHeaders(map[string]string{
"X-API-Version": "v1.0",
"X-Service-Name": "user-service",
"X-Environment": "production",
}))
// Add caching headers
server := servex.New(servex.WithCustomHeaders(map[string]string{
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0",
}))
// Add CORS headers (basic example)
server := servex.New(servex.WithCustomHeaders(map[string]string{
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
}))
Use cases:
- API versioning headers
- Service identification
- Custom caching policies
- CORS configuration
- Application-specific headers
- Debugging and monitoring headers
Note: Custom headers can override security headers if they have the same name. For security headers, prefer using the dedicated security options instead.
func WithDefaultAuditLogger ¶
func WithDefaultAuditLogger() Option
WithDefaultAuditLogger enables default audit logging using the server's logger. This creates a DefaultAuditLogger that logs security events using structured logging.
Example:
// Enable basic audit logging server := servex.New( servex.WithDefaultAuditLogger(), ) // Enable audit logging with headers included (be careful with sensitive data) server := servex.New( servex.WithDefaultAuditLogger(), servex.WithAuditLogHeaders(true), )
The default audit logger will:
- Log authentication events (login, logout, token validation)
- Log rate limiting violations
- Log request filtering blocks (IP, User-Agent, etc.)
- Log CSRF protection events
- Log suspicious activities
All events are logged with structured fields for easy parsing and analysis.
func WithDefaultMetrics ¶
WithDefaultMetrics enables the default built-in metrics endpoint with Prometheus-compatible output.
This creates a comprehensive metrics endpoint that tracks:
- Total requests, responses, and errors
- Error rate percentage
- Average response time in milliseconds
- Requests per second
- Response status code distribution (2xx, 3xx, 4xx, 5xx)
- HTTP method distribution (GET, POST, PUT, DELETE, etc.)
- Per-path request counts and timing statistics
- System metrics (memory usage, goroutine count, GC stats)
The metrics endpoint outputs in Prometheus text format (version 0.0.4) and can be scraped by Prometheus, Grafana, or other monitoring tools.
Example:
// Enable default metrics at /metrics
server := servex.New(servex.WithDefaultMetrics())
// Custom metrics path
server := servex.New(servex.WithDefaultMetrics("/stats"))
// Combined with other monitoring features
server := servex.New(
servex.WithDefaultMetrics("/metrics"),
servex.WithHealthEndpoint(),
servex.WithRequestLogger(myLogger),
)
Available metrics include:
- servex_requests_total - Total number of HTTP requests
- servex_responses_total - Total number of HTTP responses
- servex_errors_total - Total number of errors (4xx and 5xx)
- servex_error_rate_percent - Percentage of requests that resulted in errors
- servex_requests_per_second - Current request rate
- servex_response_time_ms_avg - Average response time in milliseconds
- servex_responses_by_status_total{status="200"} - Responses by status code
- servex_requests_by_method_total{method="GET"} - Requests by HTTP method
- servex_requests_by_path_total{path="/api/users"} - Requests by path
- servex_memory_usage_bytes - Current memory usage
- servex_goroutines - Number of active goroutines
- servex_gc_count - Total garbage collection count
Default path: "/metrics" if not specified.
Use this when:
- You want quick observability without writing custom metrics
- You need Prometheus-compatible metrics
- You want built-in system and HTTP metrics
- You're building a production service and need monitoring
Note: This automatically creates and registers a metrics endpoint. For custom metrics, use WithMetrics() instead.
func WithDisableHealthEndpoint ¶ added in v2.3.0
func WithDisableHealthEndpoint() Option
WithDisableHealthEndpoint disables the automatic health check endpoint.
The health endpoint is enabled by default for production readiness. Use this function to explicitly disable it if you:
- Don't need health checks
- Have your own custom health check endpoint
- Want to minimize exposed endpoints
- Are running in an environment without load balancers
Example:
// Disable the default health endpoint
server := servex.New(servex.WithDisableHealthEndpoint())
// Disable and implement custom health logic
server := servex.New(servex.WithDisableHealthEndpoint())
server.Get("/custom-health", func(w http.ResponseWriter, r *http.Request) {
// Custom health check logic
servex.C(w, r).Response(200, map[string]string{"status": "healthy"})
})
Note: Most production applications should keep the health endpoint enabled for proper monitoring and orchestration.
func WithDisableRequestLogging ¶
func WithDisableRequestLogging() Option
WithDisableRequestLogging disables HTTP request logging completely. This is an alias for WithNoRequestLog().
Example:
server := servex.New(servex.WithDisableRequestLogging())
See WithNoRequestLog() for detailed documentation.
func WithEnableRequestSizeLimits ¶
WithEnableRequestSizeLimits enables global request size limit middleware. When enabled, all requests are checked against the configured size limits. Individual endpoints can still use smaller limits via context methods.
Use cases for disabling:
- Fine-grained control per endpoint
- Custom size limit middleware
- Performance-critical applications
- Legacy compatibility
func WithFilterConfig ¶
func WithFilterConfig(filter FilterConfig) Option
WithFilterConfig sets the complete request filtering configuration at once. This allows fine-grained control over all filtering settings for IP addresses, User-Agents, headers, and query parameters.
Example:
filterConfig := servex.FilterConfig{
AllowedIPs: []string{"10.0.0.0/8", "192.168.1.100"},
BlockedUserAgents: []string{"BadBot", "Scraper"},
AllowedHeaders: map[string][]string{
"X-API-Version": {"v1", "v2"},
},
StatusCode: 403,
Message: "Access denied by security filter",
ExcludePaths: []string{"/health", "/public/*"},
}
server := servex.New(servex.WithFilterConfig(filterConfig))
Use this when you need to configure multiple filtering settings at once or when loading configuration from files or environment variables.
func WithFilterExcludePaths ¶
WithFilterExcludePaths excludes specific paths from request filtering. Requests to these paths will bypass all filtering rules.
Example:
// Exclude public endpoints from filtering
server := servex.New(
servex.WithAllowedIPs("192.168.1.0/24"),
servex.WithFilterExcludePaths("/health", "/public/*", "/docs/*"),
)
// Exclude monitoring from strict filtering
server := servex.New(
servex.WithBlockedUserAgents("curl"),
servex.WithFilterExcludePaths("/metrics", "/status", "/ping"),
)
Common exclusions:
- Health checks: "/health", "/ping"
- Public APIs: "/public/*", "/api/public/*"
- Documentation: "/docs/*", "/swagger/*"
- Static assets: "/static/*", "/assets/*"
- Monitoring: "/metrics", "/status"
Path matching supports wildcards (*) for pattern matching. Excluded paths bypass ALL filtering rules (IP, User-Agent, headers, query params).
func WithFilterIncludePaths ¶
WithFilterIncludePaths specifies which paths should be filtered. If set, only requests to these paths will be subject to filtering rules.
Example:
// Only filter admin endpoints
server := servex.New(
servex.WithAllowedIPs("192.168.1.0/24"),
servex.WithFilterIncludePaths("/admin/*", "/api/admin/*"),
)
// Filter only sensitive API endpoints
server := servex.New(
servex.WithBlockedUserAgents("curl", "wget"),
servex.WithFilterIncludePaths("/api/sensitive/*", "/api/payment/*"),
)
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to be filtered
- Paths in ExcludePaths are then excluded from filtering
Use cases:
- Protect only sensitive endpoints
- Apply filtering to specific API versions
- Filter only external-facing endpoints
- Granular security control
Path matching supports wildcards (*) for pattern matching.
func WithFilterMessage ¶
WithFilterMessage sets the response message when requests are blocked by filters. Default is "Request blocked by security filter" if not set.
Example:
// Generic security message
server := servex.New(
servex.WithAllowedIPs("192.168.1.0/24"),
servex.WithFilterMessage("Access denied for security reasons"),
)
// Specific filter message
server := servex.New(
servex.WithBlockedUserAgents("BadBot"),
servex.WithFilterMessage("Your user agent is not allowed"),
)
// Helpful message with contact info
server := servex.New(
servex.WithAllowedHeaders(map[string][]string{"X-API-Key": {"validkey"}}),
servex.WithFilterMessage("Missing or invalid API key. Contact [email protected] for access."),
)
Best practices:
- Be clear but not too specific about the filter
- Include contact information for legitimate users
- Avoid revealing security implementation details
- Keep messages user-friendly
The message is returned as plain text in the response body.
func WithFilterStatusCode ¶
WithFilterStatusCode sets the HTTP status code returned when requests are blocked by filters. Default is 403 (Forbidden) if not set.
Example:
// Use standard 403 Forbidden
server := servex.New(
servex.WithAllowedIPs("192.168.1.0/24"),
servex.WithFilterStatusCode(403),
)
// Use 404 to hide the existence of endpoints
server := servex.New(
servex.WithBlockedUserAgents("BadBot"),
servex.WithFilterStatusCode(404),
)
// Use 429 to indicate rate limiting (misleading but sometimes useful)
server := servex.New(
servex.WithBlockedIPs("malicious-range"),
servex.WithFilterStatusCode(429),
)
Common status codes:
- 403 Forbidden (recommended) - Clear about blocking
- 404 Not Found - Hides endpoint existence
- 401 Unauthorized - Suggests authentication needed
- 429 Too Many Requests - Can mislead attackers
Choose based on your security strategy and user experience needs.
func WithFilterTrustedProxies ¶
WithFilterTrustedProxies sets trusted proxy IP addresses or CIDR ranges for accurate client IP detection in filtering.
Example:
// Trust load balancer IPs for filtering
server := servex.New(
servex.WithAllowedIPs("192.168.1.0/24"),
servex.WithFilterTrustedProxies("10.0.0.0/8", "172.16.0.0/12"),
)
// Trust specific proxy servers
server := servex.New(
servex.WithBlockedIPs("malicious-range"),
servex.WithFilterTrustedProxies("192.168.1.100", "192.168.1.101"),
)
How it works:
- Without trusted proxies: Uses r.RemoteAddr (proxy IP) for IP filtering
- With trusted proxies: Uses X-Forwarded-For or X-Real-IP headers
Common proxy ranges:
- AWS ALB: Check AWS documentation for current ranges
- Cloudflare: Use Cloudflare's published IP ranges
- Internal load balancers: Your internal network ranges
- Docker networks: 172.16.0.0/12, 10.0.0.0/8
Security considerations:
- Only list IPs you actually trust
- Malicious clients can spoof X-Forwarded-For headers
- Ensure proxy properly validates and forwards real client IPs
- Consider using separate trusted proxy lists for different purposes
func WithHSTSHeader ¶
WithHSTSHeader sets the Strict-Transport-Security header to enforce HTTPS connections. HSTS prevents protocol downgrade attacks and cookie hijacking.
Parameters:
- maxAge: Maximum age in seconds (typically 31536000 for 1 year)
- includeSubdomains: Whether to apply to all subdomains
- preload: Whether to include in browser HSTS preload lists
Example:
// Basic HSTS for 1 year server := servex.New(servex.WithHSTSHeader(31536000, false, false)) // Header: Strict-Transport-Security: max-age=31536000 // HSTS with subdomains for 1 year server := servex.New(servex.WithHSTSHeader(31536000, true, false)) // Header: Strict-Transport-Security: max-age=31536000; includeSubDomains // Full HSTS with preload server := servex.New(servex.WithHSTSHeader(63072000, true, true)) // Header: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Recommended values:
- Development: 300 (5 minutes) or 0 to disable
- Staging: 86400 (1 day)
- Production: 31536000 (1 year) or more
Important considerations:
- Only enable HSTS when you're confident HTTPS works correctly
- Once enabled, browsers will refuse HTTP connections for the duration
- Preload requires HTTPS to be working perfectly
- Use short max-age initially, increase gradually
Warning: Incorrect HSTS configuration can make your site inaccessible. Test thoroughly before using long max-age values or preload.
func WithHTTPSRedirect ¶ added in v2.1.0
func WithHTTPSRedirect() Option
WithHTTPSRedirect configures the server to automatically redirect HTTP requests to HTTPS. This is a convenience method for the most common HTTPS redirect scenario.
func WithHTTPSRedirectConfig ¶ added in v2.1.0
func WithHTTPSRedirectConfig(config HTTPSRedirectConfig) Option
WithHTTPSRedirectConfig sets the complete HTTPS redirection configuration. This allows fine-grained control over all HTTPS redirect settings.
Example:
httpsConfig := servex.HTTPSRedirectConfig{
Enabled: true,
Permanent: true,
TrustedProxies: []string{"10.0.0.0/8", "172.16.0.0/12"},
ExcludePaths: []string{"/health", "/.well-known/*"},
}
server := servex.New(servex.WithHTTPSRedirectConfig(httpsConfig))
Use this when you need to configure multiple HTTPS redirect settings at once or when loading configuration from files or environment variables.
func WithHTTPSRedirectExcludePaths ¶ added in v2.1.0
WithHTTPSRedirectExcludePaths sets paths that should be excluded from HTTPS redirection. Requests to these paths will not be redirected to HTTPS.
Common exclusions:
- Health checks: "/health", "/ping" (for load balancers that use HTTP)
- Let's Encrypt challenges: "/.well-known/acme-challenge/*"
- Development endpoints: "/debug/*"
- Legacy integrations that require HTTP: "/legacy/*"
Example:
// Exclude health checks and Let's Encrypt challenges
server := servex.New(
servex.WithHTTPSRedirect(),
servex.WithHTTPSRedirectExcludePaths("/health", "/.well-known/*"),
)
Path matching supports wildcards (*) for pattern matching. Use sparingly - most paths should use HTTPS for security.
func WithHTTPSRedirectIncludePaths ¶ added in v2.1.0
WithHTTPSRedirectIncludePaths sets paths that should be included in HTTPS redirection. If set, only requests to these paths will be redirected to HTTPS.
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to be considered for redirection
- Paths in ExcludePaths are then excluded from redirection
Example:
// Only redirect specific sensitive areas
server := servex.New(
servex.WithHTTPSRedirect(),
servex.WithHTTPSRedirectIncludePaths("/admin/*", "/user/*", "/api/private/*"),
)
// Gradual HTTPS migration
server := servex.New(
servex.WithHTTPSRedirect(),
servex.WithHTTPSRedirectIncludePaths("/secure/*"),
)
Use cases:
- Gradual HTTPS migration: Start with specific paths
- Mixed HTTP/HTTPS applications: Only secure sensitive areas
- Testing HTTPS setup: Limit scope during testing
Path matching supports wildcards (*) for pattern matching. Leave empty to redirect all paths (recommended for production).
func WithHTTPSRedirectTemporary ¶ added in v2.1.0
func WithHTTPSRedirectTemporary() Option
WithHTTPSRedirectTemporary enables automatic HTTP to HTTPS redirection using temporary redirects (302). This is useful during development and testing when you don't want browsers to cache the redirects.
Example:
// Enable temporary HTTPS redirection for development server := servex.New(servex.WithHTTPSRedirectTemporary())
For production use, prefer WithHTTPSRedirect() which uses permanent redirects (301) for better SEO and performance.
func WithHTTPSRedirectTrustedProxies ¶ added in v2.1.0
WithHTTPSRedirectTrustedProxies sets the trusted proxy IP addresses or CIDR ranges for accurate HTTP/HTTPS detection when behind load balancers or proxies.
When behind proxies, the server cannot detect HTTPS from r.TLS alone. This setting allows checking X-Forwarded-Proto and similar headers only when the request comes from trusted proxy IPs.
Example:
// Trust common internal networks
server := servex.New(
servex.WithHTTPSRedirect(),
servex.WithHTTPSRedirectTrustedProxies("10.0.0.0/8", "172.16.0.0/12"),
)
// Trust specific load balancer IPs
server := servex.New(
servex.WithHTTPSRedirect(),
servex.WithHTTPSRedirectTrustedProxies("192.168.1.100", "192.168.1.101"),
)
Security note: Only list IPs you actually trust. Malicious clients can spoof X-Forwarded-Proto headers if the proxy IP is trusted.
func WithHealthEndpoint ¶
func WithHealthEndpoint() Option
WithHealthEndpoint enables an automatic health check endpoint that returns server status. This creates a simple endpoint that responds with "OK" and HTTP 200 status.
Note: The health endpoint is enabled by default. You only need to use this function if you want to explicitly enable it after disabling it, or to ensure it's enabled for clarity in your code.
Example:
// Health endpoint is already enabled by default
server := servex.New()
// Available at: GET /health
// Explicitly enable (redundant but clear)
server := servex.New(servex.WithHealthEndpoint())
// Available at: GET /health
// Custom health path
server := servex.New(
servex.WithHealthEndpoint(),
servex.WithHealthPath("/status"),
)
// Available at: GET /status
The health endpoint:
- Returns 200 OK with "OK" body when server is running
- Bypasses authentication and filtering
- Suitable for load balancer health checks
- Kubernetes liveness/readiness probes
- Monitoring systems
Use cases:
- Load balancer health checks
- Kubernetes probes
- Monitoring and alerting
- Service discovery
- Uptime monitoring
To disable the health endpoint, use WithDisableHealthEndpoint(). For custom health logic, implement your own endpoint instead of using this option.
func WithHealthPath ¶
WithHealthPath sets a custom path for the health check endpoint. This only works when WithHealthEndpoint() is also used.
Example:
// Custom health check path
server := servex.New(
servex.WithHealthEndpoint(),
servex.WithHealthPath("/ping"),
)
// Available at: GET /ping
// Health check for specific service
server := servex.New(
servex.WithHealthEndpoint(),
servex.WithHealthPath("/api/v1/health"),
)
// Available at: GET /api/v1/health
Common health check paths:
- "/health" (default)
- "/ping"
- "/status"
- "/healthz" (Kubernetes style)
- "/alive"
- "/ready"
Default is "/health" if not specified. The path should start with "/" and be unique to avoid conflicts.
func WithIdleTimeout ¶
WithIdleTimeout sets the maximum duration that idle Keep-Alive connections will be kept open. After this timeout, idle connections are closed.
A zero or negative value sets the default of 180 seconds.
Example:
// Short idle timeout for high-throughput servers server := servex.New(servex.WithIdleTimeout(30 * time.Second)) // Longer timeout for persistent connections server := servex.New(servex.WithIdleTimeout(5 * time.Minute))
Recommended values:
- Web applications: 120-180 seconds
- APIs with frequent requests: 60-120 seconds
- Microservices: 30-60 seconds
- WebSocket services: 300+ seconds
Shorter timeouts reduce resource usage but may impact performance for clients making frequent requests. Longer timeouts improve performance but consume more server resources.
func WithLogFields ¶
WithLogFields specifies which fields to include in request logs. If not set, all available fields will be logged (default behavior).
Example:
// Log only essential fields server := servex.New(servex.WithLogFields( servex.MethodLogField, servex.URLLogField, servex.StatusLogField, servex.DurationLogField, )) // Log minimal fields for privacy compliance server := servex.New(servex.WithLogFields( servex.MethodLogField, servex.StatusLogField, servex.DurationLogField, ))
Available fields:
- RequestIDLogField: Request ID
- IPLogField: Client IP address
- UserAgentLogField: User-Agent header
- URLLogField: Request URL
- MethodLogField: HTTP method (GET, POST, etc.)
- ProtoLogField: HTTP protocol version
- ErrorLogField: Error information
- ErrorMessageLogField: Error message
- StatusLogField: HTTP status code
- DurationLogField: Request duration in milliseconds
Use this to:
- Reduce log verbosity and storage costs
- Focus on specific metrics or debugging needs
- Comply with privacy regulations (e.g., exclude IP addresses)
- Optimize performance by logging fewer fields
Note: This only affects the default BaseRequestLogger. Custom RequestLogger implementations are not affected by this setting.
func WithLogger ¶
WithLogger sets a custom logger for server events, errors, and panics. The logger must implement the Logger interface. Set via WithLogger().
If not set, servex will create a JSON logger that writes to stderr.
The logger receives:
- Server startup/shutdown events (Info level)
- Request errors and panics (Error level)
- Debug information when available (Debug level)
func WithMaxFileUploadSize ¶
WithMaxFileUploadSize sets the maximum allowed file upload size in bytes. This applies to multipart form uploads and file uploads.
Common configurations:
- Profile images: WithMaxFileUploadSize(10 << 20) // 10 MB
- Document uploads: WithMaxFileUploadSize(200 << 20) // 200 MB
- Media files: WithMaxFileUploadSize(2 << 30) // 2 GB
- Data imports: WithMaxFileUploadSize(1 << 30) // 1 GB
Consider your server's available memory and disk space when setting this limit.
func WithMaxHeaderBytes ¶ added in v2.3.0
WithMaxHeaderBytes sets the maximum size of request headers the server will accept. This controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body.
Example:
// Set max header size to 2 MB server := servex.New(servex.WithMaxHeaderBytes(2 << 20)) // Use with other timeouts for comprehensive protection server := servex.New( servex.WithMaxHeaderBytes(1 << 20), // 1 MB max headers servex.WithReadHeaderTimeout(10 * time.Second), servex.WithReadTimeout(30 * time.Second), )
Recommended values:
- Most applications: 1 MB (1 << 20)
- API servers: 512 KB - 1 MB
- Applications with large headers: 2-4 MB
- Restrictive applications: 256 KB
Default: 1 MB (1 << 20) if not set or zero.
Setting this helps prevent attacks where clients send extremely large headers to consume server resources. A reasonable limit protects against slowloris-style attacks.
func WithMaxJSONBodySize ¶
WithMaxJSONBodySize sets the maximum allowed JSON request body size in bytes. This specifically applies to JSON payloads and takes precedence over MaxRequestBodySize for JSON.
Recommended values:
- API servers: WithMaxJSONBodySize(5 << 20) // 5 MB
- Configuration APIs: WithMaxJSONBodySize(1 << 20) // 1 MB
- Data import APIs: WithMaxJSONBodySize(50 << 20) // 50 MB
- Real-time APIs: WithMaxJSONBodySize(1 << 20) // 1 MB
Smaller JSON limits help prevent JSON parsing attacks and reduce memory usage.
func WithMaxMultipartMemory ¶
WithMaxMultipartMemory sets the maximum memory used for multipart form parsing in bytes. Files larger than this are stored in temporary files on disk.
Balance considerations:
- Higher values: Faster processing, more memory usage
- Lower values: Slower processing, less memory usage, more disk I/O
Recommended: 10-50 MB for most applications Example: WithMaxMultipartMemory(32 << 20) // 32 MB
func WithMaxRequestBodySize ¶
WithMaxRequestBodySize sets the maximum allowed request body size in bytes. This applies to all request bodies including JSON, form data, and file uploads. Use 0 to disable global request size limits.
Common configurations:
- API servers: WithMaxRequestBodySize(10 << 20) // 10 MB
- Web applications: WithMaxRequestBodySize(50 << 20) // 50 MB
- File upload services: WithMaxRequestBodySize(1 << 30) // 1 GB
- Microservices: WithMaxRequestBodySize(5 << 20) // 5 MB
This is a global limit applied via middleware. Individual endpoints can use smaller limits via context methods like ReadJSONWithLimit().
func WithMetrics ¶
WithMetrics sets a custom metrics collector that will be called on each HTTP request and response.
The Metrics interface requires two methods:
- HandleRequest(r *http.Request) - Called when a request arrives
- HandleResponse(r *http.Request, w http.ResponseWriter, statusCode int, duration time.Duration) - Called when response is sent
This allows you to collect detailed metrics about your application's HTTP traffic. When using a custom metrics implementation, the default metrics endpoint is automatically disabled.
Example - Basic Request Counter:
type MyMetrics struct {
requestCount int64
}
func (m *MyMetrics) HandleRequest(r *http.Request) {
atomic.AddInt64(&m.requestCount, 1)
}
func (m *MyMetrics) HandleResponse(r *http.Request, w http.ResponseWriter, statusCode int, duration time.Duration) {
// Track response metrics, status codes, response times, etc.
}
metrics := &MyMetrics{}
server := servex.New(servex.WithMetrics(metrics))
Example - Prometheus Integration:
type PrometheusMetrics struct {
requestsTotal *prometheus.CounterVec
requestDuration *prometheus.HistogramVec
}
func (m *PrometheusMetrics) HandleRequest(r *http.Request) {
// Increment request counter
m.requestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()
}
func (m *PrometheusMetrics) HandleResponse(r *http.Request, w http.ResponseWriter, statusCode int, duration time.Duration) {
// Record response time and status
m.requestDuration.WithLabelValues(r.Method, r.URL.Path, fmt.Sprint(statusCode)).Observe(duration.Seconds())
}
Use cases:
- Prometheus metrics collection with custom labels and buckets
- StatsD or DataDog integration
- Custom analytics and monitoring systems
- Application Performance Monitoring (APM) integration
- Request/response tracking for debugging
- Business metrics (e.g., tracking API usage per customer)
Performance considerations:
- The metrics methods are called for EVERY request, ensure they are fast and non-blocking
- Avoid expensive operations like database writes or external API calls
- Use atomic operations for counters to avoid mutex contention
- Consider using buffering or background workers for complex metric processing
Note: Using WithMetrics disables the default metrics endpoint. If you need both built-in and custom metrics, consider wrapping or composing metrics implementations, or use WithDefaultMetrics() instead for the built-in Prometheus-compatible metrics endpoint.
func WithMetricsAndDefault ¶ added in v2.3.0
WithMetricsAndDefault enables both custom metrics and the default built-in metrics simultaneously.
This function combines your custom Metrics implementation with the built-in default metrics, calling both on each request. This is useful when you want to:
- Send metrics to your own monitoring system (e.g., custom Prometheus metrics)
- Keep the built-in /metrics endpoint for quick observability
- Have both detailed custom metrics and standard HTTP metrics
Both metrics implementations will receive HandleRequest and HandleResponse calls for every request. The default metrics endpoint will still be available at the specified path (default: "/metrics").
Example:
// Your custom Prometheus metrics
customMetrics := &MyPrometheusMetrics{
requestsTotal: prometheus.NewCounterVec(...),
// ... other custom metrics
}
// Enable both custom and default metrics
server := servex.New(
servex.WithMetricsAndDefault(customMetrics),
)
// Now both your custom metrics AND built-in metrics are active
// The /metrics endpoint shows the built-in metrics
// Custom path for built-in metrics
server := servex.New(
servex.WithMetricsAndDefault(customMetrics, "/stats"),
)
Use cases:
- Gradual migration from built-in to custom metrics
- Running both systems in parallel for comparison
- Custom business metrics alongside standard HTTP metrics
- Different metrics for different monitoring systems
Performance note: Both metrics implementations will be called on every request. Ensure both are optimized for high-frequency calls.
func WithMetricsDefault ¶ added in v2.3.0
WithMetricsDefault is an alias for WithDefaultMetrics. It enables the default built-in metrics endpoint with Prometheus-compatible output.
This function provides an alternative naming convention that some developers may find more intuitive (WithMetricsDefault vs WithDefaultMetrics).
Example:
// These are equivalent:
server := servex.New(servex.WithDefaultMetrics())
server := servex.New(servex.WithMetricsDefault())
// Both enable the /metrics endpoint
server := servex.New(servex.WithMetricsDefault("/stats"))
See WithDefaultMetrics() for full documentation and available metrics.
func WithNoLogClientErrors ¶
func WithNoLogClientErrors() Option
WithNoLogClientErrors disables logging of client errors in error level (HTTP status codes 400-499). Server errors (5xx) will still be logged in error level if request logging is enabled.
Example:
// Don't log 404s, 400s, etc. in error level to reduce noise server := servex.New(servex.WithNoLogClientErrors())
Use this to:
- Reduce log noise from bad requests
- Focus on server-side issues
- Improve log readability in production
Commonly filtered errors include:
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 429 Too Many Requests
func WithNoRequestLog ¶
func WithNoRequestLog() Option
WithNoRequestLog disables HTTP request logging completely. No requests will be logged regardless of status or errors.
Example:
// Disable all request logging server := servex.New(servex.WithNoRequestLog())
Use this when:
- You have external request logging (load balancer, proxy)
- You want to reduce log volume
- Performance is critical and logging overhead matters
- You're implementing custom request logging middleware
Note: This only disables request logging. Server events, errors, and panics will still be logged through the main logger.
func WithProxyConfig ¶
func WithProxyConfig(proxy ProxyConfiguration) Option
WithProxyConfig sets the reverse proxy configuration. This enables L7 reverse proxy/API gateway functionality with load balancing, traffic dumping, health checking, and advanced routing capabilities.
Example:
proxyConfig := ProxyConfiguration{
Enabled: true,
Rules: []ProxyRule{
{
Name: "api-backend",
PathPrefix: "/api/",
Backends: []Backend{
{URL: "http://backend1:8080", Weight: 2},
{URL: "http://backend2:8080", Weight: 1},
},
LoadBalancing: WeightedRoundRobinStrategy,
StripPrefix: "/api",
},
},
TrafficDump: TrafficDumpConfig{
Enabled: true,
Directory: "./traffic_dumps",
IncludeBody: true,
},
}
server, _ := servex.New(servex.WithProxyConfig(proxyConfig))
Features:
- Multiple load balancing strategies (round-robin, weighted, least-connections, etc.)
- Health checking with automatic backend failover
- Traffic dumping for analysis and debugging
- Path-based and header-based routing
- Connection pooling and timeout management
- RAW HTTP request logging
func WithRPM ¶
WithRPM sets rate limiting to allow a specific number of requests per minute. This is a convenience function for simple rate limiting configuration.
Example:
// Allow 1000 requests per minute per client server := servex.New(servex.WithRPM(1000)) // Strict rate limiting for public APIs server := servex.New(servex.WithRPM(60)) // 1 request per second average
Equivalent to:
servex.WithRequestsPerInterval(rpm, time.Minute)
Common RPM values:
- Public APIs: 60-1000 RPM
- Internal APIs: 1000-10000 RPM
- File uploads: 10-100 RPM
- Authentication: 10-60 RPM
func WithRPS ¶
WithRPS sets rate limiting to allow a specific number of requests per second. This is a convenience function for simple rate limiting configuration.
Example:
// Allow 10 requests per second per client server := servex.New(servex.WithRPS(10)) // High-throughput API server := servex.New(servex.WithRPS(100))
Equivalent to:
servex.WithRequestsPerInterval(rps, time.Second)
Common RPS values:
- Web applications: 1-10 RPS
- APIs: 10-100 RPS
- High-performance APIs: 100-1000 RPS
- Microservices: 50-500 RPS
func WithRateLimitConfig ¶
func WithRateLimitConfig(rateLimit RateLimitConfig) Option
WithRateLimitConfig sets the complete rate limiting configuration at once. This allows fine-grained control over all rate limiting settings.
Example:
rateLimitConfig := servex.RateLimitConfig{
Enabled: true,
RequestsPerInterval: 100,
Interval: time.Minute,
BurstSize: 20,
StatusCode: 429,
Message: "Rate limit exceeded. Try again later.",
ExcludePaths: []string{"/health", "/metrics"},
TrustedProxies: []string{"10.0.0.0/8"},
}
server := servex.New(servex.WithRateLimitConfig(rateLimitConfig))
Use this when you need to configure multiple rate limiting settings at once or when loading configuration from files or environment variables.
func WithRateLimitExcludePaths ¶
WithRateLimitExcludePaths excludes specific paths from rate limiting. Requests to these paths will not be counted against rate limits.
Example:
// Exclude monitoring endpoints
server := servex.New(
servex.WithRPS(10),
servex.WithRateLimitExcludePaths("/health", "/metrics", "/status"),
)
// Exclude static assets
server := servex.New(
servex.WithRPS(100),
servex.WithRateLimitExcludePaths("/static/*", "/assets/*", "/favicon.ico"),
)
Common exclusions:
- Health checks: "/health", "/ping"
- Metrics: "/metrics", "/stats"
- Static files: "/static/*", "/assets/*"
- Documentation: "/docs/*", "/swagger/*"
- Infrastructure: "/robots.txt", "/favicon.ico"
Path matching supports wildcards (*) for pattern matching.
func WithRateLimitIncludePaths ¶
WithRateLimitIncludePaths specifies which paths should be rate limited. If set, only requests to these paths will be rate limited. All other paths are excluded.
Example:
// Only rate limit API endpoints
server := servex.New(
servex.WithRPS(100),
servex.WithRateLimitIncludePaths("/api/*"),
)
// Rate limit specific sensitive endpoints
server := servex.New(
servex.WithRPS(5),
servex.WithRateLimitIncludePaths("/api/auth/*", "/api/admin/*"),
)
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to be rate limited
- Paths in ExcludePaths are then excluded from rate limiting
Use cases:
- Protect only sensitive endpoints
- Apply different limits to different API versions
- Rate limit only external-facing endpoints
- Granular control over protection
func WithRateLimitKeyFunc ¶
WithRateLimitKeyFunc sets a custom function to extract the rate limit key from requests. This determines how clients are identified for rate limiting purposes.
Example:
// Rate limit by IP address
server := servex.New(
servex.WithRPS(10),
servex.WithRateLimitKeyFunc(func(r *http.Request) string {
return r.RemoteAddr
}),
)
// Rate limit by API key
server := servex.New(
servex.WithRPS(100),
servex.WithRateLimitKeyFunc(func(r *http.Request) string {
apiKey := r.Header.Get("X-API-Key")
if apiKey == "" {
return r.RemoteAddr // Fallback to IP
}
return "api:" + apiKey
}),
)
// Rate limit by user ID (requires auth)
server := servex.New(
servex.WithRPS(50),
servex.WithRateLimitKeyFunc(func(r *http.Request) string {
userID := r.Context().Value("userID")
if userID != nil {
return "user:" + userID.(string)
}
return r.RemoteAddr
}),
)
Default behavior uses client IP address. Custom key functions enable:
- User-based rate limiting
- API key-based limits
- Different limits for different client types
- Combined identification strategies
func WithRateLimitMessage ¶
WithRateLimitMessage sets the response message when rate limit is exceeded. Default is "rate limit exceeded, try again later." if not set.
Example:
// Custom rate limit message
server := servex.New(
servex.WithRPS(10),
servex.WithRateLimitMessage("Too many requests. Please slow down and try again in a few moments."),
)
// Include retry information
server := servex.New(
servex.WithRPM(100),
servex.WithRateLimitMessage("Rate limit exceeded. Maximum 100 requests per minute allowed."),
)
Best practices:
- Be clear about the limit
- Suggest when to retry
- Keep messages user-friendly
- Include contact information for questions
The message is returned as plain text in the response body.
func WithRateLimitStatusCode ¶
WithRateLimitStatusCode sets the HTTP status code returned when rate limit is exceeded. Default is 429 (Too Many Requests) if not set.
Example:
// Use standard 429 status server := servex.New( servex.WithRPS(10), servex.WithRateLimitStatusCode(429), ) // Use 503 Service Unavailable server := servex.New( servex.WithRPS(10), servex.WithRateLimitStatusCode(503), )
Common status codes:
- 429 Too Many Requests (recommended)
- 503 Service Unavailable
- 502 Bad Gateway (for proxy scenarios)
The 429 status code is specifically designed for rate limiting and is understood by most HTTP clients and libraries.
func WithRateLimitTrustedProxies ¶
WithRateLimitTrustedProxies sets trusted proxy IP addresses or CIDR ranges for accurate client IP detection in rate limiting.
Example:
// Trust load balancer IPs
server := servex.New(
servex.WithRPS(10),
servex.WithRateLimitTrustedProxies("10.0.0.0/8", "172.16.0.0/12"),
)
// Trust specific proxy servers
server := servex.New(
servex.WithRPS(100),
servex.WithRateLimitTrustedProxies("192.168.1.100", "192.168.1.101"),
)
How it works:
- Without trusted proxies: Uses r.RemoteAddr (proxy IP)
- With trusted proxies: Uses X-Forwarded-For or X-Real-IP headers
Common proxy ranges:
- AWS ALB: Check AWS documentation for current ranges
- Cloudflare: Use Cloudflare's published IP ranges
- Internal load balancers: Your internal network ranges
- Docker networks: 172.16.0.0/12, 10.0.0.0/8
Security note: Only list IPs you actually trust. Malicious clients can spoof X-Forwarded-For headers if the proxy IP is trusted.
func WithReadHeaderTimeout ¶
WithReadHeaderTimeout sets the maximum duration for reading request headers. This timeout is specifically for reading the HTTP headers, not the body. After headers are read, ReadTimeout takes over for the body.
A zero or negative value sets the default of 60 seconds.
Example:
// Fast header timeout for performance server := servex.New(servex.WithReadHeaderTimeout(5 * time.Second)) // Combined with read timeout server := servex.New( servex.WithReadHeaderTimeout(5 * time.Second), servex.WithReadTimeout(30 * time.Second), )
Recommended values:
- Most applications: 2-10 seconds
- High-performance APIs: 2-5 seconds
- Development: 10-30 seconds
This should typically be shorter than ReadTimeout since headers are usually small. Protects against slow header attacks where clients send headers very slowly.
func WithReadTimeout ¶
WithReadTimeout sets the maximum duration for reading the entire request, including the body. This timeout starts when the connection is accepted and ends when the request body is fully read. It includes time for reading headers and body.
A zero or negative value sets the default of 60 seconds.
Example:
// Short timeout for API servers server := servex.New(servex.WithReadTimeout(10 * time.Second)) // Longer timeout for file upload endpoints server := servex.New(servex.WithReadTimeout(5 * time.Minute))
Recommended values:
- API servers: 10-30 seconds
- Web applications: 30-60 seconds
- File upload services: 5-15 minutes
- Microservices: 5-15 seconds
Setting this too low may cause legitimate requests to timeout. Setting this too high may allow slow clients to exhaust server resources.
func WithRemoveHeaders ¶
WithRemoveHeaders removes specific headers from responses. This is useful for removing server identification headers or other unwanted headers.
Example:
// Remove server identification headers
server := servex.New(servex.WithRemoveHeaders("Server", "X-Powered-By"))
// Remove additional headers for security
server := servex.New(servex.WithRemoveHeaders(
"Server",
"X-Powered-By",
"X-AspNet-Version",
"X-AspNetMvc-Version",
))
// Remove caching headers
server := servex.New(servex.WithRemoveHeaders("ETag", "Last-Modified"))
Common headers to remove:
- "Server": Web server software identification
- "X-Powered-By": Technology stack identification
- "X-AspNet-Version": ASP.NET version (if proxying)
- "X-AspNetMvc-Version": ASP.NET MVC version
- "X-Generator": Content generator identification
Use cases:
- Security through obscurity
- Reduce information disclosure
- Clean up response headers
- Remove redundant headers
- Compliance requirements
Note: This removes headers that might be added by the Go HTTP server, middleware, or upstream proxies. Some headers like "Server" are added by the Go standard library and will be removed by this option.
func WithRequestLogger ¶
func WithRequestLogger(r RequestLogger) Option
WithRequestLogger sets a custom logger specifically for HTTP request logging. This is separate from the main logger and focuses on request/response details.
If not set, it will use the main Logger in debug level for successful requests.
Use for:
- Structured request logging
- Access logs
- Request metrics
- Audit trails
func WithRequestSizeLimits ¶
func WithRequestSizeLimits() Option
WithRequestSizeLimits configures comprehensive request size limits with commonly used defaults. This is a convenience function that sets up reasonable defaults for most applications.
Default limits set:
- MaxRequestBodySize: 100 MB
- MaxJSONBodySize: 1 MB
- MaxFileUploadSize: 100 MB
- MaxMultipartMemory: 10 MB
- EnableRequestSizeLimits: true
Use individual WithMax* functions for custom limits.
func WithRequestsPerInterval ¶
WithRequestsPerInterval sets custom rate limiting with a specific number of requests allowed per time interval. This provides maximum flexibility for rate limiting configuration.
Example:
// 500 requests per 5 minutes server := servex.New(servex.WithRequestsPerInterval(500, 5*time.Minute)) // 50 requests per 30 seconds server := servex.New(servex.WithRequestsPerInterval(50, 30*time.Second)) // 1000 requests per hour server := servex.New(servex.WithRequestsPerInterval(1000, time.Hour))
Use cases:
- Custom business requirements
- Unusual time windows
- Integration with external rate limits
- Compliance with API provider limits
The rate limiter uses a token bucket algorithm, refilling tokens at a constant rate.
func WithSPAMode ¶
WithSPAMode enables Single Page Application (SPA) mode for serving React, Vue, Angular apps. This serves static files from the directory and provides fallback routing for client-side navigation.
In SPA mode:
- Static files are served normally (JS, CSS, images, etc.)
- API routes continue to work (register them before calling this)
- All other routes serve the index file for client-side routing
Parameters:
- dir: Directory containing SPA build files (e.g., "build", "dist")
- indexFile: Fallback file for client-side routing (typically "index.html")
Usage pattern:
- Register your API routes first
- Enable SPA mode last
Examples:
// React app setup
server, _ := servex.New(servex.WithSPAMode("build", "index.html"))
server.GET("/api/users", handleUsers) // API routes work
server.GET("/about", handleUsers) // Serves index.html for client routing
// Vue app setup
server, _ := servex.New(servex.WithSPAMode("dist", "index.html"))
func WithSecurityConfig ¶
func WithSecurityConfig(security SecurityConfig) Option
WithSecurityConfig sets the complete security headers configuration at once. This allows fine-grained control over all security headers applied to responses.
Example:
securityConfig := servex.SecurityConfig{
Enabled: true,
ContentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'",
XContentTypeOptions: "nosniff",
XFrameOptions: "DENY",
XXSSProtection: "1; mode=block",
StrictTransportSecurity: "max-age=31536000; includeSubDomains",
}
server := servex.New(servex.WithSecurityConfig(securityConfig))
Use this when you need to configure multiple security headers at once or when loading configuration from files or environment variables.
func WithSecurityExcludePaths ¶
WithSecurityExcludePaths excludes specific paths from security headers. Requests to these paths will not receive security headers.
Example:
// Exclude API endpoints from security headers
server := servex.New(
servex.WithSecurityHeaders(),
servex.WithSecurityExcludePaths("/api/*", "/webhooks/*"),
)
// Exclude development tools
server := servex.New(
servex.WithStrictSecurityHeaders(),
servex.WithSecurityExcludePaths("/debug/*", "/metrics", "/health"),
)
Common exclusions:
- API endpoints: "/api/*" (may not need web security headers)
- Webhooks: "/webhooks/*" (external services)
- Health checks: "/health", "/ping"
- Metrics: "/metrics", "/prometheus"
- Development: "/debug/*", "/dev/*"
- Static assets: "/static/*" (may need different CSP)
Use cases:
- API endpoints that don't serve HTML
- Third-party integrations
- Resources with specific security requirements
- Legacy endpoints with compatibility issues
Path matching supports wildcards (*) for pattern matching.
func WithSecurityHeaders ¶
func WithSecurityHeaders() Option
WithSecurityHeaders enables basic security headers with safe default values. This is a convenience function that applies commonly recommended security headers.
Example:
// Apply basic security headers server := servex.New(servex.WithSecurityHeaders())
Headers applied:
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
Use cases:
- Quick security improvement
- Development and testing
- Basic web application protection
- Starting point for custom security headers
For custom security headers or stricter settings, use WithStrictSecurityHeaders() or configure individual headers with specific options.
func WithSecurityIncludePaths ¶
WithSecurityIncludePaths specifies which paths should receive security headers. If set, only requests to these paths will get security headers applied.
Example:
// Only apply security headers to web pages
server := servex.New(
servex.WithSecurityHeaders(),
servex.WithSecurityIncludePaths("/", "/login", "/dashboard/*"),
)
// Apply to specific web applications
server := servex.New(
servex.WithStrictSecurityHeaders(),
servex.WithSecurityIncludePaths("/webapp/*", "/admin/*"),
)
If both IncludePaths and ExcludePaths are set:
- Paths must match IncludePaths to receive headers
- Paths in ExcludePaths are then excluded from headers
Use cases:
- Mixed API and web application
- Multiple applications on same server
- Granular security control
- Progressive security header rollout
Path matching supports wildcards (*) for pattern matching.
func WithSendErrorToClient ¶
func WithSendErrorToClient() Option
WithSendErrorToClient configures the server to include detailed error information in HTTP responses when errors occur. This includes Go error messages and stack traces.
Example:
// Development server with detailed errors server := servex.New(servex.WithSendErrorToClient()) // Production server (don't send error details) server := servex.New() // Default is false
When enabled, responses might include:
- Internal error messages
- Stack traces for panics
- Database connection errors
- File system errors
Security considerations:
- NEVER enable this in production
- Error details can reveal system information
- Use only for development and testing
- Consider using structured error responses instead
For production, implement proper error handling that returns safe, user-friendly error messages while logging detailed errors server-side.
func WithStaticFileCache ¶
WithStaticFileCache sets cache policies for static files. This controls how long browsers and proxies cache static files.
Parameters:
- maxAge: Default cache duration in seconds
- rules: File extension or path-specific cache rules
The rules map allows different cache durations for different file types:
- Key: File extension (e.g., ".js", ".css") or path pattern (e.g., "/images/*")
- Value: Cache duration in seconds
Example:
// Basic cache setup
servex.WithStaticFileCache(3600, nil) // 1 hour for all files
// Advanced cache setup with rules
rules := map[string]int{
".js": 31536000, // 1 year for JS files
".css": 31536000, // 1 year for CSS files
".html": 3600, // 1 hour for HTML files
"/images/*": 2592000, // 30 days for images
}
servex.WithStaticFileCache(86400, rules) // 1 day default, custom rules
func WithStaticFileConfig ¶
func WithStaticFileConfig(config StaticFileConfig) Option
WithStaticFileConfig sets the static file serving configuration. This provides full control over all static file serving options. Use this when you need granular control over file serving behavior.
For simpler setups, consider using WithStaticFiles() or WithSPAMode() instead.
Example:
cfg := servex.StaticFileConfig{
Enabled: true,
Dir: "build",
SPAMode: true,
IndexFile: "index.html",
CacheMaxAge: 3600,
ExcludePaths: []string{"/api/*"},
CacheRules: map[string]int{
".js": 31536000, // 1 year
".css": 31536000, // 1 year
".html": 3600, // 1 hour
},
}
server, _ := servex.New(servex.WithStaticFileConfig(cfg))
func WithStaticFileExclusions ¶
WithStaticFileExclusions sets paths that should not be served as static files. These paths will be skipped by the static file handler, allowing API routes to handle them.
This is useful when you want to exclude certain paths from static file serving, such as API endpoints that should be handled by custom handlers.
Parameters:
- paths: List of path patterns to exclude (supports wildcards with *)
Common exclusions:
- "/api/*": All API endpoints
- "/auth/*": Authentication endpoints
- "/admin/*": Admin interfaces
- "/ws/*": WebSocket endpoints
Note: API routes registered before static files are automatically excluded.
Example:
server, _ := servex.New(
servex.WithSPAMode("build", "index.html"),
servex.WithStaticFileExclusions("/api/*", "/auth/*"),
)
func WithStaticFiles ¶
WithStaticFiles enables static file serving from the specified directory. This is a simple way to serve static files from a directory.
Parameters:
- dir: Directory containing static files to serve
- urlPrefix: URL path prefix (empty for root, e.g., "/static")
For SPA support with client-side routing, use WithSPAMode() instead.
Examples:
// Serve files from "public/" at root path
servex.WithStaticFiles("public", "")
// Serve files from "assets/" under "/static" path
servex.WithStaticFiles("assets", "/static")
// Complete example
server, _ := servex.New(servex.WithStaticFiles("build", ""))
func WithStrictRequestSizeLimits ¶
func WithStrictRequestSizeLimits() Option
WithStrictRequestSizeLimits enables request size limits with strict, secure default values. This configuration prioritizes security over convenience with smaller size limits. Use for applications where security is more important than convenience.
func WithStrictSecurityHeaders ¶
func WithStrictSecurityHeaders() Option
WithStrictSecurityHeaders enables comprehensive security headers with strict settings. This applies a full set of security headers suitable for high-security environments.
Example:
// Apply strict security headers server := servex.New(servex.WithStrictSecurityHeaders())
Headers applied:
- Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: camera=(), microphone=(), geolocation=()
- X-Permitted-Cross-Domain-Policies: none
- Cross-Origin-Embedder-Policy: require-corp
- Cross-Origin-Opener-Policy: same-origin
- Cross-Origin-Resource-Policy: same-site
Use cases:
- High-security applications
- Financial services
- Healthcare applications
- Government systems
- Production web applications
Warning: These strict headers may break functionality that requires:
- External scripts or stylesheets
- Iframe embedding
- Cross-origin requests
- Third-party integrations
Test thoroughly and adjust headers as needed for your application.
type Options ¶
type Options struct {
// Certificate is the TLS certificate for HTTPS server support.
// This enables HTTPS support when the server is started with an HTTPS address.
// Use WithCertificate() to set a pre-loaded certificate, or WithCertificateFromFile()
// to load from files. If not set, only HTTP will be available.
//
// Example:
// cert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
// options.Certificate = &cert
Certificate *tls.Certificate
// CertFilePath is the path to the TLS certificate file for loading at server startup.
// The file should contain the PEM-encoded certificate chain.
// Used with KeyFilePath to enable HTTPS. Set via WithCertificateFromFile().
//
// Examples:
// - "/etc/ssl/certs/server.crt"
// - "./certs/certificate.pem"
// - "/path/to/fullchain.pem" (Let's Encrypt style)
CertFilePath string
// KeyFilePath is the path to the TLS private key file for loading at server startup.
// The file should contain the PEM-encoded private key.
// Used with CertFilePath to enable HTTPS. Set via WithCertificateFromFile().
//
// Examples:
// - "/etc/ssl/private/server.key"
// - "./certs/private.pem"
// - "/path/to/privkey.pem" (Let's Encrypt style)
KeyFilePath string
// ReadTimeout is the maximum duration for reading the entire request, including the body.
// This timeout starts when the connection is accepted and ends when the request body
// is fully read. Set via WithReadTimeout().
//
// Recommended values:
// - API servers: 10-30 seconds
// - Web applications: 30-60 seconds
// - File upload services: 5-15 minutes
// - Microservices: 5-15 seconds
//
// Default: 60 seconds if not set or zero.
ReadTimeout time.Duration
// ReadHeaderTimeout is the maximum duration for reading request headers.
// This timeout is specifically for reading the HTTP headers, not the body.
// After headers are read, ReadTimeout takes over for the body. Set via WithReadHeaderTimeout().
//
// Recommended values:
// - Most applications: 2-10 seconds
// - High-performance APIs: 2-5 seconds
// - Development: 10-30 seconds
//
// Default: 60 seconds if not set or zero.
ReadHeaderTimeout time.Duration
// IdleTimeout is the maximum duration that idle Keep-Alive connections will be kept open.
// After this timeout, idle connections are closed. Set via WithIdleTimeout().
//
// Recommended values:
// - Web applications: 120-180 seconds
// - APIs with frequent requests: 60-120 seconds
// - Microservices: 30-60 seconds
// - WebSocket services: 300+ seconds
//
// Default: 180 seconds if not set or zero.
IdleTimeout time.Duration
// MaxHeaderBytes is the maximum size of request headers in bytes.
// This controls the maximum number of bytes the server will read parsing the request header's keys and values,
// including the request line. It does not limit the size of the request body.
// Set via WithMaxHeaderBytes().
//
// Recommended values:
// - Most applications: 1 MB (1 << 20)
// - API servers: 512 KB - 1 MB
// - Applications with large headers: 2-4 MB
// - Restrictive applications: 256 KB
//
// Default: 1 MB (1 << 20) if not set or zero.
//
// Setting this helps prevent attacks where clients send extremely large headers
// to consume server resources. A reasonable limit protects against slowloris-style attacks.
MaxHeaderBytes int
// AuthToken enables simple token-based authentication using the Authorization header.
// When set, the server will check for "Authorization: Bearer <token>" headers on
// protected routes. Set via WithAuthToken().
//
// Use cases:
// - Simple API authentication
// - Service-to-service communication
// - Development and testing
//
// For advanced authentication with user management, JWT tokens, and roles,
// use the Auth field instead.
AuthToken string
// Logger is a custom logger for server events, errors, and panics.
// The logger must implement the servex.Logger interface. Set via WithLogger().
//
// If not set, servex will create a JSON logger that writes to stderr.
//
// The logger receives:
// - Server startup/shutdown events (Info level)
// - Request errors and panics (Error level)
// - Debug information when available (Debug level)
Logger Logger
// RequestLogger is a custom logger specifically for HTTP request logging.
// This is separate from the main logger and focuses on request/response details.
// Set via WithRequestLogger().
//
// If not set, it will use the main Logger in debug level for successful requests.
//
// Use for:
// - Structured request logging
// - Access logs
// - Request metrics
// - Audit trails
RequestLogger RequestLogger
// DisableRequestLogging disables HTTP request logging completely.
// No requests will be logged regardless of status or errors.
// Set to true via WithNoRequestLog() or WithDisableRequestLogging().
//
// Use when:
// - You have external request logging (load balancer, proxy)
// - You want to reduce log volume
// - Performance is critical and logging overhead matters
// - You're implementing custom request logging middleware
DisableRequestLogging bool
// NoLogClientErrors disables logging of client errors in error level (HTTP status codes 400-499).
// Server errors (5xx) will still be logged in error level if request logging is enabled.
// Set to true via WithNoLogClientErrors().
//
// Use to:
// - Reduce log noise from bad requests
// - Focus on server-side issues
// - Improve log readability in production
NoLogClientErrors bool
// LogFields specifies which fields to include in request logs.
// If empty, all available fields will be logged (default behavior).
// Set via WithLogFields().
//
// Available fields (use exported constants):
// - servex.RequestIDLogField: Request ID
// - servex.IPLogField: Client IP address
// - servex.UserAgentLogField: User-Agent header
// - servex.URLLogField: Request URL
// - servex.MethodLogField: HTTP method (GET, POST, etc.)
// - servex.ProtoLogField: HTTP protocol version
// - servex.ErrorLogField: Error information
// - servex.ErrorMessageLogField: Error message
// - servex.StatusLogField: HTTP status code
// - servex.DurationLogField: Request duration in milliseconds
//
// Use to:
// - Reduce log verbosity
// - Focus on specific metrics
// - Comply with privacy requirements
// - Optimize log storage costs
LogFields []string
// SendErrorToClient configures the server to include detailed error information
// in HTTP responses when errors occur. This includes Go error messages and stack traces.
// Set to true via WithSendErrorToClient().
//
// Security considerations:
// - NEVER enable this in production
// - Error details can reveal system information
// - Use only for development and testing
//
// When enabled, responses might include:
// - Internal error messages
// - Stack traces for panics
// - Database connection errors
// - File system errors
SendErrorToClient bool
// Auth is the JWT-based authentication configuration with user management, roles, and JWT tokens.
// Set via WithAuth(), WithAuthMemoryDatabase(), or WithAuthConfig().
//
// When configured, this automatically registers these endpoints:
// - POST /api/v1/auth/register - User registration
// - POST /api/v1/auth/login - User login
// - POST /api/v1/auth/refresh - Token refresh
// - POST /api/v1/auth/logout - User logout
// - GET /api/v1/auth/me - Current user info
//
// Use for:
// - Multi-user applications
// - Role-based access control
// - Persistent user data
// - Production authentication systems
Auth AuthConfig
// RateLimit is the rate limiting configuration to control request frequency per client.
// Set via WithRateLimitConfig(), WithRPS(), WithRPM(), or other rate limiting options.
//
// If RequestsPerInterval is not set, rate limiting will be disabled.
//
// Common configurations:
// - Public APIs: 60-1000 RPM
// - Internal APIs: 1000-10000 RPM
// - File uploads: 10-100 RPM
// - Authentication: 10-60 RPM
RateLimit RateLimitConfig
// Filter is the request filtering configuration for IP addresses, User-Agents, headers, and query parameters.
// Set via WithFilterConfig() or individual filter options like WithAllowedIPs(), WithBlockedUserAgents(), etc.
//
// Use for:
// - IP whitelisting/blacklisting
// - Bot protection
// - Geographic restrictions
// - Header-based filtering
// - Query parameter validation
Filter FilterConfig
// Security is the security headers configuration for web application protection.
// Set via WithSecurityConfig(), WithSecurityHeaders(), WithStrictSecurityHeaders(), or individual header options.
//
// Common headers include:
// - Content-Security-Policy
// - X-Frame-Options
// - X-Content-Type-Options
// - Strict-Transport-Security
// - X-XSS-Protection
//
// Use for:
// - XSS protection
// - Clickjacking prevention
// - MIME type sniffing protection
// - HTTPS enforcement
Security SecurityConfig
// CustomHeaders are custom HTTP headers that will be added to all responses.
// These headers are applied after security headers and can override them.
// Set via WithCustomHeaders().
//
// Use for:
// - API versioning headers
// - Service identification
// - Custom caching policies
// - CORS configuration
// - Application-specific headers
CustomHeaders map[string]string
// AuditLogger is the security audit logger for logging security events.
// Set via WithAuditLogger() or WithDefaultAuditLogger().
//
// Use for:
// - Security event logging and monitoring
// - Compliance requirements (SOX, GDPR, HIPAA)
// - Threat detection and analysis
// - Forensic investigation
// - Regulatory audit trails
AuditLogger AuditLogger
// EnableDefaultAuditLogger indicates that default audit logging was requested
// even if the logger wasn't available when WithDefaultAuditLogger() was called
EnableDefaultAuditLogger bool
// HeadersToRemove specifies headers to remove from responses.
// This is useful for removing server identification headers or other unwanted headers.
// Set via WithRemoveHeaders().
//
// Common headers to remove:
// - "Server": Web server software identification
// - "X-Powered-By": Technology stack identification
// - "X-AspNet-Version": ASP.NET version (if proxying)
//
// Use for:
// - Security through obscurity
// - Reduce information disclosure
// - Clean up response headers
HeadersToRemove []string
// Cache is the cache control configuration for HTTP caching headers.
// Set via WithCacheConfig(), WithCacheControl(), or other cache-related options.
//
// Controls browser and proxy caching behavior through standard HTTP headers:
// - Cache-Control: Main caching directive
// - Expires: Absolute expiration time
// - ETag: Entity tag for cache validation
// - Last-Modified: Resource modification time
// - Vary: Headers that affect caching
//
// Use for:
// - Performance optimization
// - Reduced server load
// - Improved user experience
// - CDN optimization
Cache CacheConfig
// StaticFiles is the static file serving configuration for serving web assets and SPAs.
// Set via WithStaticFiles(), WithSPAMode(), or WithStaticFileConfig().
//
// Use for:
// - Serving React/Vue/Angular apps
// - Static asset serving (CSS, JS, images)
// - Single Page Application (SPA) routing
// - Progressive Web App (PWA) support
//
// Common use cases:
// - React app with API routes: Serve build/ folder with API at /api/*
// - Documentation site: Serve docs/ folder
// - Static website: Serve public/ folder
// - Mixed SPA + API: Client routing with server API endpoints
StaticFiles StaticFileConfig
// MaxRequestBodySize is the maximum allowed request body size in bytes.
// This applies to all request bodies including JSON, form data, and file uploads.
// Set via WithMaxRequestBodySize().
//
// Default values if not set:
// - 32 MB for general request bodies
// - Use 0 to disable global request size limits
//
// Common configurations:
// - API servers: 1-10 MB
// - Web applications: 10-50 MB
// - File upload services: 100 MB - 1 GB
// - Microservices: 1-5 MB
//
// This is a global limit applied via middleware. Individual endpoints
// can use smaller limits via context methods like ReadJSONWithLimit().
MaxRequestBodySize int64
// MaxJSONBodySize is the maximum allowed JSON request body size in bytes.
// This specifically applies to JSON payloads and takes precedence over MaxRequestBodySize for JSON.
// Set via WithMaxJSONBodySize().
//
// Default: 1 MB if not set
//
// Recommended values:
// - API servers: 1-5 MB
// - Configuration APIs: 100 KB - 1 MB
// - Data import APIs: 5-50 MB
// - Real-time APIs: 100 KB - 1 MB
//
// Smaller JSON limits help prevent JSON parsing attacks and reduce memory usage.
MaxJSONBodySize int64
// MaxFileUploadSize is the maximum allowed file upload size in bytes.
// This applies to multipart form uploads and file uploads.
// Set via WithMaxFileUploadSize().
//
// Default: 100 MB if not set
//
// Common configurations:
// - Profile images: 5-10 MB
// - Document uploads: 50-200 MB
// - Media files: 500 MB - 2 GB
// - Data imports: 100 MB - 1 GB
//
// Consider your server's available memory and disk space when setting this limit.
MaxFileUploadSize int64
// MaxMultipartMemory is the maximum memory used for multipart form parsing in bytes.
// Files larger than this are stored in temporary files on disk.
// Set via WithMaxMultipartMemory().
//
// Default: 10 MB if not set
//
// Balance considerations:
// - Higher values: Faster processing, more memory usage
// - Lower values: Slower processing, less memory usage, more disk I/O
//
// Recommended: 10-50 MB for most applications
MaxMultipartMemory int64
// EnableRequestSizeLimits enables global request size limit middleware.
// When enabled, all requests are checked against the configured size limits.
// Set via WithEnableRequestSizeLimits() or WithRequestSizeLimits().
//
// When disabled, only individual endpoint size limits (via context methods) are enforced.
//
// Use cases for disabling:
// - Fine-grained control per endpoint
// - Custom size limit middleware
// - Performance-critical applications
// - Legacy compatibility
EnableRequestSizeLimits bool
// EnableHealthEndpoint enables an automatic health check endpoint that returns server status.
// This creates a simple endpoint that responds with "OK" and HTTP 200 status.
// Set to true via WithHealthEndpoint().
//
// The health endpoint:
// - Returns 200 OK with "OK" body when server is running
// - Bypasses authentication and filtering
// - Suitable for load balancer health checks
// - Kubernetes liveness/readiness probes
EnableHealthEndpoint bool
// HealthPath is the path for the health check endpoint.
// Only used when EnableHealthEndpoint is true. Set via WithHealthPath().
//
// Common health check paths:
// - "/health" (default)
// - "/ping"
// - "/status"
// - "/healthz" (Kubernetes style)
//
// Default: "/health" if EnableHealthEndpoint is true and this is empty.
HealthPath string
// Metrics is a custom metrics collector that will be called on each HTTP request.
// The metrics handler receives the http.Request for each incoming request.
// Set via WithMetrics().
//
// Use for:
// - Prometheus metrics collection
// - Custom analytics
// - Request counting and monitoring
// - Performance tracking
Metrics Metrics
// MetricsPath is the path for the default metrics endpoint.
// Only used when EnableDefaultMetrics is true. Set via WithDefaultMetrics().
//
// Common metrics paths:
// - "/metrics" (default, Prometheus style)
// - "/stats"
// - "/status/metrics"
// - "/monitoring/metrics"
//
// Default: "/metrics" if EnableDefaultMetrics is true and this is empty.
MetricsPath string
// EnableDefaultMetrics enables the default metrics endpoint.
EnableDefaultMetrics bool
// HTTPSRedirect is the HTTPS redirection configuration.
// When true, all HTTP requests will be automatically redirected to HTTPS.
HTTPSRedirect HTTPSRedirectConfig
// CORS is the Cross-Origin Resource Sharing configuration for handling cross-origin requests.
// Set via WithCORS(), WithCORSAllowOrigins(), or WithCORSConfig().
//
// CORS enables web applications running at one domain to access resources from another domain.
// This is essential for modern web applications, SPAs, and APIs that serve different frontends.
//
// Use for:
// - API servers serving web applications
// - Microservices accessed by different frontends
// - Public APIs accessed by third-party applications
// - Development servers with frontend/backend separation
CORS CORSConfig
// Proxy is the reverse proxy configuration
Proxy ProxyConfiguration
// Compression is the HTTP response compression configuration.
// Set via WithCompression(), WithCompressionConfig(), or other compression options.
//
// Controls automatic compression of HTTP response bodies using gzip or deflate encoding.
// Compression reduces bandwidth usage and improves performance for text-based content.
//
// Use for:
// - API responses (JSON, XML)
// - Static assets (CSS, JS, HTML)
// - Large text responses
// - Bandwidth optimization
Compression CompressionConfig
}
Options represents the configuration for a server.
type ProxyConfiguration ¶
type ProxyConfiguration struct {
// Enabled indicates if the proxy is enabled
Enabled bool `yaml:"enabled" json:"enabled"`
// Rules defines the routing rules
Rules []ProxyRule `yaml:"rules" json:"rules"`
// GlobalTimeout for all proxy requests
GlobalTimeout time.Duration `yaml:"global_timeout" json:"global_timeout"`
// MaxIdleConns for connection pooling
MaxIdleConns int `yaml:"max_idle_conns" json:"max_idle_conns"`
// MaxIdleConnsPerHost for connection pooling
MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host" json:"max_idle_conns_per_host"`
// IdleConnTimeout for connection pooling
IdleConnTimeout time.Duration `yaml:"idle_conn_timeout" json:"idle_conn_timeout"`
// TrafficDump configuration
TrafficDump TrafficDumpConfig `yaml:"traffic_dump" json:"traffic_dump"`
// HealthCheck configuration
HealthCheck HealthCheckConfig `yaml:"health_check" json:"health_check"`
// InsecureSkipVerify skips certificate verification
InsecureSkipVerify bool `yaml:"insecure_skip_verify" json:"insecure_skip_verify"`
}
ProxyConfiguration represents the complete proxy configuration
type ProxyRule ¶
type ProxyRule struct {
// Name is a unique identifier for the rule
Name string `yaml:"name" json:"name"`
// PathPrefix matches request paths starting with this prefix
PathPrefix string `yaml:"path_prefix" json:"path_prefix"`
// PathRegex matches request paths using regex (alternative to PathPrefix)
PathRegex string `yaml:"path_regex" json:"path_regex"`
// Host matches request Host header
Host string `yaml:"host" json:"host"`
// Headers matches specific request headers
Headers map[string]string `yaml:"headers" json:"headers"`
// Methods restricts rule to specific HTTP methods
Methods []string `yaml:"methods" json:"methods"`
// Backends defines the backend servers for this rule
Backends []Backend `yaml:"backends" json:"backends"`
// LoadBalancing strategy for this rule
LoadBalancing LoadBalancingStrategy `yaml:"load_balancing" json:"load_balancing"`
// StripPrefix removes prefix from path before forwarding
StripPrefix string `yaml:"strip_prefix" json:"strip_prefix"`
// AddPrefix adds prefix to path before forwarding
AddPrefix string `yaml:"add_prefix" json:"add_prefix"`
// Timeout for backend requests
Timeout time.Duration `yaml:"timeout" json:"timeout"`
// EnableTrafficDump enables traffic dumping for this rule
EnableTrafficDump bool `yaml:"enable_traffic_dump" json:"enable_traffic_dump"`
// DumpDirectory specifies where to dump traffic (uses global if empty)
DumpDirectory string `yaml:"dump_directory" json:"dump_directory"`
// contains filtered or unexported fields
}
ProxyRule represents a routing rule for the proxy
type RateLimitConfig ¶
type RateLimitConfig struct {
// Enabled indicates whether rate limiting is enabled.
Enabled bool
// RequestsPerInterval is the number of requests allowed per time interval.
// Set via WithRPM(), WithRPS(), or WithRequestsPerInterval().
// If not set or zero, rate limiting will be disabled.
//
// Common values:
// - Public APIs: 60-1000 per minute
// - Internal APIs: 1000-10000 per minute
// - File uploads: 10-100 per minute
// - Authentication: 10-60 per minute
//
// The rate limiter uses a token bucket algorithm, refilling tokens at a constant rate.
RequestsPerInterval int
// Interval is the time window for the rate limit.
// Set via WithRPM() (1 minute), WithRPS() (1 second), or WithRequestsPerInterval().
// If not set, defaults to 1 minute.
//
// Common intervals:
// - time.Second: For high-frequency APIs
// - time.Minute: Most common, good balance
// - time.Hour: For very restrictive limits
// - 5*time.Minute: Custom business requirements
//
// Shorter intervals provide more responsive limiting but require more memory.
Interval time.Duration
// BurstSize is the maximum number of requests that can be made immediately.
// This allows clients to exceed the normal rate limit temporarily by "bursting".
// Set via WithBurstSize(). If not set, defaults to RequestsPerInterval.
//
// How it works:
// - Clients can make up to BurstSize requests immediately
// - After bursting, they must wait for tokens to refill
// - Tokens refill at the configured rate (RequestsPerInterval/Interval)
//
// Use cases:
// - Handle traffic spikes gracefully
// - Allow batch operations
// - Improve user experience for bursty clients
// - Balance performance with protection
BurstSize int
// StatusCode is the HTTP status code returned when rate limit is exceeded.
// Set via WithRateLimitStatusCode(). Defaults to 429 (Too Many Requests) if not set.
//
// Common status codes:
// - 429 Too Many Requests (recommended)
// - 503 Service Unavailable
// - 502 Bad Gateway (for proxy scenarios)
//
// The 429 status code is specifically designed for rate limiting and is
// understood by most HTTP clients and libraries.
StatusCode int
// Message is the response body returned when rate limit is exceeded.
// Set via WithRateLimitMessage(). Defaults to "rate limit exceeded, try again later." if not set.
//
// Best practices:
// - Be clear about the limit
// - Suggest when to retry
// - Keep messages user-friendly
// - Include contact information for questions
//
// The message is returned as plain text in the response body.
Message string
// KeyFunc is a custom function to extract the rate limit key from requests.
// This determines how clients are identified for rate limiting purposes.
// Set via WithRateLimitKeyFunc().
//
// Default behavior uses client IP address. Custom key functions enable:
// - User-based rate limiting (requires authentication)
// - API key-based limits
// - Different limits for different client types
// - Combined identification strategies
//
// Example functions:
// - IP-based: func(r *http.Request) string { return r.RemoteAddr }
// - User-based: func(r *http.Request) string { return getUserID(r) }
// - API key-based: func(r *http.Request) string { return r.Header.Get("X-API-Key") }
KeyFunc func(r *http.Request) string
// ExcludePaths are paths that should be excluded from rate limiting.
// Requests to these paths will not be counted against rate limits.
// Set via WithRateLimitExcludePaths().
//
// Common exclusions:
// - Health checks: "/health", "/ping"
// - Metrics: "/metrics", "/stats"
// - Static files: "/static/*", "/assets/*"
// - Documentation: "/docs/*", "/swagger/*"
// - Infrastructure: "/robots.txt", "/favicon.ico"
//
// Path matching supports wildcards (*) for pattern matching.
ExcludePaths []string
// IncludePaths are paths that should be included in rate limiting.
// If set, only requests to these paths will be rate limited. All other paths are excluded.
// Set via WithRateLimitIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to be rate limited
// 2. Paths in ExcludePaths are then excluded from rate limiting
//
// Use cases:
// - Protect only sensitive endpoints
// - Apply different limits to different API versions
// - Rate limit only external-facing endpoints
// - Granular control over protection
IncludePaths []string
// TrustedProxies is a list of trusted proxy IP addresses or CIDR ranges
// for accurate client IP detection in rate limiting.
// Set via WithRateLimitTrustedProxies().
//
// How it works:
// - Without trusted proxies: Uses r.RemoteAddr (proxy IP)
// - With trusted proxies: Uses X-Forwarded-For or X-Real-IP headers
//
// Common proxy ranges:
// - AWS ALB: Check AWS documentation for current ranges
// - Cloudflare: Use Cloudflare's published IP ranges
// - Internal load balancers: Your internal network ranges
// - Docker networks: 172.16.0.0/12, 10.0.0.0/8
//
// Security note: Only list IPs you actually trust. Malicious clients
// can spoof X-Forwarded-For headers if the proxy IP is trusted.
TrustedProxies []string
}
RateLimitConfig holds configuration for the rate limiter middleware. This controls request frequency per client using a token bucket algorithm.
Rate limiting helps protect your server from:
- DDoS attacks
- Brute force attempts
- Resource exhaustion
- Abusive clients
Example configurations:
// API server: 100 requests per minute with burst of 20
rateLimit := RateLimitConfig{
RequestsPerInterval: 100,
Interval: time.Minute,
BurstSize: 20,
StatusCode: 429,
Message: "Rate limit exceeded. Try again later.",
}
// High-security: 10 requests per second, no burst
rateLimit := RateLimitConfig{
RequestsPerInterval: 10,
Interval: time.Second,
BurstSize: 1,
}
type RateLimitConfiguration ¶
type RateLimitConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_RATE_LIMIT_ENABLED"`
RequestsPerInterval int `yaml:"requests_per_interval" json:"requests_per_interval" env:"SERVEX_RATE_LIMIT_REQUESTS_PER_INTERVAL"`
Interval time.Duration `yaml:"interval" json:"interval" env:"SERVEX_RATE_LIMIT_INTERVAL"`
BurstSize int `yaml:"burst_size" json:"burst_size" env:"SERVEX_RATE_LIMIT_BURST_SIZE"`
StatusCode int `yaml:"status_code" json:"status_code" env:"SERVEX_RATE_LIMIT_STATUS_CODE"`
Message string `yaml:"message" json:"message" env:"SERVEX_RATE_LIMIT_MESSAGE"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_RATE_LIMIT_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_RATE_LIMIT_INCLUDE_PATHS"`
TrustedProxies []string `yaml:"trusted_proxies" json:"trusted_proxies" env:"SERVEX_RATE_LIMIT_TRUSTED_PROXIES"`
}
RateLimitConfiguration represents rate limiting configuration
type RequestLogBundle ¶
type RequestLogBundle struct {
Request *http.Request
RequestID string
Error error
ErrorMessage string
StatusCode int
StartTime time.Time
NoLogClientErrors bool
}
RequestLogBundle represents a bundle of information for logging a request.
type RequestLogger ¶
type RequestLogger interface {
Log(RequestLogBundle)
}
RequestLogger is an interface for logging requests. [RequestLogger.Log] is called at the end of each request after returning from handler.
type RoleContextKey ¶
type RoleContextKey struct{}
type SecurityConfig ¶
type SecurityConfig struct {
// Enabled determines whether security headers middleware is active.
// Must be set to true for any security headers to be applied.
// Set via WithSecurityHeaders(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// When disabled, no security headers will be added to responses,
// even if individual header values are configured.
Enabled bool
// CSRFEnabled determines whether CSRF protection is active.
// When enabled, CSRF tokens are required for POST, PUT, PATCH, DELETE requests.
// Set via WithCSRFProtection(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// CSRF protection works by:
// 1. Generating a secure random token for each session
// 2. Setting the token in a cookie and/or providing it via an endpoint
// 3. Requiring the token in a header or form field for state-changing requests
// 4. Validating that the token matches the expected value
//
// Use cases:
// - Web applications with forms and AJAX requests
// - APIs that accept requests from browsers
// - Any application vulnerable to CSRF attacks
CSRFEnabled bool
// CSRFTokenName is the name of the CSRF token in headers and form fields.
// Set via WithCSRFTokenName() or WithSecurityConfig().
//
// Common names:
// - "X-CSRF-Token" (default, Rails/Django style)
// - "X-XSRF-TOKEN" (Angular style)
// - "csrf_token" (for form fields)
// - "_token" (Laravel style)
//
// The middleware will look for the token in:
// 1. Request header with this name
// 2. Form field with this name (for multipart/form-data and application/x-www-form-urlencoded)
// 3. URL query parameter with this name (as fallback)
CSRFTokenName string
// CSRFCookieName is the name of the cookie that stores the CSRF token.
// Set via WithCSRFCookieName() or WithSecurityConfig().
//
// Common names:
// - "csrf_token" (default)
// - "XSRF-TOKEN" (Angular style, readable by JavaScript)
// - "_csrf" (Express.js style)
//
// The cookie is used to store the expected CSRF token value.
// For maximum security, set CSRFCookieHttpOnly to true.
CSRFCookieName string
// CSRFCookieHttpOnly determines if the CSRF cookie is HTTP-only.
// Set via WithCSRFCookieHttpOnly() or WithSecurityConfig().
//
// Security trade-offs:
// - true (recommended): More secure, prevents XSS token theft, but requires server-side token injection
// - false: Allows JavaScript access, enables SPA token retrieval, but vulnerable to XSS
//
// When true:
// - Use CSRFTokenEndpoint to provide tokens to JavaScript
// - Inject tokens into HTML templates server-side
//
// When false:
// - JavaScript can read document.cookie to get the token
// - Useful for SPAs and AJAX-heavy applications
CSRFCookieHttpOnly bool
// CSRFCookieSameSite sets the SameSite attribute for the CSRF cookie.
// Set via WithCSRFCookieSameSite() or WithSecurityConfig().
//
// Options:
// - "Strict": Maximum protection, may break some legitimate cross-site usage
// - "Lax" (recommended): Good protection with better usability
// - "None": Least protection, requires Secure=true, allows cross-site requests
//
// "Lax" provides good CSRF protection while maintaining usability.
CSRFCookieSameSite string
// CSRFCookieSecure determines if the CSRF cookie requires HTTPS.
// Set via WithCSRFCookieSecure() or WithSecurityConfig().
//
// Recommendations:
// - true: Required for production HTTPS sites
// - false: Only for development with HTTP
//
// Automatically set to true when SameSite=None.
CSRFCookieSecure bool
// CSRFCookiePath sets the path attribute for the CSRF cookie.
// Set via WithCSRFCookiePath() or WithSecurityConfig().
//
// Common values:
// - "/" (default): Cookie available for entire site
// - "/app": Cookie only for application section
// - "/api": Cookie only for API endpoints
//
// Use specific paths to limit cookie scope and improve security.
CSRFCookiePath string
// CSRFCookieMaxAge sets the maximum age for the CSRF cookie in seconds.
// Set via WithCSRFCookieMaxAge() or WithSecurityConfig().
//
// Common values:
// - 3600: 1 hour (short-lived, more secure)
// - 86400: 1 day (balance of security and usability)
// - 604800: 1 week (longer sessions)
// - 0: Session cookie (expires when browser closes)
//
// Shorter durations improve security but may affect user experience.
CSRFCookieMaxAge int
// CSRFTokenEndpoint enables an endpoint to retrieve CSRF tokens via AJAX.
// Set via WithCSRFTokenEndpoint() or WithSecurityConfig().
//
// When set, creates an endpoint (e.g., "/csrf-token") that returns:
// {"csrf_token": "abc123..."}
//
// Use cases:
// - SPAs that need to fetch tokens dynamically
// - AJAX applications with HttpOnly cookies
// - Mobile apps that need CSRF tokens
//
// The endpoint:
// - Uses GET method
// - Returns JSON with the token
// - Sets the CSRF cookie
// - Bypasses CSRF validation (safe since it's read-only)
CSRFTokenEndpoint string
// CSRFErrorMessage is the message returned when CSRF validation fails.
// Set via WithCSRFErrorMessage() or WithSecurityConfig().
//
// Default: "CSRF token validation failed"
//
// Best practices:
// - Keep messages generic to avoid information disclosure
// - Include guidance for legitimate users
// - Consider localization for international applications
CSRFErrorMessage string
// CSRFSafeMethods lists HTTP methods that bypass CSRF validation.
// Set via WithCSRFSafeMethods() or WithSecurityConfig().
//
// Default: [GET, "HEAD", OPTIONS, "TRACE"]
//
// These methods are considered safe because they shouldn't have side effects.
// POST, PUT, PATCH, DELETE require CSRF tokens by default.
//
// Only modify this if you have specific requirements.
CSRFSafeMethods []string
// ContentSecurityPolicy sets the Content-Security-Policy header for XSS protection.
// This header controls which resources the browser is allowed to load.
// Set via WithContentSecurityPolicy() or WithStrictSecurityHeaders().
//
// Common policies:
// - Basic: "default-src 'self'"
// - With inline scripts: "default-src 'self'; script-src 'self' 'unsafe-inline'"
// - Strict: "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'"
// - API-only: "default-src 'none'; frame-ancestors 'none'"
//
// Use CSP generators or testing tools to create appropriate policies.
// Start with a restrictive policy and gradually add exceptions as needed.
ContentSecurityPolicy string
// XContentTypeOptions sets the X-Content-Type-Options header to prevent MIME sniffing.
// This prevents browsers from interpreting files differently than declared by Content-Type.
// Set via WithSecurityHeaders(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// Standard value: "nosniff"
//
// Benefits:
// - Prevents MIME confusion attacks
// - Ensures Content-Type headers are respected
// - Reduces risk of drive-by downloads
// - Essential for file upload applications
XContentTypeOptions string
// XFrameOptions sets the X-Frame-Options header to prevent clickjacking attacks.
// This controls whether the page can be displayed in frames/iframes.
// Set via WithSecurityHeaders(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// Options:
// - "DENY": Page cannot be framed at all
// - "SAMEORIGIN": Page can only be framed by same origin
// - "ALLOW-FROM uri": Page can only be framed by specified URI
//
// Use "DENY" for maximum security unless you specifically need framing.
XFrameOptions string
// XXSSProtection sets the X-XSS-Protection header for legacy XSS protection.
// Modern browsers rely more on CSP, but this provides additional protection.
// Set via WithSecurityHeaders(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// Common values:
// - "1": Enable XSS filtering (basic)
// - "1; mode=block": Enable XSS filtering and block rather than sanitize
// - "0": Disable XSS filtering (not recommended)
//
// Note: This header is deprecated in favor of CSP but still useful for older browsers.
XXSSProtection string
// StrictTransportSecurity sets the HSTS header to enforce HTTPS usage.
// This tells browsers to only access the site over HTTPS for a specified time.
// Set via WithHSTSHeader(), WithStrictSecurityHeaders(), or WithSecurityConfig().
//
// Format: "max-age=<seconds>; includeSubDomains; preload"
//
// Common configurations:
// - Basic: "max-age=31536000" (1 year)
// - With subdomains: "max-age=31536000; includeSubDomains"
// - Maximum security: "max-age=63072000; includeSubDomains; preload" (2 years)
//
// Only set this if your site fully supports HTTPS and you're ready to commit to it.
StrictTransportSecurity string
// ReferrerPolicy sets the Referrer-Policy header to control referrer information.
// This controls how much referrer information is sent with requests.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Options:
// - "no-referrer": Never send referrer information
// - "same-origin": Send referrer only for same-origin requests
// - "strict-origin": Send origin only, and only for HTTPS-to-HTTPS
// - "strict-origin-when-cross-origin": Full URL for same-origin, origin only for cross-origin
// - "unsafe-url": Always send full URL (not recommended)
//
// Balance privacy protection with functionality needs.
ReferrerPolicy string
// PermissionsPolicy sets the Permissions-Policy header to control browser features.
// This restricts access to browser APIs and features for enhanced privacy/security.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Format: "feature=(allowlist)"
//
// Examples:
// - Block all: "geolocation=(), microphone=(), camera=(), payment=(), usb=()"
// - Self only: "geolocation=(self), microphone=(self), camera=(self)"
// - Specific origins: "geolocation=(\"https://maps.example.com\")"
//
// Common features: geolocation, microphone, camera, payment, usb, magnetometer, gyroscope
PermissionsPolicy string
// XPermittedCrossDomainPolicies sets the X-Permitted-Cross-Domain-Policies header.
// This controls cross-domain access for Flash and PDF files.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Options:
// - "none": No cross-domain access allowed (recommended)
// - "master-only": Only master policy file is allowed
// - "by-content-type": Policy files served with appropriate content type
// - "all": All policy files allowed (not recommended)
//
// Use "none" unless you specifically need cross-domain Flash/PDF functionality.
XPermittedCrossDomainPolicies string
// CrossOriginEmbedderPolicy sets the Cross-Origin-Embedder-Policy header.
// This header allows a document to control which cross-origin resources can be embedded.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Options:
// - "require-corp": Embedded resources must explicitly opt-in to being embedded
// - "unsafe-none": No restrictions (default behavior)
//
// Use "require-corp" for applications that need to isolate their context
// from potentially malicious cross-origin resources.
CrossOriginEmbedderPolicy string
// CrossOriginOpenerPolicy sets the Cross-Origin-Opener-Policy header.
// This header controls the opener relationship for windows opened via links.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Options:
// - "same-origin": Retain opener only for same-origin navigation
// - "same-origin-allow-popups": Like same-origin but allows popups
// - "unsafe-none": No restrictions (default)
//
// Use "same-origin" to prevent cross-origin pages from accessing your window object.
CrossOriginOpenerPolicy string
// CrossOriginResourcePolicy sets the Cross-Origin-Resource-Policy header.
// This header controls which cross-origin requests can include this resource.
// Set via WithStrictSecurityHeaders() or WithSecurityConfig().
//
// Options:
// - "same-site": Resource can be loaded by same-site requests only
// - "same-origin": Resource can be loaded by same-origin requests only
// - "cross-origin": Resource can be loaded by any origin
//
// Use "same-site" or "same-origin" for sensitive resources that shouldn't
// be embeddable by other origins.
CrossOriginResourcePolicy string
// ExcludePaths are paths that should be excluded from security headers.
// Requests to these paths will not have security headers applied.
// Set via WithSecurityExcludePaths().
//
// Common exclusions:
// - API endpoints that need different policies: "/api/*"
// - Legacy applications: "/legacy/*"
// - Third-party integrations: "/webhooks/*"
// - Public assets that need embedding: "/public/*"
// - Development tools: "/debug/*"
//
// Path matching supports wildcards (*) for pattern matching.
ExcludePaths []string
// IncludePaths are paths that should have security headers applied.
// If set, only requests to these paths will receive security headers.
// Set via WithSecurityIncludePaths().
//
// If both IncludePaths and ExcludePaths are set:
// 1. Paths must match IncludePaths to receive security headers
// 2. Paths in ExcludePaths are then excluded from security headers
//
// Use cases:
// - Apply security headers only to web UI: "/app/*", "/dashboard/*"
// - Secure only public-facing endpoints: "/public/*"
// - Protect specific application sections: "/admin/*", "/user/*"
//
// Path matching supports wildcards (*) for pattern matching.
IncludePaths []string
}
SecurityConfig holds configuration for security headers middleware. SecurityConfig holds configuration for security headers middleware. These headers protect web applications from common security vulnerabilities.
Security headers help prevent:
- Cross-site scripting (XSS) attacks
- Clickjacking attacks
- MIME type sniffing vulnerabilities
- Cross-origin policy violations
- Content injection attacks
Example configuration:
security := SecurityConfig{
Enabled: true,
ContentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'",
XFrameOptions: "DENY",
XContentTypeOptions: "nosniff",
StrictTransportSecurity: "max-age=31536000; includeSubDomains",
}
Use WithStrictSecurityHeaders() for a preset of maximum security headers.
type SecurityConfiguration ¶
type SecurityConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_SECURITY_ENABLED"`
// CSRF Protection Configuration
CSRFEnabled bool `yaml:"csrf_enabled" json:"csrf_enabled" env:"SERVEX_SECURITY_CSRF_ENABLED"`
CSRFTokenName string `yaml:"csrf_token_name" json:"csrf_token_name" env:"SERVEX_SECURITY_CSRF_TOKEN_NAME"`
CSRFCookieName string `yaml:"csrf_cookie_name" json:"csrf_cookie_name" env:"SERVEX_SECURITY_CSRF_COOKIE_NAME"`
CSRFCookieHttpOnly bool `yaml:"csrf_cookie_http_only" json:"csrf_cookie_http_only" env:"SERVEX_SECURITY_CSRF_COOKIE_HTTP_ONLY"`
CSRFCookieSameSite string `yaml:"csrf_cookie_same_site" json:"csrf_cookie_same_site" env:"SERVEX_SECURITY_CSRF_COOKIE_SAME_SITE"`
CSRFCookieSecure bool `yaml:"csrf_cookie_secure" json:"csrf_cookie_secure" env:"SERVEX_SECURITY_CSRF_COOKIE_SECURE"`
CSRFCookiePath string `yaml:"csrf_cookie_path" json:"csrf_cookie_path" env:"SERVEX_SECURITY_CSRF_COOKIE_PATH"`
CSRFCookieMaxAge int `yaml:"csrf_cookie_max_age" json:"csrf_cookie_max_age" env:"SERVEX_SECURITY_CSRF_COOKIE_MAX_AGE"`
CSRFTokenEndpoint string `yaml:"csrf_token_endpoint" json:"csrf_token_endpoint" env:"SERVEX_SECURITY_CSRF_TOKEN_ENDPOINT"`
CSRFErrorMessage string `yaml:"csrf_error_message" json:"csrf_error_message" env:"SERVEX_SECURITY_CSRF_ERROR_MESSAGE"`
CSRFSafeMethods []string `yaml:"csrf_safe_methods" json:"csrf_safe_methods" env:"SERVEX_SECURITY_CSRF_SAFE_METHODS"`
// Security Headers Configuration
ContentSecurityPolicy string `yaml:"content_security_policy" json:"content_security_policy" env:"SERVEX_SECURITY_CONTENT_SECURITY_POLICY"`
XContentTypeOptions string `yaml:"x_content_type_options" json:"x_content_type_options" env:"SERVEX_SECURITY_X_CONTENT_TYPE_OPTIONS"`
XFrameOptions string `yaml:"x_frame_options" json:"x_frame_options" env:"SERVEX_SECURITY_X_FRAME_OPTIONS"`
XXSSProtection string `yaml:"x_xss_protection" json:"x_xss_protection" env:"SERVEX_SECURITY_X_XSS_PROTECTION"`
StrictTransportSecurity string `yaml:"strict_transport_security" json:"strict_transport_security" env:"SERVEX_SECURITY_STRICT_TRANSPORT_SECURITY"`
ReferrerPolicy string `yaml:"referrer_policy" json:"referrer_policy" env:"SERVEX_SECURITY_REFERRER_POLICY"`
PermissionsPolicy string `yaml:"permissions_policy" json:"permissions_policy" env:"SERVEX_SECURITY_PERMISSIONS_POLICY"`
XPermittedCrossDomainPolicies string `` /* 137-byte string literal not displayed */
CrossOriginEmbedderPolicy string `yaml:"cross_origin_embedder_policy" json:"cross_origin_embedder_policy" env:"SERVEX_SECURITY_CROSS_ORIGIN_EMBEDDER_POLICY"`
CrossOriginOpenerPolicy string `yaml:"cross_origin_opener_policy" json:"cross_origin_opener_policy" env:"SERVEX_SECURITY_CROSS_ORIGIN_OPENER_POLICY"`
CrossOriginResourcePolicy string `yaml:"cross_origin_resource_policy" json:"cross_origin_resource_policy" env:"SERVEX_SECURITY_CROSS_ORIGIN_RESOURCE_POLICY"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_SECURITY_EXCLUDE_PATHS"`
IncludePaths []string `yaml:"include_paths" json:"include_paths" env:"SERVEX_SECURITY_INCLUDE_PATHS"`
}
SecurityConfiguration represents security headers configuration
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server represents a high-performance HTTP/HTTPS server with built-in middleware support.
The Server provides comprehensive features including:
- Authentication and authorization with JWT tokens
- Rate limiting with multiple strategies
- Request filtering (IP, User-Agent, headers, query params)
- Security headers and CSRF protection
- Static file serving with SPA support
- Proxy/gateway functionality with load balancing
- Request logging and metrics collection
- Cache control headers
- Graceful shutdown support
Server instances are created using New() or NewWithOptions() and configured through the Options pattern using With* functions.
Example usage:
server, err := servex.New(
servex.WithAuthToken("secret-token"),
servex.WithRateLimitRPM(60),
servex.WithSecurityHeaders(),
)
if err != nil {
log.Fatal(err)
}
server.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
servex.C(w, r).Response(200, map[string]string{"message": "Hello, World!"})
})
log.Fatal(server.Start(":8080", ""))
func NewServer ¶
NewServer creates a new Server instance with the specified options.
The server is configured using the Options pattern with With* functions. A server without a TLS certificate can only serve plain HTTP traffic.
Available configuration options include:
- Authentication: WithAuth(), WithAuthToken(), WithAuthMemoryDatabase()
- Rate limiting: WithRPM(), WithRPS(), WithRateLimitConfig()
- Security: WithSecurityHeaders(), WithCSRFProtection(), WithStrictSecurityHeaders()
- Filtering: WithAllowedIPs(), WithBlockedUserAgents(), WithFilterConfig()
- Static files: WithStaticFiles(), WithSPAMode()
- Logging: WithLogger(), WithRequestLogger(), WithAuditLogger()
- TLS: WithCertificate(), WithCertificateFromFile()
- And many more...
Example:
server, err := servex.NewServer(
servex.WithAuthToken("my-secret-token"),
servex.WithRateLimitRPM(100),
servex.WithSecurityHeaders(),
servex.WithStaticFiles("./public"),
)
if err != nil {
return fmt.Errorf("create server: %w", err)
}
The server must have routes registered using the router methods (HandleFunc, GET, POST, etc.) before starting.
func NewServerFromConfig ¶
NewServerFromConfig creates a new Server instance from a Config struct
func NewServerWithOptions ¶
NewServerWithOptions creates a new Server instance with the provided Options struct.
This function is useful when you have already constructed an Options struct, either programmatically or from configuration files. For most use cases, New() with With* functions is more convenient.
The function validates the configuration and returns an error if any invalid settings are detected.
Example:
opts := servex.Options{
AuthToken: "my-secret-token",
RateLimit: servex.RateLimitConfig{
Enabled: true,
RequestsPerInterval: 100,
Interval: time.Minute,
},
Security: servex.SecurityConfig{
Enabled: true,
XContentTypeOptions: "nosniff",
},
}
server, err := servex.NewServerWithOptions(opts)
if err != nil {
return fmt.Errorf("create server: %w", err)
}
func (*Server) AddMiddlewares ¶
AddMiddlewares adds one or more mux.MiddlewareFunc to the router.
func (*Server) AddStaticFileRoutes ¶
func (s *Server) AddStaticFileRoutes(cfg StaticFileConfig) error
AddStaticFileRoutes is a convenience method to add static file serving to a router. This can be used as an alternative to middleware if you prefer explicit routing.
func (*Server) AuthManager ¶
func (s *Server) AuthManager() *AuthManager
AuthManager returns the server's authentication manager for manual auth operations.
This provides access to the underlying AuthManager for advanced authentication use cases such as:
- Creating users programmatically
- Validating tokens manually
- Custom authentication flows
- User management operations
Returns nil if authentication is not enabled (no database configured).
Example:
if authMgr := server.AuthManager(); authMgr != nil {
ctx := context.Background()
err := authMgr.CreateUser(ctx, "admin", "secure-password", "admin", "user")
if err != nil {
log.Printf("Failed to create user: %v", err)
}
}
func (*Server) C ¶
C returns a new context for the provided request. It is a shortcut for C with server options.
func (*Server) CONNECT ¶
CONNECT is an alias for Server.Connect.
func (*Server) Connect ¶
Connect registers a new CONNECT route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) ConnectWithAuth ¶
ConnectWithAuth registers a new CONNECT route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) DELETE ¶
DELETE is an alias for Server.Delete.
func (*Server) Delete ¶
Delete registers a new DELETE route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) DeleteWithAuth ¶
DeleteWithAuth registers a new DELETE route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) Filter ¶
func (s *Server) Filter() DynamicFilterMethods
Filter returns the active filter instance for dynamic modification. Returns nil if no filter is configured or enabled.
Example:
// Block an IP that accessed a honeypot
if filter := server.Filter(); filter != nil {
err := filter.AddBlockedIP("192.168.1.100")
if err != nil {
log.Printf("Failed to block IP: %v", err)
}
}
// Check if a User-Agent is blocked
if filter := server.Filter(); filter != nil {
if filter.IsUserAgentBlocked("BadBot/1.0") {
log.Println("User-Agent is blocked")
}
}
func (*Server) GET ¶
GET is an alias for Server.Get.
func (*Server) Get ¶
Get registers a new GET route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) GetWithAuth ¶
GetWithAuth registers a new GET route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) H ¶
H is a shortcut for Server.Handle.
Parameters:
- path: The path to register the route for
- h: The handler to register the route for
- methods: The methods to register the route for
Returns:
- *mux.Route: The created route to set additional settings to the route
func (*Server) HA ¶
HA is a shortcut for Server.HandleWithAuth.
func (*Server) HEAD ¶
HEAD is an alias for Server.Head.
func (*Server) HF ¶
HF is a shortcut for Server.HandleFunc.
Parameters:
- path: The path to register the route for
- f: The handler to register the route for
- methods: The methods to register the route for
Example:
server.HF("/users", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}, GET, POST)
Returns:
- *mux.Route: The created route to set additional settings to the route
func (*Server) HFA ¶
HFA is a shortcut for Server.HandleFuncWithAuth.
func (*Server) HTTPAddress ¶
HTTPAddress returns the address the HTTP server is listening on. Returns an empty string if the HTTP server is not running or not configured.
func (*Server) HTTPSAddress ¶
HTTPSAddress returns the address the HTTPS server is listening on. Returns an empty string if the HTTPS server is not running or not configured.
func (*Server) Handle ¶
Handle registers a new route with the provided path, http.Handler and methods. It returns a pointer to the created mux.Route to set additional settings to the route.
Parameters:
- path: The path to register the route for
- h: The handler to register the route for
- methods: The methods to register the route for
Returns:
- *mux.Route: The created route to set additional settings to the route
func (*Server) HandleFunc ¶
HandleFunc registers a new route with the provided path, http.HandlerFunc and methods. It returns a pointer to the created mux.Route to set additional settings to the route.
Parameters:
- path: The path to register the route for
- f: The handler to register the route for
- methods: The methods to register the route for
Example:
server.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}, GET, POST)
Returns:
- *mux.Route: The created route to set additional settings to the route
func (*Server) HandleFuncWithAuth ¶
HandleFuncWithAuth registers a new route with the provided path, http.HandlerFunc and methods. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) HandleWithAuth ¶
HandleWithAuth registers a new route with the provided path, http.Handler and methods. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) Head ¶
Head registers a new HEAD route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) HeadWithAuth ¶
HeadWithAuth registers a new HEAD route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) IsAuthEnabled ¶
IsAuthEnabled returns true if authentication is enabled on this server.
Authentication is enabled when a database is configured through WithAuth() or WithAuthMemoryDatabase() options.
func (*Server) IsHTTP ¶
IsHTTP returns true if the HTTP server is running.
This indicates that the HTTP server has been started successfully and is accepting connections.
func (*Server) IsTLS ¶
IsTLS returns true if the HTTPS server is running.
This indicates that the server has a TLS certificate configured and the HTTPS server has been started successfully.
func (*Server) NewContext ¶
NewContext returns a new context for the provided request. It is a shortcut for NewContext with server options.
func (*Server) OPTIONS ¶
OPTIONS is an alias for Server.Options.
func (*Server) Options ¶
Options registers a new OPTIONS route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) OptionsWithAuth ¶
OptionsWithAuth registers a new OPTIONS route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) PATCH ¶
PATCH is an alias for Server.Patch.
func (*Server) POST ¶
POST is an alias for Server.Post.
func (*Server) PUT ¶
PUT is an alias for Server.Put.
func (*Server) Patch ¶
Patch registers a new PATCH route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) PatchWithAuth ¶
PatchWithAuth registers a new PATCH route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) Post ¶
Post registers a new POST route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) PostWithAuth ¶
PostWithAuth registers a new POST route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) Put ¶
Put registers a new PUT route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) PutWithAuth ¶
PutWithAuth registers a new PUT route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) R ¶
R is a shortcut for Server.Router.
func (*Server) RemoveBasePath ¶ added in v2.3.0
RemoveBasePath clears the base path for the server's router. It returns the server itself to allow method chaining.
Example:
server.WithBasePath("/api")
server.Get("/users", ...) // Results in /api/users
server.RemoveBasePath()
server.Get("/health", ...) // Results in /health
Returns:
- *Server: The server itself to allow method chaining
func (*Server) Router ¶
Router returns mux.Router, it may be useful if you want to work with router manually. It accepts a path to set as a base path for the router.
func (*Server) Shutdown ¶
Shutdown gracefully shuts down both HTTP and HTTPS servers.
This method attempts to gracefully shut down all running servers by:
- Stopping acceptance of new connections
- Allowing existing connections to complete their requests
- Running all registered cleanup functions
- Returning when all operations complete or the context times out
The context controls the shutdown timeout. It's recommended to use a timeout context (e.g., 30 seconds) to prevent hanging on long-running requests.
Parameters:
- ctx: Context with timeout for the shutdown operation
Returns an error if any server fails to shut down properly. Multiple errors are joined using errors.Join().
Example:
// Graceful shutdown with 30-second timeout
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Printf("Server shutdown error: %v", err)
}
func (*Server) Start ¶
Start starts both HTTP and HTTPS servers on the specified addresses.
Parameters:
- httpAddr: Address for HTTP server (e.g., ":8080", "localhost:8080"). Empty string disables HTTP.
- httpsAddr: Address for HTTPS server (e.g., ":8443", "localhost:8443"). Empty string disables HTTPS.
At least one address must be provided. The HTTPS server requires a TLS certificate to be configured through WithCertificate() or WithCertificateFromFile() options.
This method starts the servers asynchronously and returns immediately after successful startup. Use StartWithShutdown() if you need automatic cleanup when a context is cancelled.
Example:
// Start both HTTP and HTTPS
err := server.Start(":8080", ":8443")
// Start only HTTP
err := server.Start(":8080", "")
// Start only HTTPS
err := server.Start("", ":8443")
func (*Server) StartHTTP ¶
StartHTTP starts only the HTTP server on the specified address.
This method is useful when you only need HTTP traffic or want to start HTTP and HTTPS servers separately with different timing.
Parameters:
- address: The address to bind the HTTP server to (e.g., ":8080", "localhost:8080")
The server starts asynchronously in a goroutine and this method returns immediately after successful startup. Use the returned error to check for startup failures.
Example:
if err := server.StartHTTP(":8080"); err != nil {
log.Fatalf("Failed to start HTTP server: %v", err)
}
log.Println("HTTP server started on :8080")
func (*Server) StartHTTPS ¶
StartHTTPS starts only the HTTPS server on the specified address.
This method requires a TLS certificate to be configured through WithCertificate() or WithCertificateFromFile() options.
Parameters:
- address: The address to bind the HTTPS server to (e.g., ":8443", "localhost:8443")
The server starts asynchronously in a goroutine and this method returns immediately after successful startup. The method will return an error if no TLS certificate is configured.
Example:
server, err := servex.New(
servex.WithCertificateFromFile("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
if err := server.StartHTTPS(":8443"); err != nil {
log.Fatalf("Failed to start HTTPS server: %v", err)
}
log.Println("HTTPS server started on :8443")
func (*Server) StartWithShutdown ¶
StartWithShutdown starts HTTP and HTTPS servers with automatic graceful shutdown.
This method starts the servers and monitors the provided context. When the context is cancelled or times out, it automatically initiates a graceful shutdown with a 30-second timeout.
Parameters:
- ctx: Context for controlling server lifecycle. When cancelled, triggers shutdown.
- httpAddr: Address for HTTP server (empty string disables HTTP)
- httpsAddr: Address for HTTPS server (empty string disables HTTPS)
This is the recommended way to start servers in production as it handles cleanup automatically and supports graceful shutdown for zero-downtime deployments.
Example:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Start server with automatic shutdown
err := server.StartWithShutdown(ctx, ":8080", ":8443")
if err != nil {
log.Fatalf("Server failed: %v", err)
}
// Server will shutdown gracefully when ctx is cancelled
// or when the program receives a signal
func (*Server) StartWithShutdownHTTP ¶
StartWithShutdownHTTP starts only the HTTP server with automatic graceful shutdown.
This is a convenience method that starts only the HTTP server and automatically shuts it down when the context is cancelled. Equivalent to calling StartWithShutdown(ctx, address, "").
Parameters:
- ctx: Context for controlling server lifecycle
- address: Address for the HTTP server (e.g., ":8080")
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := server.StartWithShutdownHTTP(ctx, ":8080")
func (*Server) StartWithShutdownHTTPS ¶
StartWithShutdownHTTPS starts only the HTTPS server with automatic graceful shutdown.
This is a convenience method that starts only the HTTPS server and automatically shuts it down when the context is cancelled. Equivalent to calling StartWithShutdown(ctx, "", address).
Requires a TLS certificate to be configured through WithCertificate() or WithCertificateFromFile() options.
Parameters:
- ctx: Context for controlling server lifecycle
- address: Address for the HTTPS server (e.g., ":8443")
Example:
server, err := servex.New(
servex.WithCertificateFromFile("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err = server.StartWithShutdownHTTPS(ctx, ":8443")
func (*Server) StartWithWaitSignals ¶ added in v2.0.1
func (s *Server) StartWithWaitSignals(ctx context.Context, httpAddr, httpsAddr string, signals ...os.Signal) error
StartWithWaitSignals starts the server with automatic graceful shutdown when the provided signals are received.
This method starts the servers and waits (blocks) until the provided signals are received. When the signals are received, it automatically initiates a graceful shutdown with a 30-second timeout.
Parameters:
- ctx: Context for controlling server lifecycle
- httpAddr: Address for HTTP server (empty string disables HTTP)
- httpsAddr: Address for HTTPS server (empty string disables HTTPS)
- signals: Signals to listen for (default: [os.Interrupt, syscall.SIGTERM])
Example:
server, err := servex.New(
servex.WithCertificateFromFile("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
err = server.StartWithWaitSignals(ctx, ":8080", ":8443", os.Interrupt, syscall.SIGTERM)
if err != nil {
log.Fatal(err)
}
// Server will shutdown gracefully when ctx is cancelled
// or when the program receives a signal
func (*Server) StartWithWaitSignalsHTTP ¶ added in v2.0.1
func (s *Server) StartWithWaitSignalsHTTP(ctx context.Context, address string, signals ...os.Signal) error
StartWithWaitSignalsHTTP starts the HTTP server with automatic graceful shutdown when the provided signals are received.
This method starts the HTTP server and waits (blocks) until the provided signals are received. When the signals are received, it automatically initiates a graceful shutdown with a 30-second timeout.
Parameters:
- ctx: Context for controlling server lifecycle
- httpAddr: Address for HTTP server (empty string disables HTTP)
- httpsAddr: Address for HTTPS server (empty string disables HTTPS)
- signals: Signals to listen for (default: [os.Interrupt, syscall.SIGTERM])
Example:
server, err := servex.New(
servex.WithCertificateFromFile("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
err = server.StartWithWaitSignalsHTTP(ctx, ":8080", os.Interrupt, syscall.SIGTERM)
if err != nil {
log.Fatal(err)
}
// Server will shutdown gracefully when ctx is cancelled
// or when the program receives a signal
func (*Server) StartWithWaitSignalsHTTPS ¶ added in v2.0.1
func (s *Server) StartWithWaitSignalsHTTPS(ctx context.Context, address string, signals ...os.Signal) error
StartWithWaitSignalsHTTPS starts the HTTPS server with automatic graceful shutdown when the provided signals are received.
This method starts the HTTPS server and waits (blocks) until the provided signals are received. When the signals are received, it automatically initiates a graceful shutdown with a 30-second timeout.
Parameters:
- ctx: Context for controlling server lifecycle
- httpAddr: Address for HTTP server (empty string disables HTTP)
- httpsAddr: Address for HTTPS server (empty string disables HTTPS)
- signals: Signals to listen for (default: [os.Interrupt, syscall.SIGTERM])
Example:
server, err := servex.New(
servex.WithCertificateFromFile("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
err = server.StartWithWaitSignalsHTTPS(ctx, ":8443", os.Interrupt, syscall.SIGTERM)
if err != nil {
log.Fatal(err)
}
// Server will shutdown gracefully when ctx is cancelled
// or when the program receives a signal
func (*Server) TRACE ¶
TRACE is an alias for Server.Trace.
func (*Server) Trace ¶
Trace registers a new TRACE route with the provided path and http.HandlerFunc. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) TraceWithAuth ¶
TraceWithAuth registers a new TRACE route with the provided path and http.HandlerFunc. It adds auth middleware to the route with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
func (*Server) Use ¶
Use adds one or more mux.MiddlewareFunc to the router.
func (*Server) WithAuth ¶
func (s *Server) WithAuth(next http.HandlerFunc, roles ...UserRole) http.HandlerFunc
WithAuth adds auth middleware to the router with the provided roles. It returns a pointer to the created mux.Route to set additional settings to the route.
Parameters:
- next: The next handler to register the route for
- roles: The roles to register the route for
Returns:
- http.HandlerFunc: The created handler to register the route for
func (*Server) WithBasePath ¶
WithBasePath sets the base path for the server's router. It returns the server itself to allow method chaining.
Parameters:
- path: The base path to set for the router
Example:
server.WithBasePath("/api")
server.Get("/users", ...)
Result: /api/users
Returns:
- *Server: The server itself to allow method chaining
type ServerConfig ¶
type ServerConfig struct {
HTTP string `yaml:"http" json:"http" env:"SERVEX_SERVER_HTTP"`
HTTPS string `yaml:"https" json:"https" env:"SERVEX_SERVER_HTTPS"`
CertFile string `yaml:"cert_file" json:"cert_file" env:"SERVEX_SERVER_CERT_FILE"`
KeyFile string `yaml:"key_file" json:"key_file" env:"SERVEX_SERVER_KEY_FILE"`
ReadTimeout time.Duration `yaml:"read_timeout" json:"read_timeout" env:"SERVEX_SERVER_READ_TIMEOUT"`
ReadHeaderTimeout time.Duration `yaml:"read_header_timeout" json:"read_header_timeout" env:"SERVEX_SERVER_READ_HEADER_TIMEOUT"`
IdleTimeout time.Duration `yaml:"idle_timeout" json:"idle_timeout" env:"SERVEX_SERVER_IDLE_TIMEOUT"`
AuthToken string `yaml:"auth_token" json:"auth_token" env:"SERVEX_SERVER_AUTH_TOKEN"`
HealthPath string `yaml:"health_path" json:"health_path" env:"SERVEX_SERVER_HEALTH_PATH"`
MetricsPath string `yaml:"metrics_path" json:"metrics_path" env:"SERVEX_SERVER_METRICS_PATH"`
EnableHealthEndpoint bool `yaml:"enable_health_endpoint" json:"enable_health_endpoint" env:"SERVEX_SERVER_ENABLE_HEALTH_ENDPOINT"`
EnableDefaultMetrics bool `yaml:"enable_default_metrics" json:"enable_default_metrics" env:"SERVEX_SERVER_ENABLE_DEFAULT_METRICS"`
SendErrorToClient bool `yaml:"send_error_to_client" json:"send_error_to_client" env:"SERVEX_SERVER_SEND_ERROR_TO_CLIENT"`
EnableRequestSizeLimits bool `yaml:"enable_request_size_limits" json:"enable_request_size_limits" env:"SERVEX_SERVER_ENABLE_REQUEST_SIZE_LIMITS"`
MaxRequestBodySize int64 `yaml:"max_request_body_size" json:"max_request_body_size" env:"SERVEX_SERVER_MAX_REQUEST_BODY_SIZE"`
MaxJSONBodySize int64 `yaml:"max_json_body_size" json:"max_json_body_size" env:"SERVEX_SERVER_MAX_JSON_BODY_SIZE"`
MaxFileUploadSize int64 `yaml:"max_file_upload_size" json:"max_file_upload_size" env:"SERVEX_SERVER_MAX_FILE_UPLOAD_SIZE"`
MaxMultipartMemory int64 `yaml:"max_multipart_memory" json:"max_multipart_memory" env:"SERVEX_SERVER_MAX_MULTIPART_MEMORY"`
HTTPSRedirect HTTPSRedirectConfiguration `yaml:"https_redirect" json:"https_redirect"`
}
ServerConfig represents basic server configuration
type StaticFileConfig ¶
type StaticFileConfig struct {
// Enabled determines whether static file serving is active.
// Must be set to true for static files to be served.
// Set via WithStaticFiles(), WithSPAMode(), or WithStaticFileConfig().
Enabled bool
// Dir is the directory containing static files to serve.
// This is typically the build output directory for React/Vue/Angular apps.
// Set via WithStaticFiles().
//
// Common examples:
// - "build": React build output
// - "dist": Vue/Angular build output
// - "public": Static website files
// - "static": General static assets
//
// Files in this directory will be served at the root path unless URLPrefix is set.
Dir string
// URLPrefix is the URL path prefix for serving static files.
// If empty, files are served from the root path.
// Set via WithStaticFiles() or WithStaticFileConfig().
//
// Examples:
// - "" (empty): Files served from root (e.g., /app.js)
// - "/static": Files served under /static (e.g., /static/app.js)
// - "/assets": Files served under /assets (e.g., /assets/app.js)
//
// For SPAs, this is usually empty so the app is served from the root.
URLPrefix string
// SPAMode enables Single Page Application mode with client-side routing support.
// When enabled, requests that don't match existing files or API routes
// will be served the IndexFile to support client-side routing.
// Set via WithSPAMode().
//
// Use cases:
// - React Router applications
// - Vue Router applications
// - Angular routing
// - Any SPA with client-side routing
//
// When SPAMode is true, API routes should be registered before enabling static files.
SPAMode bool
// IndexFile is the fallback file to serve for SPA client-side routing.
// This file is served when a request doesn't match an existing file or API route.
// Only used when SPAMode is true. Set via WithSPAMode() or WithStaticFileConfig().
//
// Common values:
// - "index.html": Standard for most SPAs
// - "app.html": Custom entry point
//
// Default: "index.html" if SPAMode is true and this is empty.
IndexFile string
// StripPrefix removes the specified prefix from the URL before looking up files.
// This is useful when serving files from a subdirectory but accessing them via a different URL structure.
// Set via WithStaticFileConfig().
//
// Example:
// - URLPrefix: "/app"
// - StripPrefix: "/app"
// - Request: "/app/index.html" → looks for file at "index.html" in Dir
StripPrefix string
// ExcludePaths are URL paths that should not be served as static files.
// These paths will be skipped by the static file handler, allowing other handlers to process them.
// Set via WithStaticFileConfig().
//
// Common exclusions:
// - "/api/*": API endpoints
// - "/auth/*": Authentication endpoints
// - "/admin/*": Admin interfaces
// - "/ws/*": WebSocket endpoints
//
// Path matching supports wildcards (*) for pattern matching.
// API routes registered before static files are automatically excluded.
ExcludePaths []string
// CacheMaxAge sets the Cache-Control max-age directive for static files (in seconds).
// This controls how long browsers and proxies cache static files.
// Set via WithStaticFileConfig().
//
// Common values:
// - 3600: 1 hour (development)
// - 86400: 1 day (staging)
// - 31536000: 1 year (production, for versioned assets)
// - 0: No caching
//
// Different file types can have different cache policies by using the CacheRules field.
CacheMaxAge int
// CacheRules defines cache policies for different file types or paths.
// The key is a file extension (e.g., ".js", ".css") or path pattern (e.g., "/images/*").
// The value is the max-age in seconds.
// Set via WithStaticFileConfig().
//
// Example:
// map[string]int{
// ".js": 31536000, // 1 year for JS files
// ".css": 31536000, // 1 year for CSS files
// ".html": 3600, // 1 hour for HTML files
// "/images/*": 2592000, // 30 days for images
// }
//
// More specific rules override general rules. CacheRules override CacheMaxAge.
CacheRules map[string]int
// contains filtered or unexported fields
}
StaticFileConfig holds configuration for serving static files and Single Page Applications (SPAs).
type StaticFilesConfiguration ¶
type StaticFilesConfiguration struct {
Enabled bool `yaml:"enabled" json:"enabled" env:"SERVEX_STATIC_FILES_ENABLED"`
Dir string `yaml:"dir" json:"dir" env:"SERVEX_STATIC_FILES_DIR"`
URLPrefix string `yaml:"url_prefix" json:"url_prefix" env:"SERVEX_STATIC_FILES_URL_PREFIX"`
SPAMode bool `yaml:"spa_mode" json:"spa_mode" env:"SERVEX_STATIC_FILES_SPA_MODE"`
IndexFile string `yaml:"index_file" json:"index_file" env:"SERVEX_STATIC_FILES_INDEX_FILE"`
StripPrefix string `yaml:"strip_prefix" json:"strip_prefix" env:"SERVEX_STATIC_FILES_STRIP_PREFIX"`
ExcludePaths []string `yaml:"exclude_paths" json:"exclude_paths" env:"SERVEX_STATIC_FILES_EXCLUDE_PATHS"`
CacheMaxAge int `yaml:"cache_max_age" json:"cache_max_age" env:"SERVEX_STATIC_FILES_CACHE_MAX_AGE"`
CacheRules map[string]int `yaml:"cache_rules" json:"cache_rules"`
}
StaticFilesConfiguration represents static file serving configuration
type TrafficDumpConfig ¶
type TrafficDumpConfig struct {
// Enabled indicates if traffic dumping is enabled globally
Enabled bool `yaml:"enabled" json:"enabled"`
// Directory where to store traffic dumps
Directory string `yaml:"directory" json:"directory"`
// MaxFileSize for rotation (in bytes, default: 100MB)
MaxFileSize int64 `yaml:"max_file_size" json:"max_file_size"`
// MaxFiles for retention (default: 10)
MaxFiles int `yaml:"max_files" json:"max_files"`
// IncludeBody whether to include request/response bodies
IncludeBody bool `yaml:"include_body" json:"include_body"`
// MaxBodySize maximum body size to dump (default: 64KB)
MaxBodySize int64 `yaml:"max_body_size" json:"max_body_size"`
// SampleRate for sampling traffic (0.0-1.0, default: 1.0 = all traffic)
SampleRate float64 `yaml:"sample_rate" json:"sample_rate"`
}
TrafficDumpConfig configures traffic dumping
type User ¶
type User struct {
ID string `json:"id" bson:"_id" db:"id"`
Username string `json:"username" bson:"username" db:"username"`
Roles []UserRole `json:"roles" bson:"roles" db:"roles"`
PasswordHash string `json:"password_hash" bson:"password_hash" db:"password_hash"`
RefreshTokenHash string `json:"refresh_token_hash" bson:"refresh_token_hash" db:"refresh_token_hash"`
RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at" bson:"refresh_token_expires_at" db:"refresh_token_expires_at"`
}
User represents a user entity in the system.
type UserContextKey ¶
type UserContextKey struct{}
type UserDiff ¶
type UserDiff struct {
Username *string `json:"username,omitempty" bson:"username,omitempty" db:"username,omitempty"`
Roles *[]UserRole `json:"roles,omitempty" bson:"roles,omitempty" db:"roles,omitempty"`
PasswordHash *string `json:"password_hash,omitempty" bson:"password_hash,omitempty" db:"password_hash,omitempty"`
RefreshTokenHash *string `json:"refresh_token_hash,omitempty" bson:"refresh_token_hash,omitempty" db:"refresh_token_hash,omitempty"`
RefreshTokenExpiresAt *time.Time `json:"refresh_token_expires_at,omitempty" bson:"refresh_token_expires_at,omitempty" db:"refresh_token_expires_at,omitempty"`
}
type UserLoginRequest ¶
type UserLoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
UserLoginRequest represents the request body for user login and registration.
func (UserLoginRequest) Validate ¶
func (req UserLoginRequest) Validate() error
Validate checks if the UserLoginRequest is valid.
type UserLoginResponse ¶
type UserLoginResponse struct {
ID string `json:"id"`
Username string `json:"username"`
Roles []UserRole `json:"roles"`
AccessToken string `json:"accessToken,omitempty"`
}
UserLoginResponse represents the response body for successful user login or registration.
type UserRole ¶
type UserRole string
UserRole represents a role assigned to a user. It's defined as a string type for easy JSON marshaling/unmarshaling.
type UserUpdateRequest ¶
type UserUpdateRequest struct {
ID string `json:"id"`
Username *string `json:"username,omitempty"`
Roles *[]UserRole `json:"roles,omitempty"`
Password *string `json:"password,omitempty"`
}
UserUpdateRequest represents the request body for updating user information.
func (UserUpdateRequest) Validate ¶
func (req UserUpdateRequest) Validate() error
Validate checks if the UserUpdateRequest is valid.
Source Files
¶
- audit.go
- auth.go
- config.go
- context_core.go
- context_helpers.go
- context_request.go
- context_response.go
- context_validation.go
- filter.go
- logging.go
- metrics.go
- middleware_auth.go
- middleware_core.go
- middleware_other.go
- middleware_security.go
- options_auth.go
- options_cache.go
- options_compression.go
- options_core.go
- options_cors.go
- options_filter.go
- options_health.go
- options_https.go
- options_ratelimit.go
- options_security.go
- options_server.go
- options_sizelimits.go
- options_static.go
- presets.go
- proxy.go
- ratelimit.go
- rawhttp.go
- router.go
- servex.go
- static.go