// Package httputil provides typed handler adapters and HTTP response helpers. // // Handler adapters eliminate HTTP boilerplate — business functions stay pure Go // with no knowledge of request parsing or response encoding. All errors flow // through a centralized [Error] handler that logs once at the correct level and // writes a standardized JSON response body. // // # Typed handler adapters // // type CreateUserReq struct { // Email string `json:"email" validate:"required,email"` // } // type CreateUserRes struct { // ID string `json:"id"` // } // // r.Post("/users", httputil.Handle(v, logger, func(ctx context.Context, req CreateUserReq) (CreateUserRes, error) { // u, err := svc.CreateUser(ctx, req.Email) // if err != nil { // return CreateUserRes{}, err // propagates to Error — logged once, correct HTTP status // } // return CreateUserRes{ID: u.ID}, nil // })) // // # Centralized error handler // // [Error] is the single point of error processing for all handlers: // - 5xx → Error level (logz auto-enriches with error_code and WithContext fields) // - 4xx → Warn level (client mistake — not a server failure) // - 499 → Info level (client cancelled the request intentionally) // // Call it directly from [HandlerFunc] when you need path parameters or custom logic: // // r.Get("/users/{id}", httputil.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { // id := chi.URLParam(r, "id") // u, err := svc.GetUser(r.Context(), id) // if err != nil { // httputil.Error(logger, w, r, err) // return nil // } // httputil.JSON(w, http.StatusOK, u) // return nil // }).ServeHTTP) package httputil