Skip to content

Commit c386480

Browse files
authored
handle specific check for case agent-target address is url (#119)
1 parent 8f39ce8 commit c386480

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

test/unittest/utils/http/http_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,32 @@ func TestHttpPathParser(t *testing.T) {
470470
assert.Equal(t, parsedUrl, "https://godcapability.tno.nl")
471471
}
472472

473+
func TestHttpPathUrlComposition(t *testing.T) {
474+
target := cacao.AgentTarget{
475+
Address: map[cacao.NetAddressType][]string{
476+
"url": {"https://godcapability.tno.nl/isp"},
477+
},
478+
}
479+
480+
command := cacao.Command{
481+
Type: "http-api",
482+
Command: "POST /isp/cst HTTP/1.1",
483+
Headers: map[string][]string{"accept": {"application/json"}},
484+
}
485+
httpOptions := http.HttpOptions{
486+
Target: &target,
487+
Command: &command,
488+
}
489+
490+
parsedUrl, err := httpOptions.ExtractUrl()
491+
if err != nil {
492+
t.Error("failed test because: ", err)
493+
}
494+
// Duplication of path values if present is INTENDED behaviour and
495+
// a warning will be issued
496+
assert.Equal(t, parsedUrl, "https://godcapability.tno.nl/isp/isp/cst")
497+
}
498+
473499
func TestHttpPathBreakingParser(t *testing.T) {
474500
target := cacao.AgentTarget{
475501
Address: map[cacao.NetAddressType][]string{

utils/http/http.go

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ var (
2323
log *logger.Log
2424
)
2525

26+
func init() {
27+
log = logger.Logger(component, logger.Info, "", logger.Json)
28+
}
29+
2630
type HttpOptions struct {
2731
Target *cacao.AgentTarget
2832
Command *cacao.Command
@@ -52,7 +56,6 @@ func (httpRequest *HttpRequest) SkipCertificateValidation(skip bool) {
5256
}
5357

5458
func (httpRequest *HttpRequest) Request(httpOptions HttpOptions) ([]byte, error) {
55-
log = logger.Logger(component, logger.Info, "", logger.Json)
5659
request, err := httpOptions.setupRequest()
5760
if err != nil {
5861
return []byte{}, err
@@ -201,9 +204,17 @@ func (httpOptions *HttpOptions) ExtractUrl() (string, error) {
201204
}
202205
}
203206

207+
// If for an http-api command the agent-target address is a URL,
208+
// we should warn for misuse of the field when appendind command-specified path
204209
if len(target.Address["url"]) > 0 {
205210
if target.Address["url"][0] != "" {
206-
return parsePathBasedUrl(target.Address["url"][0])
211+
urlObject, err := parsePathBasedUrl(target.Address["url"][0])
212+
if err != nil {
213+
return "", err
214+
}
215+
if (urlObject.Path != "" && urlObject.Path != "/") && urlObject.Path == path {
216+
log.Warn("possible http api invocation path duplication: agent-target url has same path of http-api command path")
217+
}
207218
}
208219
}
209220
return buildSchemeAndHostname(path, target)
@@ -213,11 +224,25 @@ func buildSchemeAndHostname(path string, target *cacao.AgentTarget) (string, err
213224
var hostname string
214225

215226
scheme := setDefaultScheme(target)
216-
hostname, err := extractHostname(scheme, target)
227+
hostname, err := extractHostname(target)
217228
if err != nil {
218229
return "", err
219230
}
220231

232+
// If only URL is used to compose the URL target, then
233+
// scheme and port are not considered
234+
if len(target.Address["url"]) > 0 &&
235+
len(target.Address["dname"]) == 0 &&
236+
len(target.Address["ipv4"]) == 0 &&
237+
len(target.Address["ipv6"]) == 0 {
238+
239+
url := strings.TrimSuffix(hostname, "/")
240+
if len(path) > 1 && !strings.HasPrefix(path, "/") {
241+
path = "/" + path
242+
}
243+
return strings.TrimSuffix(url+path, "/"), nil
244+
}
245+
221246
parsedUrl := &url.URL{
222247
Scheme: scheme,
223248
Host: fmt.Sprintf("%s:%s", hostname, target.Port),
@@ -240,7 +265,7 @@ func setDefaultScheme(target *cacao.AgentTarget) string {
240265
return scheme
241266
}
242267

243-
func extractHostname(scheme string, target *cacao.AgentTarget) (string, error) {
268+
func extractHostname(target *cacao.AgentTarget) (string, error) {
244269
var address string
245270

246271
if len(target.Address["dname"]) > 0 {
@@ -256,28 +281,29 @@ func extractHostname(scheme string, target *cacao.AgentTarget) (string, error) {
256281
return "", errors.New("failed regex rule for domain name")
257282
}
258283
address = target.Address["ipv4"][0]
284+
259285
} else if len(target.Address["url"]) > 0 {
260-
match, _ := regexp.MatchString(ipv4Regex, target.Address["url"][0])
261-
if !match {
262-
return "", errors.New("failed regex rule for domain name")
286+
_, err := parsePathBasedUrl(target.Address["url"][0])
287+
if err != nil {
288+
return "", err
263289
}
264290
address = target.Address["url"][0]
291+
265292
} else {
266293
return "", errors.New("unsupported target address type")
267294
}
268295
return address, nil
269296
}
270297

271-
func parsePathBasedUrl(httpUrl string) (string, error) {
298+
func parsePathBasedUrl(httpUrl string) (*url.URL, error) {
272299
parsedUrl, err := url.ParseRequestURI(httpUrl)
273300
if err != nil {
274-
return "", err
301+
return parsedUrl, err
275302
}
276-
277303
if parsedUrl.Hostname() == "" {
278-
return "", errors.New("no domain name")
304+
return parsedUrl, errors.New("no domain name")
279305
}
280-
return parsedUrl.String(), nil
306+
return parsedUrl, nil
281307
}
282308

283309
func validatePort(port string) error {

0 commit comments

Comments
 (0)