fix: don't flush status immediately

Closes: #148

Co-authored-by: Roberto Abdelkader Martínez Pérez <robertomartinezp@gmail.com>
This commit is contained in:
pancho horrillo
2021-01-11 17:54:54 +01:00
parent 5dbfee40eb
commit ec227c2ba3
6 changed files with 34 additions and 12 deletions
+6 -1
View File
@@ -194,7 +194,6 @@ func setResponseStatus(w http.ResponseWriter, r *http.Request, h *model.Handler)
httperror.ErrorJSON(w, InvalidStatusCode, http.StatusBadRequest) httperror.ErrorJSON(w, InvalidStatusCode, http.StatusBadRequest)
} else { } else {
h.Status = si h.Status = si
h.Writer.WriteHeader(si)
} }
} }
@@ -223,6 +222,12 @@ func setResponseCookies(w http.ResponseWriter, r *http.Request, h *model.Handler
} }
func setResponseBody(w http.ResponseWriter, r *http.Request, h *model.Handler) { func setResponseBody(w http.ResponseWriter, r *http.Request, h *model.Handler) {
if !h.BodyOut {
h.Writer.WriteHeader(h.Status)
h.BodyOut = true
}
n, err := io.Copy(h.Writer, r.Body) n, err := io.Copy(h.Writer, r.Body)
if err != nil { if err != nil {
if n > 0 { if n > 0 {
+1 -1
View File
@@ -1319,7 +1319,7 @@ func TestSetResponseStatusSetsGivenStatus(t *testing.T) {
setResponseStatus(w, r, &h) setResponseStatus(w, r, &h)
res := hw.Result() res := hw.Result()
if res.StatusCode != http.StatusTeapot { if h.Status != http.StatusTeapot {
t.Errorf("Status code mismatch. Expected: 418, Got: %d", res.StatusCode) t.Errorf("Status code mismatch. Expected: 418, Got: %d", res.StatusCode)
} }
} }
+3
View File
@@ -47,4 +47,7 @@ type Handler struct {
// SentBytes is the number of sent bytes // SentBytes is the number of sent bytes
SentBytes int64 SentBytes int64
// The transfer of the body has started
BodyOut bool
} }
@@ -75,6 +75,12 @@ func handlerBuilder(route model.Route) http.Handler {
err = spawner(h, nil, nil) err = spawner(h, nil, nil)
} }
// In case of the user not setting /request/body
if !h.BodyOut {
h.Writer.WriteHeader(h.Status)
h.BodyOut = true
}
if err != nil { if err != nil {
logger.L.Println(err) logger.L.Println(err)
} }
@@ -46,8 +46,9 @@ func TestHandlerBuilderCallsSpawner(t *testing.T) {
called = true called = true
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
if !called { if !called {
t.Error("Didn't call spawner") t.Error("Didn't call spawner")
@@ -64,8 +65,9 @@ func TestHandlerBuilderStoresHandlerInDataHandlers(t *testing.T) {
} }
h := handlerBuilder(route) h := handlerBuilder(route)
data.Handlers = data.New() data.Handlers = data.New()
w := httptest.NewRecorder()
h.ServeHTTP(nil, nil) h.ServeHTTP(w, nil)
if !added { if !added {
t.Error("handler not added to data.Handlers") t.Error("handler not added to data.Handlers")
@@ -85,8 +87,9 @@ func TestHandlerBuilderStoresTheProperRoute(t *testing.T) {
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
if !reflect.DeepEqual(got, route) { if !reflect.DeepEqual(got, route) {
t.Error("Route not stored properly in the handler") t.Error("Route not stored properly in the handler")
@@ -105,8 +108,9 @@ func TestHandlerBuilderStoresTheProperRequest(t *testing.T) {
return nil return nil
} }
r := &http.Request{} r := &http.Request{}
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, r) handlerBuilder(route).ServeHTTP(w, r)
if got != r { if got != r {
t.Error("Request not stored properly in the handler") t.Error("Request not stored properly in the handler")
@@ -145,8 +149,9 @@ func TestHandlerBuilderGeneratesAProperID(t *testing.T) {
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
if _, err := uuid.Parse(got); err != nil { if _, err := uuid.Parse(got); err != nil {
t.Error("ID not generated properly") t.Error("ID not generated properly")
@@ -165,8 +170,9 @@ func TestHandlerBuilderCallsSpawnerWithTheStoredHandler(t *testing.T) {
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
if gotStored != gotPassed { if gotStored != gotPassed {
t.Error("Proper handler not passed to spawner()") t.Error("Proper handler not passed to spawner()")
@@ -196,8 +202,9 @@ func TestHandlerBuilderRemovesHandlerWhenDone(t *testing.T) {
spawner = spawn.Spawn spawner = spawn.Spawn
idGenerator = uuid.NewUUID idGenerator = uuid.NewUUID
route := model.Route{} route := model.Route{}
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
if len(data.Handlers.ListIDs()) != 0 { if len(data.Handlers.ListIDs()) != 0 {
t.Error("Handler not removed upon completion") t.Error("Handler not removed upon completion")
@@ -218,8 +225,9 @@ func TestHandlerBuilderLogToLogHandlerWhenDebugIsEnabled(t *testing.T) {
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
// NOTE: logStream will write stdout and stderr contents eventually. // NOTE: logStream will write stdout and stderr contents eventually.
// We do not have any control the goroutines running logStream, thus we // We do not have any control the goroutines running logStream, thus we
@@ -252,8 +260,9 @@ func TestHandlerBuilderDoesNotLogToLogHandlerWhenDebugIsDisabled(t *testing.T) {
return nil return nil
} }
w := httptest.NewRecorder()
handlerBuilder(route).ServeHTTP(nil, nil) handlerBuilder(route).ServeHTTP(w, nil)
// NOTE: logStream will write stdout and stderr contents eventually. // NOTE: logStream will write stdout and stderr contents eventually.
// We do not have any control the goroutines running logStream, thus we // We do not have any control the goroutines running logStream, thus we
@@ -51,7 +51,6 @@ Feature: Setting values for handler response resources in Kapow! server.
| /response/body | bodyValue1 | body | - | | /response/body | bodyValue1 | body | - |
| /response/stream | bodyValue2 | body | - | | /response/stream | bodyValue2 | body | - |
@skip
Scenario: Overwrite a resource for the current response. Scenario: Overwrite a resource for the current response.
Write twice a on a resource, such as a gzip middleware would require: Write twice a on a resource, such as a gzip middleware would require:
kapow get /response/body | gzip -c | kapow set /response/body kapow get /response/body | gzip -c | kapow set /response/body