-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjson.go
100 lines (83 loc) · 2.41 KB
/
json.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
// Copyright 2016 Tim Shannon. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package main
import (
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
)
const (
statusSuccess = "success"
statusError = "error"
statusFail = "fail"
)
const maxJSONSize = 1 << 20 //10MB
var errInputTooLarge = &Fail{
Message: "Input size is too large, please check your input and try again",
HTTPStatus: http.StatusRequestEntityTooLarge,
}
// JSend is the standard format for a response from townsourced
type JSend struct {
Status string `json:"status"`
Data interface{} `json:"data,omitempty"`
Message string `json:"message,omitempty"`
Failures []error `json:"failures,omitempty"`
More bool `json:"more,omitempty"` // more data exists for this request
}
//respondJsend marshalls the input into a json byte array
// and writes it to the reponse with appropriate header
func respondJsend(w http.ResponseWriter, response *JSend) {
respondJsendCode(w, response, 0)
}
// respondJsendCode is the same as respondJSend, but lets you specify a status code
func respondJsendCode(w http.ResponseWriter, response *JSend, statusCode int) {
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Content-Type", "application/json")
if len(response.Failures) > 0 && response.Message == "" {
response.Message = "One or more item has failed. Check the individual failures for details."
}
result, err := json.MarshalIndent(response, "", " ")
if err != nil {
log.Printf("Error marshalling response: %s", err)
result, _ = json.Marshal(&JSend{
Status: statusError,
Message: "An internal error occurred, and we'll look into it.",
})
}
if statusCode <= 0 {
switch response.Status {
case statusFail:
w.WriteHeader(http.StatusBadRequest)
case statusError:
w.WriteHeader(http.StatusInternalServerError)
}
//default is status 200
} else {
w.WriteHeader(statusCode)
}
_, err = w.Write(result)
if err != nil {
log.Printf("Error writing jsend response: %s", err)
}
}
func parseInput(r *http.Request, result interface{}) error {
lr := &io.LimitedReader{R: r.Body, N: maxJSONSize + 1}
buff, err := ioutil.ReadAll(lr)
if err != nil {
return err
}
if lr.N == 0 {
return errInputTooLarge
}
if len(buff) == 0 {
return nil
}
err = json.Unmarshal(buff, result)
if err != nil {
return err
}
return nil
}