No results for

Powered byAlgolia

HTTP Cookies are used by web sites and apps to store pieces of stateful information on the user's device. A server tells the client, via a Set-Cookie HTTP header, what information it wants to be stored on the user's machine.

The user's browser will store the cookie data and associate it with the hostname of the server, and for each subsequent request to that hostname, it will include the stored cookie data in a Cookie header.

You can then control more specific rules for when cookie data should be sent or not, including limiting it to specific subdomains of the domain or a specific path. It's also possible to set an expiry date on the cookie and tell the browser only to send it over encrypted (SSL/TLS) connections.

Cookies with k6

For most intents and purposes k6 will transparently manage the receiving, storage and sending of cookies as described above, so that testing of your cookie-based web site or app will just work without you having to do anything special.

In some use cases, you might desire more control over the cookies. In k6 you have two options, either to directly manipulate HTTP headers, or use the more ergonomic cookie API. We will go through the latter below.

Setting simple cookies

To simulate that a cookie has previously been set by a browser and is now supposed to be included in a subsequent request to the server we include the cookie in the cookies request parameter:

1import http from 'k6/http';
2
3export default function () {
4 http.get('https://httpbin.org/cookies', {
5 cookies: {
6 my_cookie: 'hello world',
7 },
8 });
9}

This will only apply the cookie for the request in question, but will not be sent for any subsequent requests. If you want to do that you have to add the cookie to a cookie jar, and by default there's a per-VU cookie jar we can interact with to set and inspect cookies:

1import http from 'k6/http';
2
3export default function () {
4 const jar = http.cookieJar();
5 jar.set('https://httpbin.org/cookies', 'my_cookie', 'hello world');
6 http.get('https://httpbin.org/cookies');
7}

The per-VU cookie jar stores all cookies received from the server in a Set-Cookie header. You can also create "local cookie jars" that overrides the per-VU cookie jar, but more on that in a bit.

You can also specify that a cookie should be overridden if already part of the per-VU cookie jar:

1import http from 'k6/http';
2import { check } from 'k6';
3
4export default function () {
5 const jar = http.cookieJar();
6 jar.set('https://httpbin.org/cookies', 'my_cookie', 'hello world');
7
8 const cookies = {
9 my_cookie: {
10 value: 'hello world 2',
11 replace: true,
12 },
13 };
14
15 const res = http.get('https://httpbin.org/cookies', {
16 cookies,
17 });
18
19 check(res, {
20 'cookie has correct value': (r) => r.cookies.my_cookie[0].value === 'hello world 2',
21 });
22}

Accessing cookies

To see which cookies were set for a particular response we can look in the cookies property of the response object:

1import http from 'k6/http';
2import { check } from 'k6';
3
4export default function () {
5 const res = http.get('https://httpbin.org/cookies/set?my_cookie=hello%20world', { redirects: 0 });
6 check(res, {
7 "has cookie 'my_cookie'": (r) => r.cookies.my_cookie.length > 0,
8 'cookie has correct value': (r) => r.cookies.my_cookie[0].value === 'hello world',
9 });
10}

The response object's cookies property is a map where the key is the cookie name and the value is an array of response cookie objects (see below for description). It is an array to support multiple cookies having the same name (but different domain and/or path attributes), which is part of RFC6265.

A response cookie object contains the following properties:

PropertyTypeDescription
namestringthe name of the cookie
valuestringthe value of the cookie
domainstringdomain deciding what hostnames this cookie should be sent to
pathstringlimiting the cookie to only be sent if the path of the request matches this value
expiresstringwhen the cookie expires, this needs to be in the RFC1123 format looking like: Mon, 02 Jan 2006 15:04:05 MST
max_agenumberused for the same purpose as expires but defined as the number of seconds a cookie will be valid
securebooleanif true, the cookie will only be sent over an encrypted (SSL/TLS) connection
http_onlybooleanif true, the cookie would not be exposed to JavaScript in a browser environment

To see which cookies are set, and stored in the cookie jar, for a particular URL we can use the cookieForURL() method of the cookie jar object:

1import http from 'k6/http';
2import { check } from 'k6';
3
4export default function () {
5 const res = http.get('https://httpbin.org/cookies/set?my_cookie=hello%20world', { redirects: 0 });
6 const jar = http.cookieJar();
7 const cookies = jar.cookiesForURL('http://httpbin.org/');
8 check(res, {
9 "has cookie 'my_cookie'": (r) => cookies.my_cookie.length > 0,
10 'cookie has correct value': (r) => cookies.my_cookie[0] === 'hello world',
11 });
12}

The cookies object returned by the jar's cookiesForURL() method is a map where the key is the cookie name and the value is an array of cookie values (strings). It is an array to support multiple cookies having the same name (but different domain and/or path attributes), which is part of RFC6265.

Setting advanced cookies with attributes

To set cookies that more tightly controls the behavior of the cookie we must add the cookie to a cookie jar. An example:

1import http from 'k6/http';
2import { check } from 'k6';
3
4export default function () {
5 const jar = http.cookieJar();
6 jar.set('https://httpbin.org/cookies', 'my_cookie', 'hello world', {
7 domain: 'httpbin.org',
8 path: '/cookies',
9 secure: true,
10 max_age: 600,
11 });
12 const res = http.get('https://httpbin.org/cookies');
13 check(res, {
14 'has status 200': (r) => r.status === 200,
15 "has cookie 'my_cookie'": (r) => r.cookies.my_cookie[0] !== null,
16 'cookie has correct value': (r) => r.cookies.my_cookie[0].value == 'hello world',
17 });
18}

Besides the per-VU cookie jar you can also create local cookie jars that can override the per-VU cookie jar on a per-request basis. An example:

1import http from 'k6/http';
2import { check } from 'k6';
3
4export default function () {
5 const jar = new http.CookieJar();
6
7 // Add cookie to local jar
8 const cookieOptions = {
9 domain: 'httpbin.org',
10 path: '/cookies',
11 secure: true,
12 max_age: 600,
13 };
14 jar.set('https://httpbin.org/cookies', 'my_cookie', 'hello world', cookieOptions);
15
16 // Override per-VU jar with local jar for the following request
17 const res = http.get('https://httpbin.org/cookies', { jar });
18 check(res, {
19 'has status 200': (r) => r.status === 200,
20 "has cookie 'my_cookie'": (r) => r.cookies.my_cookie[0] !== null,
21 'cookie has correct value': (r) => r.cookies.my_cookie[0].value == 'hello world',
22 });
23}

Examples

1// Example showing two methods how to log all cookies (with attributes) from a HTTP response.
2import http from 'k6/http';
3
4function logCookie(c) {
5 // Here we log the name and value of the cookie along with additional attributes.
6 // For full list of attributes see:
7 // https://k6.io/docs/using-k6/cookies#properties-of-a-response-cookie-object
8 const output = `
9 ${c.name}: ${c.value}
10 tdomain: ${c.domain}
11 tpath: ${c.path}
12 texpires: ${c.expires}
13 thttpOnly: ${c.http_only}
14 `;
15 console.log(output);
16}
17export default function () {
18 const res = http.get('https://www.google.com/');
19
20 // Method 1: Use for-loop and check for non-inherited properties
21 for (const name in res.cookies) {
22 if (res.cookies.hasOwnProperty(name) !== undefined) {
23 logCookie(res.cookies[name][0]);
24 }
25 }
26
27 // Method 2: Use ES6 Map to loop over Object entries
28 new Map(Object.entries(res.cookies)).forEach((v, k) => {
29 logCookie(v[0]);
30 });
31}