Skip to content

Commit

Permalink
handle specific check for case agent-target address is url (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucamrgs authored May 14, 2024
1 parent 8f39ce8 commit c386480
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
26 changes: 26 additions & 0 deletions test/unittest/utils/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,32 @@ func TestHttpPathParser(t *testing.T) {
assert.Equal(t, parsedUrl, "https://godcapability.tno.nl")
}

func TestHttpPathUrlComposition(t *testing.T) {
target := cacao.AgentTarget{
Address: map[cacao.NetAddressType][]string{
"url": {"https://godcapability.tno.nl/isp"},
},
}

command := cacao.Command{
Type: "http-api",
Command: "POST /isp/cst HTTP/1.1",
Headers: map[string][]string{"accept": {"application/json"}},
}
httpOptions := http.HttpOptions{
Target: &target,
Command: &command,
}

parsedUrl, err := httpOptions.ExtractUrl()
if err != nil {
t.Error("failed test because: ", err)
}
// Duplication of path values if present is INTENDED behaviour and
// a warning will be issued
assert.Equal(t, parsedUrl, "https://godcapability.tno.nl/isp/isp/cst")
}

func TestHttpPathBreakingParser(t *testing.T) {
target := cacao.AgentTarget{
Address: map[cacao.NetAddressType][]string{
Expand Down
50 changes: 38 additions & 12 deletions utils/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ var (
log *logger.Log
)

func init() {
log = logger.Logger(component, logger.Info, "", logger.Json)
}

type HttpOptions struct {
Target *cacao.AgentTarget
Command *cacao.Command
Expand Down Expand Up @@ -52,7 +56,6 @@ func (httpRequest *HttpRequest) SkipCertificateValidation(skip bool) {
}

func (httpRequest *HttpRequest) Request(httpOptions HttpOptions) ([]byte, error) {
log = logger.Logger(component, logger.Info, "", logger.Json)
request, err := httpOptions.setupRequest()
if err != nil {
return []byte{}, err
Expand Down Expand Up @@ -201,9 +204,17 @@ func (httpOptions *HttpOptions) ExtractUrl() (string, error) {
}
}

// If for an http-api command the agent-target address is a URL,
// we should warn for misuse of the field when appendind command-specified path
if len(target.Address["url"]) > 0 {
if target.Address["url"][0] != "" {
return parsePathBasedUrl(target.Address["url"][0])
urlObject, err := parsePathBasedUrl(target.Address["url"][0])
if err != nil {
return "", err
}
if (urlObject.Path != "" && urlObject.Path != "/") && urlObject.Path == path {
log.Warn("possible http api invocation path duplication: agent-target url has same path of http-api command path")
}
}
}
return buildSchemeAndHostname(path, target)
Expand All @@ -213,11 +224,25 @@ func buildSchemeAndHostname(path string, target *cacao.AgentTarget) (string, err
var hostname string

scheme := setDefaultScheme(target)
hostname, err := extractHostname(scheme, target)
hostname, err := extractHostname(target)
if err != nil {
return "", err
}

// If only URL is used to compose the URL target, then
// scheme and port are not considered
if len(target.Address["url"]) > 0 &&
len(target.Address["dname"]) == 0 &&
len(target.Address["ipv4"]) == 0 &&
len(target.Address["ipv6"]) == 0 {

url := strings.TrimSuffix(hostname, "/")
if len(path) > 1 && !strings.HasPrefix(path, "/") {
path = "/" + path
}
return strings.TrimSuffix(url+path, "/"), nil
}

parsedUrl := &url.URL{
Scheme: scheme,
Host: fmt.Sprintf("%s:%s", hostname, target.Port),
Expand All @@ -240,7 +265,7 @@ func setDefaultScheme(target *cacao.AgentTarget) string {
return scheme
}

func extractHostname(scheme string, target *cacao.AgentTarget) (string, error) {
func extractHostname(target *cacao.AgentTarget) (string, error) {
var address string

if len(target.Address["dname"]) > 0 {
Expand All @@ -256,28 +281,29 @@ func extractHostname(scheme string, target *cacao.AgentTarget) (string, error) {
return "", errors.New("failed regex rule for domain name")
}
address = target.Address["ipv4"][0]

} else if len(target.Address["url"]) > 0 {
match, _ := regexp.MatchString(ipv4Regex, target.Address["url"][0])
if !match {
return "", errors.New("failed regex rule for domain name")
_, err := parsePathBasedUrl(target.Address["url"][0])
if err != nil {
return "", err
}
address = target.Address["url"][0]

} else {
return "", errors.New("unsupported target address type")
}
return address, nil
}

func parsePathBasedUrl(httpUrl string) (string, error) {
func parsePathBasedUrl(httpUrl string) (*url.URL, error) {
parsedUrl, err := url.ParseRequestURI(httpUrl)
if err != nil {
return "", err
return parsedUrl, err
}

if parsedUrl.Hostname() == "" {
return "", errors.New("no domain name")
return parsedUrl, errors.New("no domain name")
}
return parsedUrl.String(), nil
return parsedUrl, nil
}

func validatePort(port string) error {
Expand Down

0 comments on commit c386480

Please sign in to comment.