Repository: artilleryio/artillery (JavaScript)

Issue:
Cookies don't work if the url is a $loopElement
<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating it.
-->

Version info: <!-- artillery -v output -->
```

        ___         __  _ ____
  _____/   |  _____/ /_(_) / /__  _______  __ ___
 /____/ /| | / ___/ __/ / / / _ \/ ___/ / / /____/
/____/ ___ |/ /  / /_/ / / /  __/ /  / /_/ /____/
    /_/  |_/_/   \__/_/_/_/\___/_/   \__  /
                                    /____/


VERSION INFO:

Artillery: 2.0.0-29
Node.js:   v18.13.0
OS:        darwin
```

Running this command: 
```
artillery run test-config.yml
```

I expected to see this happen:

When you set a cookie like shown in the `test-config.yml` we should see it being set on the actual request.  You should be able to see it [here](https://requestbin.myworkato.com/wsvvhgws).

Instead, this happened:

No cookie header in the request bin response.

Files being used:
```
# test-config.yml
config:
  target: "https://requestbin.myworkato.com"
scenarios:
  - flow:
    - loop:
      - get:
          url: "{{ $loopElement }}"
          cookie:
            saved: "tapir,sloth"
      over:
        - "/wsvvhgws"
          
```

I have a fix for this, but don't have a test to simulate this yet.  The reason is that the cookie is apparently set on just the last portion of the url(i.e without the domain).



Discussion:

Patch:
diff --git a/packages/core/lib/engine_http.js b/packages/core/lib/engine_http.js
index d686d1c043..8bb024ae0d 100644
--- a/packages/core/lib/engine_http.js
+++ b/packages/core/lib/engine_http.js
@@ -399,6 +399,20 @@ HttpEngine.prototype.step = function step(requestSpec, ee, opts) {
         );
         requestParams.headers = templatedHeaders;
 
+        // We compute the url here so that the cookies are set properly afterwards
+        let url = maybePrependBase(
+          template(requestParams.uri || requestParams.url, context),
+          config
+        );
+
+        if (requestParams.uri) {
+          // If a hook function sets requestParams.uri to something, request.js
+          // will pick that over .url, so we need to delete it.
+          delete requestParams.uri;
+        }
+
+        requestParams.url = url;
+
         if (
           typeof requestParams.cookie === 'object' ||
           typeof context._defaultCookie === 'object'
@@ -423,19 +437,6 @@ HttpEngine.prototype.step = function step(requestSpec, ee, opts) {
           delete requestParams.auth;
         }
 
-        let url = maybePrependBase(
-          template(requestParams.uri || requestParams.url, context),
-          config
-        );
-
-        if (requestParams.uri) {
-          // If a hook function sets requestParams.uri to something, request.js
-          // will pick that over .url, so we need to delete it.
-          delete requestParams.uri;
-        }
-
-        requestParams.url = url;
-
         // TODO: Bypass proxy if "proxy: false" is set
         requestParams.agent = {
           http: context._httpAgent,


Test patch:
diff --git a/packages/core/test/core/unit/engine_http.test.js b/packages/core/test/core/unit/engine_http.test.js
index 16e1941d01..9414d6bbdc 100644
--- a/packages/core/test/core/unit/engine_http.test.js
+++ b/packages/core/test/core/unit/engine_http.test.js
@@ -353,6 +353,66 @@ test('HTTP engine', function (tap) {
       t.end();
     });
   });
+
+  tap.test('custom cookie js in loop', function (t) {
+    const target = nock('http://localhost:8888')
+      .get('/')
+      .reply(200, function () {
+        t.equal(
+          this.req.headers.cookie,
+          'something=1234',
+          'Cookie not set when url is fed from a loop. Make sure to compute url before setting cookies'
+        );
+
+        return 'ok';
+      });
+
+    const script = {
+      config: {
+        target: 'http://localhost:8888',
+        processor: {
+          setCookie: function(requestParams, context, ee, next) {
+            requestParams.cookie = { 'something': '1234' };
+            return next();
+          },
+        },
+      },
+      scenarios: [
+        {
+          flow: [
+            {
+              loop: [
+                {
+                  get: {
+                    url: '{{ $loopElement }}',
+                    beforeRequest: "setCookie"
+                  }
+                }
+              ],
+              over: [
+                "/"
+              ]
+            }
+          ]
+        }
+      ]
+    };
+
+    const engine = new HttpEngine(script);
+    const ee = new EventEmitter();
+    const runScenario = engine.createScenario(script.scenarios[0], ee);
+
+    runScenario({ vars: {} }, function userDone(err) {
+      if (err) {
+        t.fail();
+      }
+
+      t.ok(target.isDone(), 'Should have made a request to /');
+
+      t.end();
+    });
+  });
+
   tap.test('url and uri parameters', function (t) {
     const target = nock('http://localhost:8888')
       .get('/hello?hello=world')