From e295d508ac9e5ce2c37c80e765f5ca14ced83723 Mon Sep 17 00:00:00 2001 From: Johnny Steenbergen Date: Wed, 15 Apr 2020 12:43:20 -0700 Subject: [PATCH] fix: make API type marshal before writing to respone writer to avoid duplicate write header calls on failed encoding this fix is necessary to avoid the superflour write header error. When the write fails, we log it, this shoudl never happen unless the connection gets corrupted. In that case there is nothing for the server to do except log --- kit/transport/http/api.go | 29 ++++++++++++++++++++++------- tenant/http_handler_urm_test.go | 12 ++++-------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/kit/transport/http/api.go b/kit/transport/http/api.go index 0ff2dbdacd..e5942ab369 100644 --- a/kit/transport/http/api.go +++ b/kit/transport/http/api.go @@ -165,20 +165,35 @@ func (a *API) Respond(w http.ResponseWriter, status int, v interface{}) { } w.Header().Set("Content-Type", "application/json; charset=utf-8") - enc := json.NewEncoder(writer) + + // this marshal block is to catch failures before they hit the http writer. + // default behavior for http.ResponseWriter is when body is written and no + // status is set, it writes a 200. Or if a status is set before encoding + // and an error occurs, there is no means to write a proper status code + // (i.e. 500) when that is to occur. This brings that step out before + // and then writes the data and sets the status code after marshaling + // succeeds. + var ( + b []byte + err error + ) if a == nil || a.prettyJSON { - enc.SetIndent("", "\t") + b, err = json.MarshalIndent(v, "", "\t") + } else { + b, err = json.Marshal(v) + } + if err != nil { + a.Err(w, err) + return } w.WriteHeader(status) - if err := enc.Encode(v); err != nil { - a.Err(w, err) - return + if _, err := writer.Write(b); err != nil { + a.logErr("failed to write to response writer", zap.Error(err)) } if err := writer.Close(); err != nil { - a.Err(w, err) - return + a.logErr("failed to close response writer", zap.Error(err)) } } diff --git a/tenant/http_handler_urm_test.go b/tenant/http_handler_urm_test.go index ff9f9bde40..59341479b7 100644 --- a/tenant/http_handler_urm_test.go +++ b/tenant/http_handler_urm_test.go @@ -98,8 +98,7 @@ func TestUserResourceMappingService_GetMembersHandler(t *testing.T) { "status": "active" } ] -} -`, +}`, }, }, @@ -162,8 +161,7 @@ func TestUserResourceMappingService_GetMembersHandler(t *testing.T) { "status": "active" } ] -} -`, +}`, }, }, } @@ -273,8 +271,7 @@ func TestUserResourceMappingService_PostMembersHandler(t *testing.T) { "id": "0000000000000001", "name": "user0000000000000001", "status": "active" -} -`, +}`, }, }, @@ -312,8 +309,7 @@ func TestUserResourceMappingService_PostMembersHandler(t *testing.T) { "id": "0000000000000002", "name": "user0000000000000002", "status": "active" -} -`, +}`, }, }, }