Newer
Older
"encoding/json"
"fmt"
"io"
)
/**
* Decodes JSON and writes a Bad Request status if it fails.
*/
func DecodeJson(w http.ResponseWriter, r io.Reader, document interface{},
logprefix string) error {
dec := json.NewDecoder(r)
if err := dec.Decode(document); err != nil {
log.Printf("%s Unable to decode JSON: %s", logprefix, err)
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Unable to decode JSON: %s\n", err)
return err
}
return nil
}
/**
* Sends a JSON document to some URL via HTTP.
* :param tweakrequest: can be used to tweak the request before sending it, for
* example by adding authentication headers. May be nil.
* :param responsehandler: is called when a non-error response has been read.
* May be nil.
*/
func SendJson(logprefix, method string, url *url.URL,
payload interface{},
tweakrequest func(req *http.Request),
responsehandler func(resp *http.Response, body []byte) error,
) error {
payload_bytes, err := json.Marshal(payload)
if err != nil {
log.Printf("%s: ERROR: Unable to marshal JSON: %s\n", logprefix, err)
return err
}
// TODO Sybren: enable GZip compression.
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
req, err := http.NewRequest("POST", url.String(), bytes.NewBuffer(payload_bytes))
if err != nil {
log.Printf("%s: ERROR: Unable to create request: %s\n", logprefix, err)
return err
}
req.Header.Add("Content-Type", "application/json")
if tweakrequest != nil {
tweakrequest(req)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Printf("%s: ERROR: Unable to POST to %s: %s\n", logprefix, url, err)
return err
}
body, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
log.Printf("%s: ERROR: Error %d POSTing to %s: %s\n",
logprefix, resp.StatusCode, url, err)
return err
}
if resp.StatusCode >= 300 {
log.Printf("%s: ERROR: Error %d POSTing to %s\n",
logprefix, resp.StatusCode, url)
if resp.StatusCode != 404 {
log.Printf(" body:\n%s\n", body)
}
return fmt.Errorf("%s: Error %d POSTing to %s", logprefix, resp.StatusCode, url)
}
if responsehandler != nil {
return responsehandler(resp, body)
}
return nil
}