httpserver

package module
v0.8.4 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2025 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ServerDefaultReadTimeout  = 600
	ServerDefaultWriteTimeout = 600
	ServerDefaultPort         = 5000
	ServerDefaultName         = "http"
)
View Source
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

func NewFieldError(field string, message string) error

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 NewRouter

func NewRouter(serverName string, debug bool, logger *log.Logger) *gin.Engine

NewRouter creates a new gin router with standardized logging

func ValidateJSON

func ValidateJSON(c *gin.Context, obj interface{}) bool

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

func ValidateQuery(c *gin.Context, obj interface{}) bool

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

type FieldError struct {
	Field string
	Err   error
}

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 OptionsFunc func(*Server) error

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

func (s *Server) Route() *gin.Engine

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

func (s *Server) Shutdown(ctx context.Context) error

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

func (s *Server) Start() error

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) UseAuth

func (s *Server) UseAuth(provider auth.Provider)

UseAuth registers an auth middleware

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

func (s *Server) UseRateLimiting(ratePerMinute int)

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

func (*Server) UseSession

func (s *Server) UseSession(config *session.Config, backend kv.KV, logger *log.Logger) (*session.Manager, error)

UseSession adds session middleware with provided storage

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

type ValidationError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

ValidationError represents a field validation error

type Validator added in v0.8.3

type Validator interface {
	Validate() error
}

Validator interface for custom validation logic Implement this interface on your request structs to add custom validation that runs after binding validation succeeds

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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