Popsicle Cookie Jar Middleware
popsicle-cookie-jar is a middleware designed for the Popsicle HTTP client library, enabling cookie management in Node.js environments. It integrates with Popsicle's request lifecycle to automatically handle `Set-Cookie` headers from responses and attach `Cookie` headers to outgoing requests, mimicking browser-like cookie behavior. The current stable version is 1.0.1, which primarily features an update to the underlying `tough-cookie` library for security patches. Given its single-purpose nature and recent release history, its release cadence appears to be driven by bug fixes or critical dependency updates rather than frequent feature additions. Key differentiators include its tight integration with the Popsicle ecosystem and its reliance on `tough-cookie` for robust cookie specification adherence, providing a reliable, in-memory cookie store by default, with options for custom `CookieJar` instances.
Common errors
-
Error: Cannot find module 'servie'
cause The `servie` package is a peer dependency but has not been installed.fixInstall `servie`: `npm install servie`. -
TypeError: Cannot read properties of undefined (reading 'headers') at cookiesMiddleware
cause The `popsicle-cookie-jar` middleware expects the `context.request` object to exist, typically populated by a preceding middleware or the initial Popsicle client call.fixEnsure `popsicle-cookie-jar` is used within a valid Popsicle/Servie middleware chain where the `context.request` object is properly initialized before `cookies()` is called.
Warnings
- gotcha When using `cookies()` without an argument, an *in-memory* `CookieJar` is created. If you create multiple middleware instances this way (e.g., for different requests or clients), they will each have their own independent cookie stores, which might not be the desired behavior for persistent sessions. To share cookies, pass the same `CookieJar` instance.
- breaking The `popsicle` library (which this middleware extends) moved its core cookie functionality into `popsicle-cookie-jar` starting from `popsicle` v10.0.0. If you are upgrading `popsicle` from an older version, you must now explicitly install and include `popsicle-cookie-jar` middleware to retain cookie support.
- gotcha While `popsicle-cookie-jar` provides cookie functionality, it relies on `tough-cookie` for the actual cookie parsing and storage logic. Developers should be aware of `tough-cookie`'s API and limitations, especially concerning cookie domain matching and path rules, as well as any security advisories related to `tough-cookie` itself.
- deprecated As this package is middleware for `popsicle`, users should be aware that `popsicle` itself appears to be in a maintenance-only state with no recent feature development, suggesting this middleware will likely follow a similar pattern. Consider alternatives if active development and a robust feature roadmap are critical.
Install
-
npm install popsicle-cookie-jar -
yarn add popsicle-cookie-jar -
pnpm add popsicle-cookie-jar
Imports
- cookies
const cookies = require('popsicle-cookie-jar').cookies;import { cookies } from 'popsicle-cookie-jar'; - CookieJar
const { CookieJar } = require('popsicle-cookie-jar');import { CookieJar } from 'popsicle-cookie-jar'; - compose
import { compose } from 'popsicle-cookie-jar';import { compose } from 'servie';
Quickstart
import { cookies, CookieJar } from "popsicle-cookie-jar";
import { compose } from 'servie';
// Assume 'transport' is another middleware, e.g., from 'popsicle-transport-http'
// For demonstration, we'll create a dummy transport and Popsicle client.
interface Context {
request: { url: string; headers?: Record<string, string>; };
response?: { status: number; headers: Record<string, string>; body?: any; };
}
async function dummyTransport(ctx: Context, next: () => Promise<void>) {
console.log(`Sending request to: ${ctx.request.url}`);
ctx.response = {
status: 200,
headers: { 'Set-Cookie': 'session=abc; Path=/; HttpOnly' },
body: 'Hello World'
};
await next();
}
// Create an in-memory cookie jar
const myCookieJar = new CookieJar();
// Compose the middleware with a custom cookie jar
const middlewareWithJar = compose([cookies(myCookieJar), dummyTransport]);
// Or let it create a default in-memory jar
const middlewareDefault = compose([cookies(), dummyTransport]);
async function makeRequest(middleware: (ctx: Context, next: () => Promise<void>) => Promise<void>) {
const ctx: Context = { request: { url: 'http://example.com/login' } };
await middleware(ctx, async () => {}); // No further middleware after transport
console.log('Response headers:', ctx.response?.headers);
console.log('Cookies in jar (after request):', myCookieJar.getCookiesSync('http://example.com/login'));
}
console.log('--- Using custom CookieJar ---');
await makeRequest(middlewareWithJar);
console.log('\n--- Using default (new) CookieJar instance for separate calls ---');
// Each call to cookies() without an argument creates a new jar
await makeRequest(compose([cookies(), dummyTransport]));