Skip to content

Cookies

Harry Rabin edited this page Aug 27, 2022 · 4 revisions

PatchBay supports cookies right out of the box... with an important caveat.

A current limitation of the Fetch specification is that only a single Set-Cookie header can be set in a Response. While some runtimes have non-standard fixes for this, Bun sticks to the spec – so, to get around this limitation, PatchBay exposes a home-rolled and easy-to-use cookie API for you, which under the hood maintains a single cookie called __PBCookie containing JSON text of all the cookies you set.

If you bundle your static assets with PatchBay using the build script, the included webpack config will inject the necessary code to keep cookies working on the client completely transparently*, whether they are served by PatchBay or by a dedicated static asset host. See Building for more details on webpack config with PatchBay.

* There are two small limitations, which you are unlikely to run into: you cannot use a double pipe (||) in your cookies, and your total cookie space is limited to the maximum individual cookie size of 4093 bytes.

To make the magic happen, PatchBay uses a little package called cookie-interceptor, which only supports a single instance; so, on the off chance you need to use it for your app, the instance is exposed as window.CookieInterceptor.

For edge cases where bundling with PatchBay is not doable, this problem still has an easy fix. For a simple solution, just add the following snippet to the head of your HTML page:

<script type="text/javascript">
    window.updateFromPBCookie = (cookieString) => {
        let o = cookieString.split("; ")
            .find(o => o.startsWith("__PBCookie="));
        if (!o) return;
        const e = JSON.parse(o.replace("__PBCookie=", ""));
        for (const k in e) {
            let c = (k + "=" + e[k]).replaceAll("||", ";");
            console.log(c);
            document.cookie = c;
        }
        document.cookie = "__PBCookie=undefined; Expires=Sat, 01 Jan 2000 00:00:00 GMT"
    }
    updateFromPBCookie(document.cookie);
</script>

This will parse then remove __PBCookie on initial page load, and exposes a global function updateFromPBCookie() that you can call at any time to parse it again if you have reason to believe it was updated (e.g. in the .then() of a fetch that may set cookies). For a more "advanced" solution, you could implement cookie-interceptor yourself (it's pretty easy).

While all of the above should work without a hitch, there are potential "real" fixes in the works. You may be interested in this thread, a proposal for a sensible long-term solution, and also the experimental CookieChangeEvent API which would at least allow us to stop depending on cookie-interceptor.

With that out of the way, here's a reference on our cookie API:

init(req: PBRequest)

...

set(key: string, value: string, attributes?: CookieAttributes)

...