github.com/avenga/couper@v1.12.2/handler/producer/url.go (about)

     1  package producer
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/hcl/v2"
    10  	"github.com/hashicorp/hcl/v2/hclsyntax"
    11  	"github.com/zclconf/go-cty/cty"
    12  
    13  	"github.com/avenga/couper/config/request"
    14  	"github.com/avenga/couper/eval"
    15  	"github.com/avenga/couper/utils"
    16  )
    17  
    18  func NewURLFromAttribute(hclCtx *hcl.EvalContext, content *hclsyntax.Body, attrName string, req *http.Request) (*url.URL, error) {
    19  	urlVal, err := eval.ValueFromBodyAttribute(hclCtx, content, attrName)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	if urlVal.Type() == cty.NilType { // not set
    25  		return req.URL, nil
    26  	}
    27  
    28  	if urlVal.Type() != cty.String {
    29  		return nil, fmt.Errorf("url %q: not a string", attrName)
    30  	}
    31  
    32  	urlStr := urlVal.AsString()
    33  	if urlStr == "" { // no attr
    34  		return req.URL, nil
    35  	}
    36  
    37  	u, err := url.ParseRequestURI(urlStr) // method forces abs path
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	pathMatch, wildcardEP := req.Context().Value(request.Wildcard).(string)
    43  
    44  	path := u.Path
    45  
    46  	if wildcardEP {
    47  		if strings.HasSuffix(u.Path, "/**") {
    48  			if strings.HasSuffix(req.URL.Path, "/") && !strings.HasSuffix(pathMatch, "/") {
    49  				pathMatch += "/"
    50  			}
    51  
    52  			path = utils.JoinPath("/", strings.ReplaceAll(u.Path, "/**", "/"), pathMatch)
    53  		}
    54  	}
    55  
    56  	u.Path = path
    57  	return u, nil
    58  }
    59  
    60  // removeHost prevents client-request host to leak into backend structure.
    61  func removeHost(outreq *http.Request) {
    62  	outreq.Host = ""
    63  	outreq.URL.Host = ""
    64  }