typescript 64 lines · 9 steps

Parsing a Set-Cookie header in TypeScript

Split a raw Set-Cookie string into a typed object by handling the name/value pair first, then each attribute.

Explained by highlit
1interface ParsedCookie {
2 name: string;
3 value: string;
4 domain?: string;
5 path?: string;
6 expires?: Date;
7 maxAge?: number;
8 secure: boolean;
9 httpOnly: boolean;
10 sameSite?: "Strict" | "Lax" | "None";
11}
12 
13export function parseSetCookie(header: string): ParsedCookie {
14 const [pair, ...attrs] = header.split(";");
15 const eq = pair.indexOf("=");
16 if (eq === -1) throw new Error(`Invalid cookie pair: ${pair}`);
17 
18 const cookie: ParsedCookie = {
19 name: pair.slice(0, eq).trim(),
20 value: decodeURIComponent(pair.slice(eq + 1).trim()),
21 secure: false,
22 httpOnly: false,
23 };
24 
25 for (const attr of attrs) {
26 const idx = attr.indexOf("=");
27 const key = (idx === -1 ? attr : attr.slice(0, idx)).trim().toLowerCase();
28 const raw = idx === -1 ? "" : attr.slice(idx + 1).trim();
29 
30 switch (key) {
31 case "domain":
32 cookie.domain = raw.replace(/^\./, "");
33 break;
34 case "path":
35 cookie.path = raw;
36 break;
37 case "expires": {
38 const date = new Date(raw);
39 if (!Number.isNaN(date.getTime())) cookie.expires = date;
40 break;
41 }
42 case "max-age": {
43 const n = Number(raw);
44 if (Number.isInteger(n)) cookie.maxAge = n;
45 break;
46 }
47 case "secure":
48 cookie.secure = true;
49 break;
50 case "httponly":
51 cookie.httpOnly = true;
52 break;
53 case "samesite": {
54 const v = raw.toLowerCase();
55 if (v === "strict") cookie.sameSite = "Strict";
56 else if (v === "lax") cookie.sameSite = "Lax";
57 else if (v === "none") cookie.sameSite = "None";
58 break;
59 }
60 }
61 }
62 
63 return cookie;
64}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Splitting on a delimiter and destructuring the head separates the mandatory pair from optional attributes cleanly.
  2. 2Normalizing keys to lowercase lets a single switch handle case-insensitive HTTP attribute names.
  3. 3Validating parsed values before assignment keeps malformed dates and numbers out of the typed result.

Related explainers

typescript
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
import localeFrExtra from '@angular/common/locales/extra/fr';
import localeDe from '@angular/common/locales/de';

Locale-aware bootstrapping in Angular

i18n localization dependency-injection
Intermediate 8 steps
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
 

Validating env config at boot in NestJS

configuration schema-validation environment-variables
Intermediate 8 steps
ruby
class UserAgentParser
  BROWSERS = [
    [/Edg\/([\d.]+)/, "Edge"],
    [/OPR\/([\d.]+)/, "Opera"],

Parsing user-agent strings in Ruby

regex pattern-matching lookup-tables
Intermediate 8 steps
javascript
function evaluate(expression) {
  const tokens = tokenize(expression);
  let pos = 0;
 

Building a recursive descent calculator

parsing recursion operator-precedence
Intermediate 8 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { InjectRepository } from '@nestjs/typeorm';

A cache-aside country lookup in NestJS

cache-aside dependency-injection batch-lookup
Intermediate 8 steps
typescript
import { Injectable, effect, signal, computed } from '@angular/core';
 
interface Preferences {
  theme: 'light' | 'dark';

A signal-based preferences store in Angular

signals state-management persistence
Intermediate 7 steps

Share this explainer

Here's the card — post it anywhere.

Parsing a Set-Cookie header in TypeScript — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code