Changelog
All notable changes to @mongez/http are documented here. The format follows Keep a Changelog and this project follows Semantic Versioning.
[3.5.0] 2026-08-17 Security (2) · Added (1)
Security release. Both items below are reachable in ordinary browser and server usage; the
credential-redaction change alters the shape of HttpError.request, so read the note under
rawRequest if you log errors.
Security
-
Path traversal through
Resourceid / action segments.joinUrl(src/Http.ts) concatenated the resource path ontobaseURLverbatim, so an id of../../admin/usersproduced a request to a completely different endpoint than the one the resource represents. Ids routinely come from route params, query strings or API payloads, which makes this reachable without the calling code doing anything unusual — and it defeats any authorization the server enforces per-resource-path. The joined URL is now resolved withURLand confined to the configuredbaseURL: anything landing outside it throws rather than being silently rewritten, because a request that escaped its base is a bug in the caller, not something to quietly repoint. When nobaseURLis configured there is nothing to confine against, so instead the scheme is checked and unsafe ones (javascript:,data:, …) are blocked. -
Authorization/Cookievalues no longer leak throughHttpError.HttpError.requestcarried the outgoing request with its live headers, so the standardconsole.error(error)/logger.error({ error })/ Sentry-style capture wrote a bearer token or session cookie into logs — durably, and usually into a system with a much wider read audience than the app itself.HttpError.requestnow returns a copy with sensitive header values replaced by"[redacted]". (src/HttpError.ts,src/utils/redact.ts)
Added
HttpError.rawRequest— the outgoing request with its original, unredacted headers, for the narrow cases that genuinely need them (retry with the same credentials, request signing). It is a separate property precisely so that reaching for the secret is an explicit act and never happens by accident when something serializes the error.
[3.4.0] 2026-08-08 Fixed (1) · Added (3) · Changed (2) · Docs (1)
Server-side safety and Next.js compatibility. Browser behaviour is unchanged — every
default, key and option behaves exactly as before. Everything here applies off the browser
(typeof window === "undefined"): Next.js server components and SSR, Node services,
workers, and any multi-tenant process.
Fixed
- 🔴 GET deduplication could serve one user’s response to another on a server. The
dedup key is built from URL + query params before the outgoing request exists, so it
never included
Authorization, cookies or any per-request header. Two concurrentGET /mecalls carrying different bearer tokens shared one in-flight fetch and both callers received the first caller’s response — silent, timing-dependent, and invisible in normal testing. Deduplication now defaults to off outside a browser, where it was only ever an optimisation for a single user.config.dedupeKeywas not an escape hatch for this: its(url, params)signature never receives headers, so a credential-aware key could not be written from outside the package. Server-side users should upgrade.
Added
-
fetchInitonHttpConfigandRequestOptions— extraRequestInitfields forwarded verbatim to the underlyingfetch(). The init object was built from a fixed set of keys, so anything the library didn’t model was silently dropped — including Next.js’next: { revalidate, tags }. Tags attach per fetch, sorevalidateTag()after a mutation invalidated nothing; it looked correct in development (where caching is largely disabled) and failed in production. Framework-neutral: also covers Deno/Bun/ Cloudflare keys and whatever comes next.const http = new Http({ baseURL, fetchInit: { next: { revalidate: 60 } } });await http.get('/posts', { fetchInit: { next: { tags: ['posts'] } } });Caller-supplied keys are merged first so the library’s own fields win:
method,headers,bodyandsignalcan never be overridden (that would bypass interceptors and auth, or break cancellation and the timeout controller), andcredentials/mode/keepalive/redirect/fetchCachewin whenever they are actually configured. Applied at both fetch call sites — regular requests andstream(). -
dedupe?: booleanonHttpConfigandRequestOptions— turn GET deduplication on or off per instance or per call. Defaults totruein a browser,falseelsewhere. -
dedupeKey?: stringonRequestOptions— an explicit, identity-aware dedup key, mirroring the existingcacheKey. Required for every deduplicated GET whendedupeis enabled outside a browser; takes precedence overHttpConfig.dedupeKey.
Changed
- An enabled response cache now requires an identity-aware key outside a browser. The
cache is opt-in and stays completely inert when no driver is configured — but once
enabled on a server its default URL + params key had the same blind spot as the dedup
key. It now throws unless you pass a per-request
cacheKeyor acache.generateKey, naming the fix in the message. The built-in cache remains a client-side feature; on a server prefer the framework’s cache (Next.js’ data cache viafetchInit) or a store you key per request. - Opting into deduplication outside a browser throws without a per-request
dedupeKey. The library deliberately does not hash a guessed list of credential headers into the default key — it cannot know whether identity lives inAuthorization, a session cookie or a customX-Tenant-Id, and a guess would miss cases while looking safe. Failing loudly is the safer default.
Docs
- New
server-sideskill covering the browser-vs-server split end to end: dedup and cache defaults, identity-aware keys,fetchInitwith a fullrevalidateTagexample, and whysetCurrentHttpis module-level global state that must not be called per request on a server.overview,http-client,cachingandrecipesupdated to match and to cross-link it;setCurrentHttpcarries the same warning in its JSDoc.
[3.3.8] 2026-06-04 Changed (2)
Changed
- Skills now state the response-typing rule explicitly. The
http-clientskill gained a “Type the response — always pass a generic” section: every verb isget<T = unknown>(…), so omitting the type leavesdataasunknownanddata.first_namewon’t compile — always callhttp.get<User>(…)and narrow onerrorfirst. Mirrored intollms-full.txt. - Sharper skill triggers. The
overviewandhttp-clientskill descriptions now fire on making HTTP/API requests, replacing axios/fetch, and typing a response, so an agent loads them instead of reverse-engineering usage from source. No code/API changes.
[3.3.7] Changed (1)
Changed
llms.txtblurb now uses the>blockquote convention to match every other@mongez/*package, so the ecosystem index extracts it consistently. No code/API changes.
[3.3.6] Added (1)
Added
- This changelog. No code changes — the package remains the fetch-based HTTP client with the
{ data, error }result type, per-request cancellation, GET deduplication + retry, response caching, before/after interceptors, lifecycle events, and theResourceCRUD helper.
Version history prior to 3.3.6 is available via the git tags and GitHub releases on hassanzohdy/mongez-http. Future releases will be documented here.