Documentation
¶
Overview ¶
Package httpserver provides an opinionated HTTP server wrapper around Echo v5 with integrated middleware.
The server automatically configures request logging, body size limiting, CORS (optional), validation, and error handling. It supports graceful shutdown and is production-ready.
Basic usage:
server := httpserver.New(&httpserver.Config{
Host: "0.0.0.0",
Port: 8080,
BodyLimit: "10M",
})
server.Echo.GET("/api/users", listUsersHandler)
if err := server.Start(ctx); err != nil {
return err
}
The underlying Echo instance is accessible via server.Echo for route registration and custom middleware. The server implements graceful shutdown with a configurable GracePeriod (default 15s).
Index ¶
- Constants
- func BadRequestError(err error, details ...string) *echo.HTTPError
- func ConflictError(err error, details ...string) *echo.HTTPError
- func ExecuteStandardized[REQ any, RES any](c *echo.Context, request *REQ, handlerName string, ...) (resp any, httpErr *echo.HTTPError)
- func ForbiddenError(err error, details ...string) *echo.HTTPError
- func HTTPError(code int, err error, details ...string) *echo.HTTPError
- func InternalError(err error, details ...string) *echo.HTTPError
- func NormalizePage(page, pageSize int) (normalizedPage, normalizedSize, offset int)
- func NotFoundError(err error, details ...string) *echo.HTTPError
- func RequestIDSkipper(skip bool) echomiddleware.Skipper
- func ServiceUnavailableError(err error, details ...string) *echo.HTTPError
- func UnauthorizedError(err error, details ...string) *echo.HTTPError
- func Wrapper[TREQ any](wrapped func(*echo.Context, *TREQ) (any, *echo.HTTPError)) echo.HandlerFunc
- type APIResponse
- type Config
- type ErrorResponse
- type HandlerFunc
- type HandlerResponse
- type Pagination
- type ResponseError
- type Server
Constants ¶
const ( ErrCodeValidation = i18n.CodeValidation ErrCodeNotFound = i18n.CodeNotFound ErrCodeForbidden = i18n.CodeForbidden ErrCodeConflict = i18n.CodeConflict ErrCodeInternal = i18n.CodeInternal ErrCodeBadRequest = i18n.CodeBadRequest )
Generic message codes, kept as aliases of the i18n codes the error handler reports so both packages cannot drift apart.
const ( DefaultPage = 1 DefaultPageSize = 50 MaxPageSize = 100 )
Variables ¶
This section is empty.
Functions ¶
func ExecuteStandardized ¶
func HTTPError ¶
HTTPError builds an echo error carrying the text shown to the caller.
details is preferably a message code registered in the server's i18n catalog, in which case the error handler reports it as the response code and renders the text in the caller's locale:
httpserver.ConflictError(err, messages.PhoneNumberInUse)
Any other value is treated as literal prose and returned verbatim under the generic code for the status. Omitting details falls back to err.Error(), which reaches the client as-is — pass a code for anything a user acts on.
func NormalizePage ¶
func RequestIDSkipper ¶
func RequestIDSkipper(skip bool) echomiddleware.Skipper
func ServiceUnavailableError ¶
Types ¶
type APIResponse ¶
type APIResponse[T any] struct { RequestID string `example:"3bf74527-8097-4217-8485-ffe05d16f82e" json:"requestId,omitempty"` Data T `json:"data"` Pagination *Pagination `json:"pagination,omitempty"` }
type Config ¶
type Config struct {
Host string
Port int
EnableCors bool
AllowOrigins []string
BodyLimit string
ReadHeaderTimeout time.Duration
ReadTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
GracePeriod time.Duration
Transformer *transformer.Transformer
DisableTransform bool
LogRequestBody bool
// Messages translates the message codes this service's handlers raise. It
// is merged over i18n.BuiltinCatalog, so a service only carries its own
// domain messages.
Messages i18n.Catalog
}
type ErrorResponse ¶ added in v1.7.0
type ErrorResponse struct {
Code string `example:"EMPLOYEE_NOT_FOUND" json:"code"`
Message string `example:"Employee not found" json:"message"`
}
ErrorResponse is the body every error answers with. It exists so handlers can name the real shape in their @Failure annotations — echo.HTTPError declares only a message and would document the response as missing its code.
The code is the contract a client branches on; the message is presentation and changes with the caller's Accept-Language, so nothing may depend on it.
type HandlerFunc ¶
type HandlerResponse ¶
type HandlerResponse[T any] struct { Data T `json:"data"` Pagination *Pagination `json:"pagination,omitempty"` }
func NewPaginatedResponse ¶
func NewPaginatedResponse[T any](data T, pagination *Pagination) *HandlerResponse[T]
func NewResponse ¶
func NewResponse[T any](data T) *HandlerResponse[T]
type Pagination ¶
type Pagination struct {
Page int `example:"1" json:"page"`
PageSize int `example:"10" json:"pageSize"`
TotalCount int `example:"42" json:"totalCount"`
TotalPages int `example:"5" json:"totalPages"`
}
func NewPagination ¶
func NewPagination(page, pageSize, totalCount int) *Pagination
type ResponseError ¶
func (ResponseError) Error ¶
func (e ResponseError) Error() string