Reusing the same session over several VUs

Hi,

I am completly new to k6 so this might actually be a non-issue.
The web page I am trying to test has a mandatory login, however if possible I would like to have only one login per VU, not one login per iteration. After some digging around I found this old issue:

with the suggestion of using _ITER for that purpose. However this caused only the first iteration to succeed and all others to fail.

Here is the corresponding script:

const url=__ENV.URL

export default function() {
if (__ITER == 0) {
var res = http.get(url+“/login/”)
var elem = res.html().find(‘input[name=csrfmiddlewaretoken]’);
var val = elem.attr(‘value’);
var formBuildID = res.body.match(‘class=“form-horizontal”’)[1];
var formdata = {
username: ‘testuser’,
password: ‘foo’,
csrfmiddlewaretoken: val,
form_build_id: formBuildID,
};
let headers = { ‘Referer’: url+“/login/” };
http.post(url+“/base/auth/login/” , formdata, { headers: headers });
}
var res = http.get(url+“/test-app/”);
check(res, {
‘login succeeded’: res => res.url == ${url}/test-app/,
}) || fail(‘login failed’ + res.url);
sleep(1);
}

Hi, welcome :slight_smile:

Just to be sure: which k6 version are you using? (Output of k6 version)

Your example script seems OK to me, and using __ITER as a per-VU setup workaround is also OK.

Since you say the request in the first iteration succeeds and all others fail, assuming your auth system is cookie-based, this might be an issue with how k6 handles per-VU cookies.

Could you try inspecting the cookie jar and confirming if it’s empty for the iterations with failed requests?

As a workaround, consider saving the auth cookies manually and passing them to each request that needs it. Something like (untested):

import http from "k6/http";

const url=__ENV.URL

let jar;

export default function() {
  if (__ITER == 0) {
    var res = http.get(url+"/login/");
    var elem = res.html().find('input[name=csrfmiddlewaretoken]');
    var val = elem.attr('value');
    var formBuildID = res.body.match('class=“form-horizontal”')[1];
    var formdata = {
      username: 'testuser',
      password: 'foo',
      csrfmiddlewaretoken: val,
      form_build_id: formBuildID,
    };
    headers = { 'Referer': url+"/login/" };
    http.post(url+"/base/auth/login/" , formdata, { headers: headers });

    // Store the cookie jar for subsequent iterations
    jar = http.cookieJar();
  }
  var res = http.get(url+"/test-app/", { jar });
  check(res, {
    'login succeeded': res => res.url == ${url}/test-app/,
  }) || fail('login failed' + res.url);
  sleep(1);
}

HTH,

Ivan

1 Like

Hi,

thank you for you quick reply.

My k6 version is k6 v0.26.1 (dev build, go1.13, windows/amd64)

And you were right, the cookie jar was empty for the iterations with failed requests. Your advice for saving the cookies worked, thank you :smile:

No problem, glad it worked.

A better solution to this that I just stumbled upon is the K6_NO_COOKIES_RESET environment variable and script option. See the documentation.

By default k6 will reset all cookies between iterations, and running with K6_NO_COOKIES_RESET=true will disable this behavior, which is what you want, so you don’t have to manage cookies manually.