Documentation
¶
Index ¶
- Constants
- func NewFieldError(field string, message string) error
- func NewRouter(serverName string, debug bool, logger *log.Logger) *gin.Engine
- func ValidateJSON(c *gin.Context, obj interface{}) bool
- func ValidateQuery(c *gin.Context, obj interface{}) bool
- type FieldError
- type OptionsFunc
- type Server
- func (s *Server) AddMiddleware(middlewareFunc gin.HandlerFunc)
- func (s *Server) Group(relativePath string) *gin.RouterGroup
- func (s *Server) ProcessOptions(withOptions ...OptionsFunc) error
- func (s *Server) Route() *gin.Engine
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Start() error
- func (s *Server) UseAuth(provider auth.Provider)
- func (s *Server) UseCSRFProtection()
- func (s *Server) UseDefaultSecurityHeaders()
- func (s *Server) UseRateLimiting(ratePerMinute int)
- func (s *Server) UseSecurityHeaders(config *security.SecurityConfig)
- func (s *Server) UseSession(config *session.Config, backend kv.KV, logger *log.Logger) (*session.Manager, error)
- type ServerConfig
- type ValidationError
- type Validator
Constants ¶
const ( ServerDefaultReadTimeout = 600 ServerDefaultWriteTimeout = 600 ServerDefaultPort = 5000 ServerDefaultName = "http" )
const ( // misc server options OptAuthTokenHeader = "authTokenHeader" OptAuthTokenSecret = "authTokenSecret" OptDefaultSecurityHeaders = "defaultSecurityHeaders" OptHMACSecret = "hmacSecret" )
Variables ¶
This section is empty.
Functions ¶
func NewFieldError ¶ added in v0.8.3
NewFieldError creates a custom validation error for a specific field Use this in your Validate() method to return field-specific errors
Example:
func (r *LoginRequest) Validate() error {
if r.Username == "admin" && len(r.Password) < 12 {
return NewFieldError("password", "admin password must be at least 12 characters")
}
return nil
}
This will produce: {"field": "password", "message": "admin password must be at least 12 characters"} For nested structs: {"field": "address.password", "message": "..."}
func ValidateJSON ¶
ValidateJSON validates an incoming JSON request against a struct with validation tags It performs two-stage validation: 1. Binding validation using `binding` tags 2. Recursive custom validation for structs implementing Validator interface
Error responses include full field paths for nested structures (e.g., "address.zip_code")
Example usage:
type Address struct {
Street string `json:"street" binding:"required"`
ZipCode string `json:"zip_code" binding:"required,len=5"`
}
func (a *Address) Validate() error {
if a.ZipCode == "00000" {
return NewFieldError("zip_code", "invalid zip code")
}
return nil
}
type LoginRequest struct {
Username string `json:"username" binding:"required,email"`
Password string `json:"password" binding:"required,min=8,max=32,securepassword"`
Address Address `json:"address" binding:"required"`
}
func (r *LoginRequest) Validate() error {
if r.Username == "admin" && len(r.Password) < 12 {
// Using NewFieldError for field-specific errors
return NewFieldError("password", "admin password must be at least 12 characters")
}
// Or return generic error for top-level validation
return nil
}
// Error response examples:
// Field-specific: {"errors": [{"field": "password", "message": "admin password must be at least 12 characters"}]}
// Nested field: {"errors": [{"field": "address.zip_code", "message": "invalid zip code"}]}
// Generic: {"errors": [{"field": "custom", "message": "validation failed"}]}
func LoginHandler(c *gin.Context) {
var req LoginRequest
if !ValidateJSON(c, &req) {
return // Validation failed and error response already sent
}
// Continue with valid request
}
func ValidateQuery ¶
ValidateQuery validates URL query parameters against a struct with validation tags It performs two-stage validation: 1. Binding validation using `binding` tags 2. Recursive custom validation for structs implementing Validator interface
Error responses include full field paths for nested structures ¶
Example usage:
type SearchRequest struct {
Query string `form:"q" binding:"required,min=3"`
Page int `form:"page" binding:"min=1"`
PageSize int `form:"page_size" binding:"min=10,max=100"`
}
func (s *SearchRequest) Validate() error {
if s.Page > 1000 {
return NewFieldError("page", "maximum page number is 1000")
}
return nil
}
func SearchHandler(c *gin.Context) {
var req SearchRequest
if !ValidateQuery(c, &req) {
return // Validation failed and error response already sent
}
// Continue with valid request
}
Types ¶
type FieldError ¶ added in v0.8.3
FieldError wraps validation errors with field path context
func (*FieldError) Error ¶ added in v0.8.3
func (e *FieldError) Error() string
func (*FieldError) Unwrap ¶ added in v0.8.3
func (e *FieldError) Unwrap() error
type OptionsFunc ¶
type Server ¶
type Server struct {
Config *ServerConfig
Router *gin.Engine
Server *http.Server
Logger *log.Logger
}
func NewServer ¶
func NewServer(cfg *ServerConfig, logger *log.Logger) (*Server, error)
NewServer creates a new http server.
Example usage:
cfg := &ServerConfig{...}
server, err := NewServer(cfg)
if err != nil {
log.Fatal(err)
}
server.Start()
func (*Server) AddMiddleware ¶
func (s *Server) AddMiddleware(middlewareFunc gin.HandlerFunc)
AddMiddleware adds the specified middleware function to the server's router. The middlewareFunc parameter should be a function that accepts a *gin.Context parameter. The function is added as middleware to the server's router using the Use() method of the gin.Engine. This allows the middleware to be executed for each incoming request before reaching the final handler. Example usage:
server.AddMiddleware(myMiddleware)
func myMiddleware(ctx *gin.Context) {
// do something before reaching the final handler
ctx.Next()
// do something after the final handler
}
Note: The AddMiddleware method is defined on the Server struct which contains a Router field of type gin.Engine.
func (*Server) Group ¶
func (s *Server) Group(relativePath string) *gin.RouterGroup
Group creates a new RouterGroup with the specified relativePath. A RouterGroup is used to group routes together and apply common middleware and settings. The relativePath parameter is the base path for all routes added to the group. The returned value is a pointer to the newly created RouterGroup.
Example usage:
server := &Server{
// initialize other fields
Router: gin.New(),
}
group := server.Group("/api") group.GET("/users", getUsers)
This will create a group with the base path "/api" and add a route for GET "/users". All routes added to the group will have the "/api" prefix.
func (*Server) ProcessOptions ¶
func (s *Server) ProcessOptions(withOptions ...OptionsFunc) error
ProcessOptions process default options for server
func (*Server) Route ¶
Route returns the gin.Engine instance associated with the Server.
It is used to access the underlying gin.Engine for adding routes and defining middleware.
Example usage:
server := Server{
// initialize other fields
}
engine := server.Route()
engine.GET("/hello", func(c *gin.Context) {
// handle request
})
Note: The gin.Engine instance is stored in the Router field of the Server struct.
func (*Server) Shutdown ¶
Shutdown gracefully shuts down the server by calling the Shutdown method of the underlying httpserver.Server. It takes a context.Context object as a parameter, which can be used to control the shutdown process. The method returns an error if the shutdown process fails.
func (*Server) Start ¶
Start starts the HTTP server of the Server instance. If the Server's TLSConfig is nil, it starts the server using ListenAndServe method of httpserver.Server. Otherwise, it starts the server using ListenAndServeTLS method of httpserver.Server. If the returned error from the server is not http.ErrServerClosed, it is returned. Otherwise, nil is returned.
Usage example:
func (a *SampleApplication) Run() {
// register http destructor callback
blueprint.RegisterDestructor(func() error {
return a.httpServer.Shutdown(a.container.GetContext())
})
// Start application - http server
a.container.Run(func(app interface{}) error {
go func() {
log.Info().Msg(fmt.Sprintf("Running Sample Application API at %s:%d", a.httpServer.Config.Host, a.httpServer.Config.Port))
a.container.AbortFatal(a.httpServer.Start())
}()
return nil
})
}
func (*Server) UseCSRFProtection ¶
func (s *Server) UseCSRFProtection()
UseCSRFProtection adds CSRF protection to the server
func (*Server) UseDefaultSecurityHeaders ¶
func (s *Server) UseDefaultSecurityHeaders()
UseDefaultSecurityHeaders adds default security headers to a server
func (*Server) UseRateLimiting ¶
UseRateLimiting adds rate limiting middleware to the server ratePerMinute specifies the allowed requests per minute
func (*Server) UseSecurityHeaders ¶
func (s *Server) UseSecurityHeaders(config *security.SecurityConfig)
UseSecurityHeaders adds default security headers to a server
type ServerConfig ¶
type ServerConfig struct {
Host string `json:"host"`
Port int `json:"port"`
ReadTimeout int `json:"readTimeout"`
WriteTimeout int `json:"writeTimeout"`
Debug bool `json:"debug"`
Options map[string]string `json:"options"`
TrustedProxies []string `json:"trustedProxies"`
tlsProvider.ServerConfig
}
func NewServerConfig ¶
func NewServerConfig() *ServerConfig
func (*ServerConfig) GetOption ¶
func (c *ServerConfig) GetOption(key string, defaultValue string) string
GetOption retrieves the value associated with the specified key from the Options map of the ServerConfig. If the key exists, the corresponding value is returned. Otherwise, the defaultValue is returned. The Options map is defined as map[string]string in the ServerConfig struct. Example usage:
serverConfig := ServerConfig{
// initialize other fields
Options: map[string]string{
"key1": "value1",
"key2": "value2",
},
}
option := serverConfig.GetOption("key1", "default")
// option is "value1"
option := serverConfig.GetOption("key3", "default")
// option is "default"
func (*ServerConfig) GetUrl ¶ added in v0.8.2
func (c *ServerConfig) GetUrl() string
GetUrl build http url from config
func (*ServerConfig) NewServer ¶
func (c *ServerConfig) NewServer(logger *log.Logger) (*Server, error)
func (*ServerConfig) Validate ¶
func (c *ServerConfig) Validate() error
type ValidationError ¶
ValidationError represents a field validation error