63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package httputil
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
)
|
|
|
|
func WriteJSON(w http.ResponseWriter, status int, data any) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(data)
|
|
}
|
|
|
|
func DecodeJSON[T any](w http.ResponseWriter, r *http.Request) (T, error) {
|
|
var v T
|
|
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
|
|
|
|
dec := json.NewDecoder(r.Body)
|
|
dec.DisallowUnknownFields()
|
|
|
|
if err := dec.Decode(&v); err != nil {
|
|
return v, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func WriteValidationErrors(w http.ResponseWriter, err error) {
|
|
var ve validator.ValidationErrors
|
|
if !errors.As(err, &ve) {
|
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
|
return
|
|
}
|
|
|
|
problems := make(map[string]string, len(ve))
|
|
for _, fe := range ve {
|
|
problems[fe.Field()] = messageForTag(fe)
|
|
}
|
|
WriteJSON(w, http.StatusBadRequest, map[string]any{"errors": problems})
|
|
}
|
|
|
|
func messageForTag(fe validator.FieldError) string {
|
|
switch fe.Tag() {
|
|
case "required":
|
|
return "is required"
|
|
case "email":
|
|
return "must be a valid email address"
|
|
case "min":
|
|
return fmt.Sprintf("must be at least %s characters", fe.Param())
|
|
case "max":
|
|
return fmt.Sprintf("must be at most %s characters", fe.Param())
|
|
case "gte":
|
|
return fmt.Sprintf("must be %s or greater", fe.Param())
|
|
case "lte":
|
|
return fmt.Sprintf("must be %s or less", fe.Param())
|
|
default:
|
|
return "is invalid"
|
|
}
|
|
}
|