94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
"git.threesix.ai/jordan/sp4-final-1770497325/pkg/httperror"
|
|
"git.threesix.ai/jordan/sp4-final-1770497325/pkg/httpresponse"
|
|
"git.threesix.ai/jordan/sp4-final-1770497325/pkg/httpvalidation"
|
|
)
|
|
|
|
// Bind decodes JSON from the request body into v.
|
|
// Returns an HTTPError on failure that can be returned directly from a HandlerFunc.
|
|
//
|
|
// Usage:
|
|
//
|
|
// func CreateUser(w http.ResponseWriter, r *http.Request) error {
|
|
// var req CreateUserRequest
|
|
// if err := app.Bind(r, &req); err != nil {
|
|
// return err // Returns typed HTTPError
|
|
// }
|
|
// // req is now decoded
|
|
// }
|
|
func Bind(r *http.Request, v any) error {
|
|
if err := httpresponse.DecodeJSON(r, v); err != nil {
|
|
if errors.Is(err, httpresponse.ErrEmptyBody) {
|
|
return httperror.BadRequest("request body is required")
|
|
}
|
|
return httperror.BadRequest("invalid request body")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BindStrict decodes JSON from the request body with strict field checking.
|
|
// Unknown fields in the JSON will cause an error.
|
|
func BindStrict(r *http.Request, v any) error {
|
|
if err := httpresponse.DecodeJSONStrict(r, v); err != nil {
|
|
if errors.Is(err, httpresponse.ErrEmptyBody) {
|
|
return httperror.BadRequest("request body is required")
|
|
}
|
|
if errors.Is(err, httpresponse.ErrUnknownFields) {
|
|
return httperror.BadRequest("unknown fields in request body")
|
|
}
|
|
return httperror.BadRequest("invalid request body")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BindAndValidate decodes JSON and validates using httpvalidation.
|
|
// Returns a validation error with field-level details if validation fails.
|
|
//
|
|
// Usage:
|
|
//
|
|
// type CreateUserRequest struct {
|
|
// Name string `json:"name" validate:"required,min=1,max=100"`
|
|
// Email string `json:"email" validate:"required,email"`
|
|
// }
|
|
//
|
|
// func CreateUser(w http.ResponseWriter, r *http.Request) error {
|
|
// var req CreateUserRequest
|
|
// if err := app.BindAndValidate(r, &req); err != nil {
|
|
// return err
|
|
// }
|
|
// // req is decoded and validated
|
|
// }
|
|
func BindAndValidate(r *http.Request, v any) error {
|
|
// Decode JSON
|
|
if err := Bind(r, v); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Validate struct
|
|
if details := httpvalidation.ValidateStruct(v); len(details) > 0 {
|
|
return httperror.WithDetails(httperror.Validation("validation failed"), details)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// BindAndValidateStrict decodes JSON with strict field checking and validates.
|
|
func BindAndValidateStrict(r *http.Request, v any) error {
|
|
// Decode JSON strictly
|
|
if err := BindStrict(r, v); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Validate struct
|
|
if details := httpvalidation.ValidateStruct(v); len(details) > 0 {
|
|
return httperror.WithDetails(httperror.Validation("validation failed"), details)
|
|
}
|
|
|
|
return nil
|
|
}
|