github.com/avenga/couper@v1.12.2/handler/producer/response.go (about) 1 package producer 2 3 import ( 4 "io" 5 "net/http" 6 "strings" 7 8 "github.com/hashicorp/hcl/v2/hclsyntax" 9 10 "github.com/avenga/couper/errors" 11 "github.com/avenga/couper/eval" 12 "github.com/avenga/couper/internal/seetie" 13 ) 14 15 // Response represents the producer <Response> object. 16 type Response struct { 17 Context *hclsyntax.Body 18 } 19 20 func NewResponse(req *http.Request, resp *hclsyntax.Body, statusCode int) (*http.Response, error) { 21 clientres := &http.Response{ 22 Header: make(http.Header), 23 Proto: req.Proto, 24 ProtoMajor: req.ProtoMajor, 25 ProtoMinor: req.ProtoMinor, 26 Request: req, 27 } 28 29 hclCtx := eval.ContextFromRequest(req).HCLContextSync() 30 31 if attr, ok := resp.Attributes["status"]; ok { 32 val, err := eval.Value(hclCtx, attr.Expr) 33 if err != nil { 34 return nil, err 35 } else if statusValue := int(seetie.ValueToInt(val)); statusValue > 0 { 36 statusCode = statusValue 37 } 38 } 39 clientres.StatusCode = statusCode 40 clientres.Status = http.StatusText(clientres.StatusCode) 41 42 respBody, ct, bodyErr := eval.GetBody(hclCtx, resp) 43 if bodyErr != nil { 44 return nil, errors.Evaluation.With(bodyErr) 45 } 46 47 if ct != "" { 48 clientres.Header.Set("Content-Type", ct) 49 } 50 51 if attr, ok := resp.Attributes["headers"]; ok { 52 val, err := eval.Value(hclCtx, attr.Expr) 53 if err != nil { 54 return nil, err 55 } 56 57 eval.SetHeader(val, clientres.Header) 58 } 59 60 if respBody != "" { 61 r := strings.NewReader(respBody) 62 clientres.Body = io.NopCloser(r) 63 } 64 65 return clientres, nil 66 }