Skip to content

Commit

Permalink
early bufferOpts readout
Browse files Browse the repository at this point in the history
  • Loading branch information
malud committed May 16, 2023
1 parent 1817311 commit 481ba00
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 17 deletions.
10 changes: 7 additions & 3 deletions eval/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,12 @@ func (c *Context) WithClientRequest(req *http.Request) *Context {
}
}
port, _ := strconv.ParseInt(p, 10, 64)
// TODO how to set request.BufferOptions appropriately before WithClientRequest() is called
body, jsonBody := parseReqBody(req, true)

var parseJSON bool
if opts, ok := ctx.Value(request.BufferOptions).(BufferOption); ok {
parseJSON = opts.JSONRequest()
}
body, jsonBody := parseReqBody(req, parseJSON)

origin := NewRawOrigin(req.URL)
ctx.eval.Variables[ClientRequest] = cty.ObjectVal(ctxMap.Merge(ContextMap{
Expand Down Expand Up @@ -472,7 +476,7 @@ func mergeBackendVariables(etx *hcl.EvalContext, key string, cmap ContextMap) {
const defaultMaxMemory = 32 << 20 // 32 MB

// parseForm populates the request PostForm field.
// As Proxy we should not consume the request body.
// As Proxy, we should not consume the request body.
// Rewind body via GetBody method.
func parseForm(r *http.Request) *http.Request {
if r.GetBody == nil || r.Form != nil {
Expand Down
20 changes: 15 additions & 5 deletions eval/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsimple"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"

"github.com/avenga/couper/config/configload"
Expand Down Expand Up @@ -87,10 +89,18 @@ func TestNewHTTPContext(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(subT *testing.T) {
file, diags := hclsyntax.ParseConfig([]byte(tt.hcl), "test.hcl", hcl.InitialPos)
if diags.HasErrors() {
subT.Fatal(diags)
}
bufferOption := eval.MustBuffer(file.Body)

helper := test.New(subT)

req := httptest.NewRequest(tt.reqMethod, "https://couper.io/"+tt.query, tt.body)
*req = *req.Clone(context.WithValue(req.Context(), request.Endpoint, "couper-proxy"))
ctx := context.WithValue(req.Context(), request.Endpoint, "couper-proxy")
ctx = context.WithValue(ctx, request.BufferOptions, bufferOption)
*req = *req.Clone(ctx)

for k, v := range tt.reqHeader {
req.Header[k] = v
Expand All @@ -99,13 +109,13 @@ func TestNewHTTPContext(t *testing.T) {
bereq := req.Clone(context.Background())
beresp := newBeresp(bereq)

helper.Must(eval.SetGetBody(req, eval.BufferRequest, 512))
helper.Must(eval.SetGetBody(req, bufferOption, 512))

ctx := baseCtx.WithClientRequest(req).WithBeresp(beresp, cty.NilVal, false).HCLContext()
ctx.Functions = nil // we are not interested in a functions test
hclCtx := baseCtx.WithClientRequest(req).WithBeresp(beresp, cty.NilVal, false).HCLContext()
hclCtx.Functions = nil // we are not interested in a functions test

var resultMap map[string]cty.Value
_ = hclsimple.Decode(tt.name+".hcl", []byte(tt.hcl), ctx, &resultMap)
_ = hclsimple.Decode(tt.name+".hcl", []byte(tt.hcl), hclCtx, &resultMap)

for k, v := range tt.want {
cv, ok := resultMap[k]
Expand Down
12 changes: 8 additions & 4 deletions handler/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ func TestEndpoint_RoundTripContext_Variables_json_body(t *testing.T) {
for _, method := range tt.methods {
t.Run(method+" "+tt.name, func(subT *testing.T) {
helper := test.New(subT)

iBody := helper.NewInlineContext(tt.inlineCtx)
backend := transport.NewBackend(
helper.NewInlineContext(tt.inlineCtx),
iBody,
&transport.Config{NoProxyFromEnv: true}, nil, logger)

ep := handler.NewEndpoint(&handler.EndpointOptions{
Expand All @@ -226,9 +226,12 @@ func TestEndpoint_RoundTripContext_Variables_json_body(t *testing.T) {
req := httptest.NewRequest(method, "/", body)
tt.header.Set(req)

bufferOption := eval.MustBuffer(iBody)

// normally injected by server/http
helper.Must(eval.SetGetBody(req, eval.BufferRequest, 1024))
*req = *req.WithContext(eval.NewDefaultContext().WithClientRequest(req))
helper.Must(eval.SetGetBody(req, bufferOption, 1024))
ctx := context.WithValue(req.Context(), request.BufferOptions, bufferOption)
*req = *req.WithContext(eval.NewDefaultContext().WithClientRequest(req.WithContext(ctx)))

rec := httptest.NewRecorder()
rw := writer.NewResponseWriter(rec, "") // crucial for working ep due to res.Write()
Expand Down Expand Up @@ -347,6 +350,7 @@ func TestEndpoint_RoundTripContext_Null_Eval(t *testing.T) {
} else {
req.Header.Set("Content-Type", "application/json")
}
req = req.WithContext(context.WithValue(context.Background(), request.BufferOptions, bufOpts))
req = req.WithContext(eval.NewDefaultContext().WithClientRequest(req))

rec := httptest.NewRecorder()
Expand Down
12 changes: 7 additions & 5 deletions server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ func (s *HTTPServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
ctx = context.WithValue(ctx, request.Handler, hs.String())
}

if err = s.setGetBody(h, req); err != nil {
bufferOption, err := s.setGetBody(h, req)
if err != nil {
h = mux.opts.ServerOptions.ServerErrTpl.WithError(err)
}

Expand Down Expand Up @@ -283,20 +284,21 @@ func (s *HTTPServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
}

ctx = context.WithValue(ctx, request.BufferOptions, bufferOption)
// due to the middleware callee stack we have to update the 'req' value.
*req = *req.WithContext(s.evalCtx.WithClientRequest(req.WithContext(ctx)))

h.ServeHTTP(rw, req)
}

func (s *HTTPServer) setGetBody(h http.Handler, req *http.Request) error {
func (s *HTTPServer) setGetBody(h http.Handler, req *http.Request) (opt eval.BufferOption, err error) {
inner := getChildHandler(h)

var err error
if limitHandler, ok := inner.(handler.BodyLimit); ok {
err = eval.SetGetBody(req, limitHandler.BufferOptions(), limitHandler.RequestLimit())
opt = limitHandler.BufferOptions()
err = eval.SetGetBody(req, opt, limitHandler.RequestLimit())
}
return err
return opt, err
}

// getHost configures the host from the incoming request host based on
Expand Down
3 changes: 3 additions & 0 deletions server/testdata/integration/endpoint_eval/15_couper.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ server "bodies" {
endpoint "/req" {
response {
status = 200
headers = {
x-json: request.json_body
}
json_body = request
}
}
Expand Down
3 changes: 3 additions & 0 deletions server/testdata/integration/endpoint_eval/19_couper.hcl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
server "request" {
endpoint "/**" {
response {
headers = {
x-json = request.json_body
}
json_body = request
}
}
Expand Down

0 comments on commit 481ba00

Please sign in to comment.