improve parse errors, they now return type errors, no field name though because that's broken for some reason

This commit is contained in:
sam 2023-12-27 01:44:41 +01:00
parent c8066be0a6
commit 9726827706
No known key found for this signature in database
GPG key ID: B4EF20DDE721CAA1
2 changed files with 55 additions and 17 deletions

View file

@ -1,11 +1,8 @@
package admin package admin
import ( import (
"encoding/json"
"net/http" "net/http"
"reflect"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server" "codeberg.org/pronounscc/pronouns.cc/backend/server"
"github.com/aarondl/opt/omit" "github.com/aarondl/opt/omit"
"github.com/go-chi/render" "github.com/go-chi/render"
@ -68,22 +65,11 @@ func (s *Server) UserAction(w http.ResponseWriter, r *http.Request) (err error)
ctx := r.Context() ctx := r.Context()
claims, _ := server.ClaimsFromContext(ctx) claims, _ := server.ClaimsFromContext(ctx)
var req UserActionRequest req, err := server.Decode[UserActionRequest](r)
err = json.NewDecoder(r.Body).Decode(&req)
if err != nil { if err != nil {
// TODO: figure out why this isn't working return err
log.Debug(reflect.TypeOf(err).String())
log.Debugf("%#v", err)
log.Debugf("%T", err)
if pe, ok := err.(*json.UnmarshalTypeError); ok {
log.Debugf("value = %q, field = %q\n", pe.Value, pe.Field)
} else {
log.Debugf("type assertion for %T to *json.UnmarshalTypeError failed", err)
}
return server.NewV2Error(server.ErrBadRequest, "")
} }
// validate input
if errs := req.Validate(); len(errs) != 0 { if errs := req.Validate(); len(errs) != 0 {
return server.NewV2Error(server.ErrBadRequest, "", errs...) return server.NewV2Error(server.ErrBadRequest, "", errs...)
} }

View file

@ -1,8 +1,12 @@
package server package server
import ( import (
"encoding/json"
"fmt" "fmt"
"io"
"net/http"
json2 "github.com/aarondl/json"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
) )
@ -58,6 +62,9 @@ type ModelParseError struct {
ExpectedValues []any `json:"expected_values,omitempty"` ExpectedValues []any `json:"expected_values,omitempty"`
ActualValue any `json:"actual_value,omitempty"` ActualValue any `json:"actual_value,omitempty"`
ExpectedType string `json:"expected_type,omitempty"`
ActualType string `json:"actual_type,omitempty"`
Key string `json:"-"` Key string `json:"-"`
} }
@ -82,3 +89,48 @@ func NewModelParseErrorWithValues(key, message string, expectedValues []any, act
ActualValue: actualValue, ActualValue: actualValue,
} }
} }
func ParseJSONError(err error) *ModelParseError {
switch pe := err.(type) {
case *json.UnmarshalTypeError:
key := pe.Field
if key == "" {
key = "parse"
}
return &ModelParseError{
Key: key,
ExpectedType: pe.Type.String(),
ActualType: pe.Value,
}
case *json2.UnmarshalTypeError:
key := pe.Field
if key == "" {
key = "parse"
}
return &ModelParseError{
Key: key,
ExpectedType: pe.Type.String(),
ActualType: pe.Value,
}
}
return nil
}
func Decode[T any](r *http.Request) (T, error) {
var t T
b, _ := io.ReadAll(r.Body)
err := json.Unmarshal(b, &t)
// err := render.Decode(r, &t)
if err != nil {
pe := ParseJSONError(err)
if pe != nil {
return t, NewV2Error(ErrBadRequest, "", *pe)
}
return t, NewV2Error(ErrBadRequest, "")
}
return t, nil
}