-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_decoder.go
93 lines (80 loc) · 2.43 KB
/
json_decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package routes
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/kayprogrammer/socialnet-v6/utils"
)
func DecodeJSONBody(c *fiber.Ctx, dst interface{}) (int, *utils.ErrorResponse) {
var errData *utils.ErrorResponse
code := 200
if c.Get("Content-Type") != "application/json" {
errD := utils.RequestErr(utils.ERR_INVALID_REQUEST, "Content-Type header is not application/json")
errData = &errD
return code, errData
}
dec := json.NewDecoder(bytes.NewReader(c.Body()))
dec.DisallowUnknownFields()
err := dec.Decode(&dst)
msg := "Invalid Entry"
fieldErrors := make(map[string]string)
status_code := 422
if err != nil {
var syntaxError *json.SyntaxError
var unmarshalTypeError *json.UnmarshalTypeError
errStr := err.Error()
switch {
case errors.As(err, &syntaxError):
msg = fmt.Sprintf(
"Request body contains badly-formed JSON (at position %d)",
syntaxError.Offset,
)
case errors.Is(err, io.ErrUnexpectedEOF):
status_code = http.StatusBadRequest
msg="Request body contains badly-formed JSON"
case errors.As(err, &unmarshalTypeError):
fieldName := unmarshalTypeError.Field
fieldErrors[fieldName] = "Invalid format"
case strings.HasPrefix(errStr, "json: unknown field "):
fieldName := strings.TrimPrefix(errStr, "json: unknown field ")
fieldErrors[fieldName] = "Unknown field"
case errors.Is(err, io.EOF):
status_code = http.StatusBadRequest
msg = "Request body must not be empty"
case errStr == "http: request body too large":
status_code = http.StatusRequestEntityTooLarge
msg = "Request body must not be larger than 1MB"
default:
status_code = 400
msg = "Invalid request"
}
errData := utils.RequestErr(utils.ERR_INVALID_REQUEST, msg)
if len(fieldErrors) > 0 {
errData.Data = &fieldErrors
}
code = status_code
return code, &errData
}
err = dec.Decode(&struct{}{})
if err != io.EOF {
errData := utils.RequestErr(utils.ERR_INVALID_REQUEST, "Request body must only contain a single JSON object")
return 400, &errData
}
return code, nil
}
func ValidateRequest(c *fiber.Ctx, data interface{}) (*int, *utils.ErrorResponse) {
validator := utils.Validator()
if errCode, errData := DecodeJSONBody(c, &data); errData != nil {
return &errCode, errData
}
if errData := validator.Validate(data); errData != nil {
errCode := 422
return &errCode, errData
}
return nil, nil
}