-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandler.go
131 lines (119 loc) · 3.64 KB
/
handler.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package gmock // nolint:golint
import (
"bytes"
"encoding/json"
"io"
"net/http"
"github.com/rs/zerolog/log"
)
// addStubHandler is the handler for the /httpmock/add endpoint.
// It expects a POST request with a JSON or YAML body containing a StubRequest.
// The stub is added to the server's stubs map.
// If the stub is invalid, it returns a 400 Bad Request.
// If the stub is valid, it returns a 201 Created.
func (s *Server) addStubHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
log.Error().Msgf("method %s not allowed", r.Method)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Error().Msgf("error reading body: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
stub, err := getStubFromBytes(body)
if err != nil {
log.Error().Msgf("failed to parse stub request: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if errs := s.addStub(stub); len(errs) > 0 {
w.WriteHeader(http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusCreated)
}
// listStubsHandler is the handler for the /httpmock/list endpoint.
// It expects a GET request.
// It returns a JSON array with the existing stubs.
// If no stubs are found, it returns an empty array.
func (s *Server) listStubsHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
log.Error().Msgf("method %s not allowed", r.Method)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
values := make([]*Stub, 0, len(s.stubs))
for _, v := range s.stubs {
values = append(values, v)
}
body, err := json.MarshalIndent(values, "", " ")
if err != nil {
log.Error().Msgf("error marshaling stubs: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if _, err := w.Write(body); err != nil {
log.Error().Msgf("error listing stubs: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
// genericStubHandler is the handler for any stub endpoint.
// It returns the stub response if the current request is an existing stub request.
// If the request is not a stub request, it returns a 404 Not Found.
func (s *Server) genericStubHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
log.Error().Msgf("error reading body: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
// compact JSON body before hashing
var compactedBody string
if body != nil {
buff := new(bytes.Buffer)
if err := json.Compact(buff, body); err != nil {
log.Error().Msgf("error compacting body: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
compactedBody = buff.String()
}
h := getHash(StubRequest{
Method: r.Method,
Path: r.URL.Path,
Query: r.URL.Query(),
Body: compactedBody,
})
if stub, ok := s.stubs[h]; ok {
for k, v := range stub.Response.Headers {
for _, vv := range v {
w.Header().Add(k, vv)
}
}
if _, ok := w.Header()["Content-Type"]; !ok {
w.Header().Set("Content-Type", defaultContentType)
}
log.Info().Msgf("stub found: %s", stub.Request.String())
body, err := json.Marshal(stub.Response.Body)
if err != nil {
log.Error().Msgf("error marshaling stub body: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if _, err := w.Write(body); err != nil {
log.Error().Msgf("error writing stub body: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if stub.Response.StatusCode != http.StatusOK {
w.WriteHeader(stub.Response.StatusCode)
}
return
}
log.Error().Msgf("no stub found for request: %s %s %s", r.Method, r.URL.String(), compactedBody)
w.WriteHeader(http.StatusNotFound)
}