Cookies with duplicated name - js-cookie/js-cookie GitHub Wiki

Test http server:

// server.mjs
import http from 'http'

const host = 'localhost'
const port = 3000

http
  .createServer((req, res) => {
    if (req.url.endsWith('/test')) {
      res.setHeader('Set-Cookie', 'foo=nested; Path=/test')
    } else {
      res.setHeader('Set-Cookie', 'foo=top; Path=/')
    }
    res.writeHead(200)
    res.end('<p><a href="/test">Go to /test</a></p><p id="cookie-p"></p><script>document.getElementById("cookie-p").innerText = document.cookie;</script>')
  })
  .listen(port, host, () => {
    console.log(`Server is running on http://${host}:${port}`)
  })

In the browser visit /, and /test.

Cookie string:

Browser document.cookie
Firefox 109.0.1 foo=nested; foo=top
Chrome 113.0.5672.126 foo=nested; foo=top
Safari 16.4 foo=nested; foo=top
Edge 125.0.2535.67 foo=nested; foo=top
Opera One 110.0.5130.49 foo=nested; foo=top
Chrome for Android 125.0.6422.112 foo=nested; foo=top
Opera Mobile 82.3.4342.79590 foo=nested; foo=top
Opera Mini 81.0.2254.72209 foo=nested; foo=top
Firefox for Android 126.0.1 foo=nested; foo=top

New Test Server

// server.mjs
import http from 'http'

const host = 'localhost'
const port = 3000

/*
To use the tests follow these steps (Unless a test says otherwise)

Click "Go to {name}"
Click "Go to Nested"
See "Results"
*/
const COOKIE_SET = [
    {
        name: "path-test",        // Also part of the URL
        value: "root",            // non-nested value
        nested_value: "toor",     // nested value
        attrs: {}                 // Attributes for the cookie (also supports functions)
    },
    {
        /*
        Process for this test:
        Click "Go to expire-test"
        Click "Go to Nested"
        See "Results"

        You may want to double check:
        Click "Go to expire-test"
        Manually modify URL to "/expire-test/nested/dontTouchCookies"
        See "Results"
        */
        name: "expire-test",
        value: "root",
        nested_value: "toor",
        attrs: {
            expires: function() {
                var date = new Date();
                date.setTime(date.getTime() + 5*60*1000);
                return date.toGMTString();
            }
        }
    },
    {
        name: "big-root-test",
        value: "SomeValueBiggerThanTheNestedOne",
        nested_value: "nested",
        attrs: {}
    },
    {
        name: "big-nested-test",
        value: "root",
        nested_value: "SomeValueBiggerThanTheRootOne",
        attrs: {}
    },
    {
        /*
        Process for this test:
        Click "Go to max-age-test"
        Click "Go to Nested"
        See "Results"

        You may want to double check:
        Click "Go to max-age-test"
        Manually modify URL to "/max-age-test/nested/dontTouchCookies"
        See "Results"
        */
        name: "max-age-test",
        value: "root",
        nested_value: "toor",
        attrs: {"Max-Age": 5*60}
    },
    {
        name: "root-samesite-test",
        value: "root",
        nested_value: "toor",
        attrs: {SameSite: function(v) { return v === "root" ? "Strict" : "Lax"; }}
    },
    {
        name: "nested-samesite-test",
        value: "root",
        nested_value: "toor",
        attrs: {SameSite: function(v) { return v === "toor" ? "Strict" : "Lax"; }}
    }
]

function createCookie(name, value, attrs) {
    var cookie = `${name}=${value};`;
    for (const k in attrs) {
        if (Object.hasOwnProperty.call(attrs, k)) {
            const v = attrs[k];
            if(v instanceof Function) { cookie += ` ${k}=${v(value)};`; }
            else { cookie += ` ${k}=${v};`; }
        }
    }
    return cookie;
}

function SetTestCookies(server, path) {
    const isNested = path.endsWith("/nested");
    for (let index = 0; index < COOKIE_SET.length; index++) {
        const cookie_data = COOKIE_SET[index];
        if(path.includes(cookie_data.name)) {
            var nattrs = cookie_data.attrs;
            nattrs.Path = path;
            server.setHeader('Set-Cookie', createCookie(cookie_data.name, isNested ? cookie_data.nested_value : cookie_data.value, nattrs));
        }
    }
}

function createHTML() {
    var html = '<p><a href="./nested">Go to Nested</a></p>';
    html += '<p><a href="./dontTouchCookies">Go to DontTouchCookies</a></p>';

    html += '<p>Tests</p>'
    for (let i = 0; i < COOKIE_SET.length; i++) {
        const cookie_data = COOKIE_SET[i];
        html += `<p><a href="/${cookie_data.name}/">Go to ${cookie_data.name}</a></p>`
    }

    html += '<p>Results</p>';
    html += '<p id="cookie-p"></p>';
    html += '<script>document.getElementById("cookie-p").innerText = document.cookie;</script>';
    return html;
}

http
  .createServer((req, res) => {
      if(!req.url.startsWith("/favicon")) {
        console.log(req.url);
        if(!req.url.endsWith("/dontTouchCookies")) {
            SetTestCookies(res, req.url);
        }
    }

    res.writeHead(200)
    res.end(createHTML());
  })
  .listen(port, host, () => {
    console.log(`Server is running on http://${host}:${port}`)
  })

This server contains multiple test cases where one can use to test a browser. You can create your own test cases for attributes or combinations that were not tested.

A test is automatically created for an entry in the COOKIE_SET. The attributes array can have functions, as values, where the first parameter is the value/nested_value that will be sent to the browser.

NOTE: path-test is basically the old test.

Browser Version path-test expire-test max-age-test
Chrome 125.0.6422.113 path-test=toor; path-test=root expire-test=toor; expire-test=root max-age-test=toor; max-age-test=root
Firefox 125.0.3 path-test=toor; path-test=root expire-test=toor; expire-test=root max-age-test=toor; max-age-test=root
Edge 125.0.2535.67 path-test=toor; path-test=root expire-test=toor; expire-test=root max-age-test=toor; max-age-test=root
Opera 110.0.5130.66 path-test=toor; path-test=root expire-test=toor; expire-test=root max-age-test=toor; max-age-test=root
Browser Version big-root-test big-nested-test
Chrome 125.0.6422.113 big-root-test=nested; big-root-test=SomeValueBiggerThanTheNestedOne big-nested-test=SomeValueBiggerThanTheRootOne; big-nested-test=root
Firefox 125.0.3 big-root-test=nested; big-root-test=SomeValueBiggerThanTheNestedOne big-nested-test=SomeValueBiggerThanTheRootOne; big-nested-test=root
Edge 125.0.2535.67 big-root-test=nested; big-root-test=SomeValueBiggerThanTheNestedOne big-nested-test=SomeValueBiggerThanTheRootOne; big-nested-test=root
Opera 110.0.5130.66 big-root-test=nested; big-root-test=SomeValueBiggerThanTheNestedOne big-nested-test=SomeValueBiggerThanTheRootOne; big-nested-test=root
Browser Version root-samesite-test nested-samesite-test
Chrome 125.0.6422.113 root-samesite-test=toor; root-samesite-test=root nested-samesite-test=toor; nested-samesite-test=root
Firefox 125.0.3 root-samesite-test=toor; root-samesite-test=root nested-samesite-test=toor; nested-samesite-test=root
Edge 125.0.2535.67 root-samesite-test=toor; root-samesite-test=root nested-samesite-test=toor; nested-samesite-test=root
Opera 110.0.5130.66 root-samesite-test=toor; root-samesite-test=root nested-samesite-test=toor; nested-samesite-test=root
⚠️ **GitHub.com Fallback** ⚠️