forked from noxecane/anansi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
requests.go
108 lines (96 loc) · 2.63 KB
/
requests.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package siber
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
"github.com/go-chi/chi"
ozzo "github.com/go-ozzo/ozzo-validation/v4"
)
// ReadBody extracts the bytes in a request body without destroying the contents of the body
func ReadBody(r *http.Request) []byte {
var buffer bytes.Buffer
// copy request body to in memory buffer while being read
readSplit := io.TeeReader(r.Body, &buffer)
body, err := ioutil.ReadAll(readSplit)
if err != nil {
panic(err)
}
// return what you collected
r.Body = ioutil.NopCloser(&buffer)
return body
}
// ReadJSON decodes the JSON body of the request and destroys to prevent possible issues with
// writing a response. If the content type is not JSON it fails with a 415. Otherwise it fails
// with a 400 on validation errors.
func ReadJSON(r *http.Request, v interface{}) {
// make sure we are reading a JSON type
contentType := r.Header.Get("Content-Type")
if !strings.Contains(contentType, "application/json") {
panic(JSendError{
Code: http.StatusUnsupportedMediaType,
Message: http.StatusText(http.StatusUnsupportedMediaType),
})
}
err := json.NewDecoder(r.Body).Decode(v)
switch {
case err == io.EOF:
// tell the user all the required attributes
err := ozzo.Validate(v)
if err != nil {
panic(JSendError{
Code: http.StatusUnprocessableEntity,
Message: "We could not validate your request.",
Data: err,
})
}
return
case err != nil:
panic(JSendError{
Code: http.StatusBadRequest,
Message: "We cannot parse your request body.",
Err: err,
})
default:
// validate parsed JSON data
err = ozzo.Validate(v)
if err != nil {
panic(JSendError{
Code: http.StatusUnprocessableEntity,
Message: "We could not validate your request.",
Data: err,
})
}
}
}
// IDParam extracts a uint URL parameter from the given request
func IDParam(r *http.Request, name string) uint {
param := chi.URLParam(r, name)
if param == "" {
err := fmt.Sprintf("requested param %s is not part of route", name)
panic(errors.New(err))
}
raw, err := strconv.ParseUint(param, 10, 32)
if err != nil {
panic(JSendError{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("%s must be an ID", name),
})
}
return uint(raw)
}
// StringParam basically just ensures the param name is correct. You might not
// need this method unless you're too lazy to do real tests.
func StringParam(r *http.Request, name string) string {
param := chi.URLParam(r, name)
if param == "" {
err := fmt.Sprintf("requested param %s is not part of route", name)
panic(errors.New(err))
}
return param
}