Skip to content

Commit

Permalink
Fixup #449 : buffer body for default edge case (#450)
Browse files Browse the repository at this point in the history
* Fixup #449 : buffer body for default edge case

* Fixup, ignore situation for websocket configurations

* Add additional testcases
  • Loading branch information
Marcel Ludwig authored Mar 3, 2022
1 parent e6c196d commit 157a4a6
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
24 changes: 18 additions & 6 deletions eval/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,13 @@ func newBerespValues(ctx context.Context, readBody bool, beresp *http.Response)
}
} else if bOk && (bufferOption&BufferResponse) != BufferResponse {
hasBlock, _ := bereq.Context().Value(request.ResponseBlock).(bool)
ws, _ := bereq.Context().Value(request.WebsocketsAllowed).(bool)
if name != "default" || (name == "default" && hasBlock) {
// beresp body is not referenced and can be closed
// prevent resource leak, free connection
_ = beresp.Body.Close()
} else if !ws {
parseSetRespBody(beresp)
}
}

Expand Down Expand Up @@ -430,24 +433,33 @@ func parseReqBody(req *http.Request) (cty.Value, cty.Value) {
func parseRespBody(beresp *http.Response) (cty.Value, cty.Value) {
jsonBody := cty.EmptyObjectVal

if beresp == nil || beresp.Body == nil {
b := parseSetRespBody(beresp)
if b == nil {
return cty.NilVal, jsonBody
}

if isJSONMediaType(beresp.Header.Get("Content-Type")) {
jsonBody = parseJSONBytes(b)
}
return cty.StringVal(string(b)), jsonBody
}

func parseSetRespBody(beresp *http.Response) []byte {
if beresp == nil || beresp.Body == nil {
return nil
}

b, err := io.ReadAll(beresp.Body)
if err != nil {
return cty.NilVal, jsonBody
return nil
}

// prevent resource leak
_ = beresp.Body.Close()

beresp.Body = io.NopCloser(bytes.NewBuffer(b)) // reset

if isJSONMediaType(beresp.Header.Get("Content-Type")) {
jsonBody = parseJSONBytes(b)
}
return cty.StringVal(string(b)), jsonBody
return b
}

func parseJSONBytes(b []byte) cty.Value {
Expand Down
8 changes: 8 additions & 0 deletions server/http_backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package server_test
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -38,6 +39,8 @@ func TestBackend_MaxConnections_BodyClose(t *testing.T) {
"/",
"/named",
"/default",
"/default2",
"/ws",
}

for _, p := range paths {
Expand All @@ -51,5 +54,10 @@ func TestBackend_MaxConnections_BodyClose(t *testing.T) {
if res.StatusCode != http.StatusOK {
t.Errorf("want: 200, got %d", res.StatusCode)
}

_, err = io.Copy(io.Discard, res.Body)
helper.Must(err)

helper.Must(res.Body.Close())
}
}
19 changes: 19 additions & 0 deletions server/testdata/integration/backends/04_couper.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ server {
backend = "be"
}
}

endpoint "/default2" {
request {
url = "{{ .origin }}/"
backend = "be"
}
request "a" {
url = "{{ .origin }}/"
backend = "be"
}
}

endpoint "/ws" {
proxy {
url = "{{ .origin }}/"
websockets = true
backend = "be"
}
}
}

definitions {
Expand Down

0 comments on commit 157a4a6

Please sign in to comment.