Update util dep

main
Kegan Dougal 2017-02-21 17:17:56 +00:00
parent 51f9741b34
commit 9e6127d12a
4 changed files with 55 additions and 15 deletions

2
vendor/manifest vendored
View File

@ -92,7 +92,7 @@
{ {
"importpath": "github.com/matrix-org/util", "importpath": "github.com/matrix-org/util",
"repository": "https://github.com/matrix-org/util", "repository": "https://github.com/matrix-org/util",
"revision": "0bbc3896e02031e7e7338948b73ce891aa73ab2b", "revision": "4de125c773716ad380f2f80cc6c04789ef4c906a",
"branch": "master" "branch": "master"
}, },
{ {

View File

@ -5,8 +5,14 @@ import "fmt"
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error. // HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
type HTTPError struct { type HTTPError struct {
WrappedError error WrappedError error
Message string // A human-readable message to return to the client in a JSON response. This
Code int // is ignored if JSON is supplied.
Message string
// HTTP status code.
Code int
// JSON represents the JSON that should be serialized and sent to the client
// instead of the given Message.
JSON interface{}
} }
func (e HTTPError) Error() string { func (e HTTPError) Error() string {

View File

@ -68,7 +68,10 @@ func Protect(handler http.HandlerFunc) http.HandlerFunc {
"Request panicked!\n%s", debug.Stack(), "Request panicked!\n%s", debug.Stack(),
) )
jsonErrorResponse( jsonErrorResponse(
w, req, &HTTPError{nil, "Internal Server Error", 500}, w, req, &HTTPError{
Message: "Internal Server Error",
Code: 500,
},
) )
} }
}() }()
@ -112,7 +115,10 @@ func MakeJSONAPI(handler JSONRequestHandler) http.HandlerFunc {
if !ok { if !ok {
r, err := json.Marshal(res) r, err := json.Marshal(res)
if err != nil { if err != nil {
jsonErrorResponse(w, req, &HTTPError{nil, "Failed to serialise response as JSON", 500}) jsonErrorResponse(w, req, &HTTPError{
Message: "Failed to serialise response as JSON",
Code: 500,
})
return return
} }
resBytes = r resBytes = r
@ -135,9 +141,23 @@ func jsonErrorResponse(w http.ResponseWriter, req *http.Request, httpErr *HTTPEr
w.WriteHeader(httpErr.Code) // Set response code w.WriteHeader(httpErr.Code) // Set response code
r, err := json.Marshal(&JSONError{ var err error
Message: httpErr.Message, var r []byte
}) if httpErr.JSON != nil {
r, err = json.Marshal(httpErr.JSON)
if err != nil {
// failed to marshal the supplied interface. Whine and fallback to the HTTP message.
logger.WithError(err).Error("Failed to marshal HTTPError.JSON")
}
}
// failed to marshal or no custom JSON was supplied, send message JSON.
if err != nil || httpErr.JSON == nil {
r, err = json.Marshal(&JSONError{
Message: httpErr.Message,
})
}
if err != nil { if err != nil {
// We should never fail to marshal the JSON error response, but in this event just skip // We should never fail to marshal the JSON error response, but in this event just skip
// marshalling altogether // marshalling altogether

View File

@ -29,12 +29,26 @@ func TestMakeJSONAPI(t *testing.T) {
ExpectCode int ExpectCode int
ExpectJSON string ExpectJSON string
}{ }{
{nil, &HTTPError{nil, "Everything is broken", 500}, 500, `{"message":"Everything is broken"}`}, // Error return values // Error message return values
{nil, &HTTPError{nil, "Not here", 404}, 404, `{"message":"Not here"}`}, // With different status codes {nil, &HTTPError{nil, "Everything is broken", 500, nil}, 500, `{"message":"Everything is broken"}`},
{&MockResponse{"yep"}, nil, 200, `{"foo":"yep"}`}, // Success return values // Error JSON return values
{[]MockResponse{{"yep"}, {"narp"}}, nil, 200, `[{"foo":"yep"},{"foo":"narp"}]`}, // Top-level array success values {nil, &HTTPError{nil, "Everything is broken", 500, struct {
{[]byte(`actually bytes`), nil, 200, `actually bytes`}, // raw []byte escape hatch Foo string `json:"foo"`
{func(cannotBe, marshalled string) {}, nil, 500, `{"message":"Failed to serialise response as JSON"}`}, // impossible marshal }{"yep"}}, 500, `{"foo":"yep"}`},
// Error JSON return values which fail to be marshalled should fallback to text
{nil, &HTTPError{nil, "Everything is broken", 500, struct {
Foo interface{} `json:"foo"`
}{func(cannotBe, marshalled string) {}}}, 500, `{"message":"Everything is broken"}`},
// With different status codes
{nil, &HTTPError{nil, "Not here", 404, nil}, 404, `{"message":"Not here"}`},
// Success return values
{&MockResponse{"yep"}, nil, 200, `{"foo":"yep"}`},
// Top-level array success values
{[]MockResponse{{"yep"}, {"narp"}}, nil, 200, `[{"foo":"yep"},{"foo":"narp"}]`},
// raw []byte escape hatch
{[]byte(`actually bytes`), nil, 200, `actually bytes`},
// impossible marshal
{func(cannotBe, marshalled string) {}, nil, 500, `{"message":"Failed to serialise response as JSON"}`},
} }
for _, tst := range tests { for _, tst := range tests {
@ -58,7 +72,7 @@ func TestMakeJSONAPI(t *testing.T) {
func TestMakeJSONAPIRedirect(t *testing.T) { func TestMakeJSONAPIRedirect(t *testing.T) {
log.SetLevel(log.PanicLevel) // suppress logs in test output log.SetLevel(log.PanicLevel) // suppress logs in test output
mock := MockJSONRequestHandler{func(req *http.Request) (interface{}, *HTTPError) { mock := MockJSONRequestHandler{func(req *http.Request) (interface{}, *HTTPError) {
return nil, &HTTPError{nil, "https://matrix.org", 302} return nil, &HTTPError{nil, "https://matrix.org", 302, nil}
}} }}
mockReq, _ := http.NewRequest("GET", "http://example.com/foo", nil) mockReq, _ := http.NewRequest("GET", "http://example.com/foo", nil)
mockWriter := httptest.NewRecorder() mockWriter := httptest.NewRecorder()