@@ -382,3 +382,101 @@ func (s *UtilsTestSuite) TestResolvePlaceholderSpecialCharactersInValue() {
382382 })
383383 }
384384}
385+
386+ func (s * UtilsTestSuite ) TestResolveRequestPlaceholderFromInitiatorRequest () {
387+ ctx := & providers.NodeContext {}
388+ ctx .SetInitiatorRequest (& providers.InitiatorRequest {
389+ Headers : map [string ][]string {"User-Agent" : {"curl/8.0" }},
390+ QueryParams : map [string ][]string {"utm_source" : {"newsletter" }},
391+ })
392+
393+ tests := []struct {
394+ name string
395+ input string
396+ expected string
397+ }{
398+ {"Header default source" , "{{request(header.User-Agent)}}" , "curl/8.0" },
399+ {"Header explicit init source" , "{{request(init.header.User-Agent)}}" , "curl/8.0" },
400+ {"Header case-insensitive lookup" , "{{request(header.user-agent)}}" , "curl/8.0" },
401+ {"Query default source" , "{{request(query.utm_source)}}" , "newsletter" },
402+ {"Query explicit init source" , "{{request(init.query.utm_source)}}" , "newsletter" },
403+ {"Embedded in larger value" , "ua={{request(header.User-Agent)}}" , "ua=curl/8.0" },
404+ }
405+
406+ for _ , tt := range tests {
407+ s .Run (tt .name , func () {
408+ result := ResolvePlaceholder (ctx , tt .input , nil , nil , nil )
409+ s .Equal (tt .expected , result )
410+ })
411+ }
412+ }
413+
414+ func (s * UtilsTestSuite ) TestResolveRequestPlaceholderFromCurrentRequest () {
415+ ctx := & providers.NodeContext {}
416+ ctx .SetInitiatorRequest (& providers.InitiatorRequest {
417+ Headers : map [string ][]string {"User-Agent" : {"init-agent" }},
418+ })
419+ ctx .SetCurrentRequest (& providers.InitiatorRequest {
420+ Headers : map [string ][]string {"User-Agent" : {"flow-agent" }},
421+ QueryParams : map [string ][]string {"step" : {"otp" }},
422+ })
423+
424+ s .Equal ("flow-agent" , ResolvePlaceholder (ctx , "{{request(flow.header.User-Agent)}}" , nil , nil , nil ))
425+ s .Equal ("otp" , ResolvePlaceholder (ctx , "{{request(flow.query.step)}}" , nil , nil , nil ))
426+ // Default source stays init even when a current request is present.
427+ s .Equal ("init-agent" , ResolvePlaceholder (ctx , "{{request(header.User-Agent)}}" , nil , nil , nil ))
428+ }
429+
430+ func (s * UtilsTestSuite ) TestResolveRequestPlaceholderQueryIsCaseSensitive () {
431+ ctx := & providers.NodeContext {}
432+ ctx .SetInitiatorRequest (& providers.InitiatorRequest {
433+ QueryParams : map [string ][]string {"utm_source" : {"newsletter" }},
434+ })
435+
436+ s .Equal ("{{request(query.UTM_SOURCE)}}" ,
437+ ResolvePlaceholder (ctx , "{{request(query.UTM_SOURCE)}}" , nil , nil , nil ),
438+ "query lookups must be case-sensitive" )
439+ }
440+
441+ func (s * UtilsTestSuite ) TestResolveRequestPlaceholderFirstValueWins () {
442+ ctx := & providers.NodeContext {}
443+ ctx .SetInitiatorRequest (& providers.InitiatorRequest {
444+ Headers : map [string ][]string {"X-Forwarded-For" : {"1.1.1.1" , "2.2.2.2" }},
445+ })
446+
447+ s .Equal ("1.1.1.1" , ResolvePlaceholder (ctx , "{{request(header.X-Forwarded-For)}}" , nil , nil , nil ))
448+ }
449+
450+ func (s * UtilsTestSuite ) TestResolveRequestPlaceholderUnresolvable () {
451+ ctxWithReq := & providers.NodeContext {}
452+ ctxWithReq .SetInitiatorRequest (& providers.InitiatorRequest {
453+ Headers : map [string ][]string {"User-Agent" : {"curl/8.0" }},
454+ })
455+
456+ ctxWithoutReq := & providers.NodeContext {}
457+
458+ tests := []struct {
459+ name string
460+ ctx * providers.NodeContext
461+ input string
462+ expected string
463+ }{
464+ {"Nil initiator request" , ctxWithoutReq , "{{request(header.User-Agent)}}" ,
465+ "{{request(header.User-Agent)}}" },
466+ {"Nil current request" , ctxWithReq , "{{request(flow.header.User-Agent)}}" ,
467+ "{{request(flow.header.User-Agent)}}" },
468+ {"Unknown header" , ctxWithReq , "{{request(header.X-Missing)}}" , "{{request(header.X-Missing)}}" },
469+ {"Unknown source" , ctxWithReq , "{{request(other.header.User-Agent)}}" ,
470+ "{{request(other.header.User-Agent)}}" },
471+ {"Unknown type" , ctxWithReq , "{{request(cookie.session)}}" , "{{request(cookie.session)}}" },
472+ {"Missing name" , ctxWithReq , "{{request(header.)}}" , "{{request(header.)}}" },
473+ {"Missing type separator" , ctxWithReq , "{{request(header)}}" , "{{request(header)}}" },
474+ }
475+
476+ for _ , tt := range tests {
477+ s .Run (tt .name , func () {
478+ result := ResolvePlaceholder (tt .ctx , tt .input , nil , nil , nil )
479+ s .Equal (tt .expected , result )
480+ })
481+ }
482+ }
0 commit comments