Documentation
¶
Overview ¶
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/kanata996/chix"
)
func main() {
type listUsersQuery struct {
Role string `query:"role"`
}
handler := chix.HandleErrors()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var query listUsersQuery
if chix.Error(r, chix.DecodeQuery(r, &query)) {
return
}
role := strings.TrimSpace(query.Role)
if role == "" {
role = "member"
}
if err := chix.RespondWithMeta(w, http.StatusOK, []map[string]any{
{"id": "u_1", "role": role},
}, map[string]any{"count": 1}); err != nil {
chix.Error(r, err)
}
}))
req := httptest.NewRequest(http.MethodGet, "/users?role=admin", nil)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
fmt.Println(rr.Code)
fmt.Println(strings.TrimSpace(rr.Body.String()))
}
Output: 200 {"data":[{"id":"u_1","role":"admin"}],"meta":{"count":1}}
Index ¶
- func DecodeAndValidateJSON[T any](r *http.Request, dst *T, fn ValidateFunc[T], opts ...DecodeOption) error
- func DecodeAndValidateQuery[T any](r *http.Request, dst *T, fn ValidateFunc[T], opts ...QueryOption) error
- func DecodeJSON[T any](r *http.Request, dst *T, opts ...DecodeOption) error
- func DecodeQuery[T any](r *http.Request, dst *T, opts ...QueryOption) error
- func Error(r *http.Request, err error) bool
- func HandleErrors(opts ...Option) func(http.Handler) http.Handler
- func MethodNotAllowedHandler() http.HandlerFunc
- func NotFoundHandler() http.HandlerFunc
- func Respond(w http.ResponseWriter, status int, data any) error
- func RespondEmpty(w http.ResponseWriter, status int) error
- func RespondWithMeta(w http.ResponseWriter, status int, data any, meta any) error
- func SetRequestID(r *http.Request, id string) *http.Request
- func UseErrorMappers(mappers ...ErrorMapper) func(http.Handler) http.Handler
- func Validate[T any](dst *T, fn ValidateFunc[T]) error
- func WriteError(w http.ResponseWriter, r *http.Request, err error, opts ...Option) bool
- type DecodeOption
- type ErrorMapper
- type ErrorReport
- type ErrorReporter
- type HTTPError
- func BadRequest(code, message string, details ...any) *HTTPError
- func Conflict(code, message string, details ...any) *HTTPError
- func Forbidden(code, message string, details ...any) *HTTPError
- func Gone(code, message string, details ...any) *HTTPError
- func MethodNotAllowed(code, message string, details ...any) *HTTPError
- func NewHTTPError(status int, code, message string, details ...any) *HTTPError
- func NotFound(code, message string, details ...any) *HTTPError
- func TooManyRequests(code, message string, details ...any) *HTTPError
- func Unauthorized(code, message string, details ...any) *HTTPError
- func UnprocessableEntity(code, message string, details ...any) *HTTPError
- type Option
- type QueryOption
- type ValidateFunc
- type Violation
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeAndValidateJSON ¶ added in v0.2.0
func DecodeAndValidateJSON[T any](r *http.Request, dst *T, fn ValidateFunc[T], opts ...DecodeOption) error
DecodeAndValidateJSON decodes a JSON request body, then runs validation.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/kanata996/chix"
"github.com/kanata996/chix/errcode"
)
func main() {
type createUserRequest struct {
Name string `json:"name"`
}
req := httptest.NewRequest(http.MethodPost, "/users", strings.NewReader(`{"name":"alice"}`))
req.Header.Set("Content-Type", "application/json")
var input createUserRequest
err := chix.DecodeAndValidateJSON(req, &input, func(value *createUserRequest) []chix.Violation {
if strings.TrimSpace(value.Name) == "" {
return []chix.Violation{{
Field: "name",
Code: errcode.ViolationRequired,
Message: "is required",
}}
}
return nil
})
fmt.Println(err == nil)
fmt.Println(input.Name)
}
Output: true alice
func DecodeAndValidateQuery ¶ added in v0.2.0
func DecodeAndValidateQuery[T any](r *http.Request, dst *T, fn ValidateFunc[T], opts ...QueryOption) error
DecodeAndValidateQuery decodes URL query parameters, then runs validation.
func DecodeJSON ¶ added in v0.2.0
func DecodeJSON[T any](r *http.Request, dst *T, opts ...DecodeOption) error
DecodeJSON decodes a JSON request body into dst and returns chix-compatible public errors for request-shape failures.
func DecodeQuery ¶ added in v0.2.0
func DecodeQuery[T any](r *http.Request, dst *T, opts ...QueryOption) error
DecodeQuery decodes URL query parameters into `query`-tagged struct fields in dst and returns chix-compatible public errors for request-shape failures.
func Error ¶ added in v0.2.0
Error records err for centralized handling and returns true when err is non-nil.
Error requires HandleErrors middleware to be installed for the current request. When you need immediate one-shot error handling without middleware, use WriteError instead.
func HandleErrors ¶ added in v0.2.0
HandleErrors constructs a standard net/http middleware that centralizes explicit error response writing and error reporting.
func MethodNotAllowedHandler ¶ added in v0.2.0
func MethodNotAllowedHandler() http.HandlerFunc
MethodNotAllowedHandler returns a default 405 handler that enters the centralized error pipeline.
func NotFoundHandler ¶ added in v0.2.0
func NotFoundHandler() http.HandlerFunc
NotFoundHandler returns a default 404 handler that enters the centralized error pipeline.
func Respond ¶ added in v0.2.0
func Respond(w http.ResponseWriter, status int, data any) error
Respond writes a success envelope without meta. The status must permit a response body.
func RespondEmpty ¶ added in v0.2.0
func RespondEmpty(w http.ResponseWriter, status int) error
RespondEmpty writes a body-less successful response.
func RespondWithMeta ¶ added in v0.2.0
RespondWithMeta writes a success envelope with explicit meta. The status must permit a response body.
func SetRequestID ¶ added in v0.2.0
SetRequestID stores the request identifier used by chix error observations.
Callers should always use the returned request for downstream handlers.
func UseErrorMappers ¶ added in v0.2.0
func UseErrorMappers(mappers ...ErrorMapper) func(http.Handler) http.Handler
UseErrorMappers returns standard net/http middleware that prepends request-scoped mappers to the current mapping chain.
This is useful for feature-first routing: each mounted route group can add its own business error mapping close to the delivery adapter, while a single outer HandleErrors middleware remains the centralized write/reporting point.
Example ¶
package main
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/kanata996/chix"
)
func main() {
errUserNotFound := errors.New("user not found")
const codeUserNotFound = "user_not_found"
mapUserError := func(err error) *chix.HTTPError {
if errors.Is(err, errUserNotFound) {
return chix.NotFound(codeUserNotFound, "user not found")
}
return nil
}
users := chix.UseErrorMappers(mapUserError)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
chix.Error(r, errUserNotFound)
}))
handler := chix.HandleErrors()(users)
req := httptest.NewRequest(http.MethodGet, "/users/missing", nil)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
fmt.Println(rr.Code)
fmt.Println(strings.TrimSpace(rr.Body.String()))
}
Output: 404 {"error":{"code":"user_not_found","message":"user not found","details":[]}}
func Validate ¶ added in v0.2.0
func Validate[T any](dst *T, fn ValidateFunc[T]) error
Validate applies a validation function and returns a standardized 422 error when violations are present.
func WriteError ¶ added in v0.2.0
WriteError immediately maps, reports, and writes err using the same error handling pipeline as HandleErrors, but without requiring middleware installation.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/kanata996/chix"
"github.com/kanata996/chix/errcode"
)
func main() {
req := httptest.NewRequest(http.MethodGet, "/reports/heavy", nil)
rr := httptest.NewRecorder()
chix.WriteError(rr, req, chix.TooManyRequests(
errcode.RateLimited,
"rate limit exceeded",
))
fmt.Println(rr.Code)
fmt.Println(strings.TrimSpace(rr.Body.String()))
}
Output: 429 {"error":{"code":"rate_limited","message":"rate limit exceeded","details":[]}}
Types ¶
type DecodeOption ¶ added in v0.2.0
type DecodeOption = reqx.DecodeOption
DecodeOption customizes JSON decoding behavior.
func AllowEmptyBody ¶ added in v0.2.0
func AllowEmptyBody() DecodeOption
AllowEmptyBody permits an empty JSON request body.
func AllowUnknownFields ¶ added in v0.2.0
func AllowUnknownFields() DecodeOption
AllowUnknownFields disables strict unknown-field rejection for JSON decoding.
func WithMaxBodyBytes ¶ added in v0.2.0
func WithMaxBodyBytes(limit int64) DecodeOption
WithMaxBodyBytes limits the number of bytes read from the request body.
type ErrorMapper ¶ added in v0.2.0
ErrorMapper maps an application error into a standardized boundary error.
type ErrorReport ¶ added in v0.2.0
type ErrorReport struct {
Request *http.Request
Error error
PublicError *HTTPError
Stage string
RequestID string
ResponseStarted bool
}
ErrorReport is the centralized observation emitted when chix handles an error. Stage identifies the internal observation point such as decode, validate, routing, processing, or write_response. RequestID is the effective request identifier used by the current error handling chain.
type ErrorReporter ¶ added in v0.2.0
type ErrorReporter func(ErrorReport)
ErrorReporter receives centralized observations for errors handled by chix.
type HTTPError ¶ added in v0.2.0
type HTTPError struct {
// contains filtered or unexported fields
}
HTTPError is the standardized public error representation used at the HTTP boundary.
func BadRequest ¶ added in v0.2.1
BadRequest constructs a 400 public HTTP error.
func MethodNotAllowed ¶ added in v0.2.1
MethodNotAllowed constructs a 405 public HTTP error.
func NewHTTPError ¶ added in v0.2.0
NewHTTPError constructs a public HTTP error.
func TooManyRequests ¶ added in v0.2.1
TooManyRequests constructs a 429 public HTTP error.
func Unauthorized ¶ added in v0.2.1
Unauthorized constructs a 401 public HTTP error.
func UnprocessableEntity ¶ added in v0.2.1
UnprocessableEntity constructs a 422 public HTTP error.
type Option ¶ added in v0.2.0
type Option func(*config)
Option customizes how chix maps and reports errors.
func WithErrorMappers ¶ added in v0.2.0
func WithErrorMappers(mappers ...ErrorMapper) Option
WithErrorMappers appends multiple startup-scoped mappers to the error mapping chain.
func WithErrorReporter ¶ added in v0.2.0
func WithErrorReporter(reporter ErrorReporter) Option
WithErrorReporter overrides centralized reporting for errors handled by chix. Passing nil disables reporting for chix error handling.
type QueryOption ¶ added in v0.2.0
type QueryOption = reqx.QueryOption
QueryOption customizes URL query decoding behavior.
func AllowUnknownQueryFields ¶ added in v0.2.0
func AllowUnknownQueryFields() QueryOption
AllowUnknownQueryFields disables strict unknown-field rejection for query parameters.
type ValidateFunc ¶ added in v0.2.0
ValidateFunc validates a decoded request value.