forked from nyaruka/courier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
responses.go
133 lines (116 loc) · 3.87 KB
/
responses.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
132
133
package courier
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/sirupsen/logrus"
validator "gopkg.in/go-playground/validator.v9"
)
// WriteError writes a JSON response for the passed in error
func WriteError(w http.ResponseWriter, r *http.Request, err error) error {
errors := []string{err.Error()}
vErrs, isValidation := err.(validator.ValidationErrors)
if isValidation {
errors = []string{}
for i := range vErrs {
errors = append(errors, fmt.Sprintf("field '%s' %s", strings.ToLower(vErrs[i].Field()), vErrs[i].Tag()))
}
}
return writeJSONResponse(w, http.StatusBadRequest, &errorResponse{errors})
}
// WriteIgnored writes a JSON response for the passed in message
func WriteIgnored(w http.ResponseWriter, r *http.Request, details string) error {
logrus.WithFields(logrus.Fields{
"url": r.Context().Value(contextRequestURL),
"elapsed_ms": getElapsedMS(r),
"details": details,
}).Info("msg ignored")
return writeData(w, http.StatusOK, details, struct{}{})
}
// WriteReceiveSuccess writes a JSON response for the passed in msg indicating we handled it
func WriteReceiveSuccess(w http.ResponseWriter, r *http.Request, msg Msg) error {
logrus.WithFields(logrus.Fields{
"url": r.Context().Value(contextRequestURL),
"elapsed_ms": getElapsedMS(r),
"channel_uuid": msg.Channel().UUID(),
"msg_uuid": msg.UUID(),
"msg_id": msg.ID().Int64,
"msg_urn": msg.URN().Identity(),
"msg_text": msg.Text(),
"msg_attachments": msg.Attachments(),
}).Info("msg received")
return writeData(w, http.StatusOK, "Message Accepted",
&receiveData{
msg.Channel().UUID(),
msg.UUID(),
msg.Text(),
msg.URN(),
msg.Attachments(),
msg.ExternalID(),
msg.ReceivedOn(),
})
}
// WriteStatusSuccess writes a JSON response for the passed in status update indicating we handled it
func WriteStatusSuccess(w http.ResponseWriter, r *http.Request, status MsgStatus) error {
log := logrus.WithFields(logrus.Fields{
"url": r.Context().Value(contextRequestURL),
"elapsed_ms": getElapsedMS(r),
"channel_uuid": status.ChannelUUID(),
})
if status.ID() != NilMsgID {
log = log.WithField("msg_id", status.ID().Int64)
} else {
log = log.WithField("msg_external_id", status.ExternalID())
}
log.Info("status updated")
return writeData(w, http.StatusOK, "Status Update Accepted",
&statusData{
status.ChannelUUID(),
status.Status(),
status.ID(),
status.ExternalID(),
})
}
func getElapsedMS(r *http.Request) float64 {
start := r.Context().Value(contextRequestStart)
if start == nil {
return -1
}
startTime, isTime := start.(time.Time)
if !isTime {
return -1
}
return float64(time.Now().Sub(startTime)) / float64(time.Millisecond)
}
type errorResponse struct {
Errors []string `json:"errors"`
}
type successResponse struct {
Message string `json:"message"`
Data interface{} `json:"data"`
}
type receiveData struct {
ChannelUUID ChannelUUID `json:"channel_uuid"`
MsgUUID MsgUUID `json:"msg_uuid"`
Text string `json:"text"`
URN URN `json:"urn"`
Attachments []string `json:"attachments,omitempty"`
ExternalID string `json:"external_id,omitempty"`
ReceivedOn *time.Time `json:"received_on,omitempty"`
}
type statusData struct {
ChannelUUID ChannelUUID `json:"channel_uuid"`
Status MsgStatusValue `json:"status"`
MsgID MsgID `json:"msg_id,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
func writeJSONResponse(w http.ResponseWriter, statusCode int, response interface{}) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
return json.NewEncoder(w).Encode(response)
}
func writeData(w http.ResponseWriter, statusCode int, message string, response interface{}) error {
return writeJSONResponse(w, statusCode, &successResponse{message, response})
}