Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
24e9f60
docs: fix request typo in readme (#404)
Aug 25, 2023
7df9776
chore: migrate to pnpm (#407)
kettanaito Aug 28, 2023
0adedc5
fix: set "X-Request-Id" header in XMLHttpRequest only in Node.js (#397)
avivasyuta Aug 28, 2023
d5f1d0d
test(fetch): add "bodyUsed" compliance (#403)
kettanaito Aug 30, 2023
93f3e83
feat: remove "headers-polyfill" dependency (#408)
kettanaito Aug 30, 2023
d60e97f
chore: set "Access-Control-Allow-Credentials" when testing xhr creden…
kettanaito Aug 30, 2023
721376f
chore: upgrade "@ossjs/release"
kettanaito Aug 30, 2023
c885f2e
chore(release): set explicit npm registry url
kettanaito Aug 30, 2023
ca14782
chore(release): v0.24.0
kettanaito Aug 30, 2023
bfac018
fix: package exports for "RemoteHttpInterceptor" (#410)
Benehiko Aug 30, 2023
d4257a5
fix(xhr): handle responses without body correctly (#411)
avivasyuta Sep 2, 2023
33dcbe0
fix(fetch): respect "abort" event on the request signal (#394)
JesusTheHun Sep 2, 2023
593814c
chore(release): v0.24.1
kettanaito Sep 2, 2023
52bb291
chore: migrate to @ossjs/release 0.7.2 (#412)
kettanaito Sep 2, 2023
76a502b
feat: support "Response.error()" for mocking network errors (#414)
kettanaito Sep 7, 2023
9136f96
chore: install playwright browsers on release
kettanaito Sep 7, 2023
cd39c9a
chore(release): v0.25.0
kettanaito Sep 7, 2023
4687327
fix: update @open-draft/deferred-promise to 2.2.0 (esm) (#415)
kettanaito Sep 7, 2023
5d4e035
chore: use "NODE_AUTH_TOKEN" env variable for pnpm publishing (#417)
kettanaito Sep 7, 2023
45df468
chore(release): v0.25.1
kettanaito Sep 7, 2023
15f1167
chore: use npx to install playwright on ci (#428)
kettanaito Sep 18, 2023
e0dc5a8
chore: set "moduleResolution" to "NodeNext" (#424)
kettanaito Sep 18, 2023
04152ed
fix: add "once", "off", and "removeAllListeners" to the Interceptor c…
kettanaito Sep 18, 2023
cf4e228
fix(Interceptor): wrap the "once" event listener, ditch "untilIdle" P…
kettanaito Sep 20, 2023
7c965da
chore(release): use "npx" to install playwright browsers
kettanaito Sep 20, 2023
1b6b058
chore(release): v0.25.2
kettanaito Sep 20, 2023
e73e809
fix: upgrade "strict-event-emitter" to 0.5.1 (#434)
kettanaito Sep 21, 2023
217c6e9
fix(ClientRequest): ignore request destroyed state when responding wi…
kettanaito Sep 21, 2023
db08d08
fix(ClientRequest): ignore message body for responses without body (#…
kettanaito Sep 21, 2023
b8bce89
chore(release): v0.25.3
kettanaito Sep 21, 2023
8d04c08
fix(ClientRequest): support the "auth" option (#440)
Sep 22, 2023
8fee310
chore(release): v0.25.4
kettanaito Sep 22, 2023
3ae4b4c
fix(ClientRequest): respect "options.path" over "url.pathname" (#441)
Sep 26, 2023
01aa28d
fix(ClientRequest): support empty "username" and "password" basic aut…
Sep 26, 2023
c91d67f
chore(release): v0.25.5
kettanaito Sep 26, 2023
04415fc
fix(ClientRequest): support falsy request headers (#450)
Sep 27, 2023
2e98a71
chore(release): v0.25.6
kettanaito Sep 27, 2023
fa5a34a
fix(ClientRequest): preserve headers casing on mocked responses (#463)
Oct 4, 2023
1c5fab5
fix(ClientRequest): suppress "ENETUNREACH" socket error (#454)
Oct 4, 2023
fce2879
chore(ClientRequest): add internal "isRequestSent" flag (#466)
kettanaito Oct 4, 2023
469fd9c
fix(ClientRequest): suppress the "EHOSTUNREACH" connection error (#467)
kettanaito Oct 4, 2023
198533a
fix(ClientRequest): support throwing custom errors in request listene…
Oct 6, 2023
65b7ac1
fix(ClientRequest): support "http.request()" and "http.get()" without…
kettanaito Oct 7, 2023
5946f54
chore(release): use node v18.14.x for release (#469)
kettanaito Oct 8, 2023
3258f5c
chore(release): v0.25.7
kettanaito Oct 8, 2023
fb8a400
fix(XMLHttpRequest): prevent invalid listener name access (#472)
hpohlmeyer Nov 7, 2023
1f04d10
chore(release): v0.25.8
kettanaito Nov 7, 2023
4e73ed9
fix(xhr): allow setters for non-existing properties (#477)
kettanaito Nov 8, 2023
9b9af96
chore: use node v18.14.2 in .nvmrc (#480)
kettanaito Nov 8, 2023
52606f7
chore(release): v0.25.9
kettanaito Nov 8, 2023
5fa1218
fix: support miniflare by checking "Response.type" access (#479)
mattcosta7 Nov 8, 2023
e868e46
chore(release): v0.25.10
kettanaito Nov 8, 2023
da1cc71
fix(xhr): support environments with missing "location" (#482)
kettanaito Nov 9, 2023
d203c26
chore(release): v0.25.11
kettanaito Nov 9, 2023
95df373
feat: allow "CONNECT" request method
kettanaito Nov 9, 2023
be7838f
wip: socket-based interception
kettanaito Nov 11, 2023
0ee564c
feat: continue socket based interception with claude
luisAzcuaga Sep 15, 2025
bf5f568
chore: add logging to debug connect method
luisAzcuaga Sep 15, 2025
158eb2c
chore: remove debug logging for CONNECT requests
luisAzcuaga Sep 17, 2025
00ed0a1
fix: add safe destroy check for proxy agents in terminate method
luisAzcuaga Sep 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
name: ci

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
matrix:
node: [18.8.0]
node: [18.14]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}

- uses: pnpm/action-setup@v2
with:
version: 7.12

- name: Install dependencies
run: yarn install --frozen-lockfile
run: pnpm install

- name: Unit tests
run: yarn test:unit
run: pnpm test:unit

- name: Build
run: yarn build
run: pnpm build

- name: Node.js tests
run: yarn test:integration:node
run: pnpm test:node

- name: Install Playwright browsers
run: npx playwright install

- name: Browser tests
run: yarn test:integration:browser
run: pnpm test:browser
29 changes: 18 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,35 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.GH_ADMIN_TOKEN }}

- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.8.0
always-auth: true
cache: yarn

- name: Setup Git
run: |
git config --local user.name "Artem Zakharchenko"
git config --local user.email "kettanaito@gmail.com"

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18.14
always-auth: true
registry-url: https://registry.npmjs.org

- uses: pnpm/action-setup@v2
with:
version: 7.12

- name: Install dependencies
run: yarn install --frozen-lockfile
run: pnpm install

- name: Install Playwright browsers
run: npx playwright install

- name: Release
run: yarn release
run: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GH_ADMIN_TOKEN }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18.8.0
v18.14.2
74 changes: 74 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is `@mswjs/interceptors`, a low-level HTTP/HTTPS/XHR/fetch request interception library. It extends native Node.js modules and browser APIs using class extensions rather than module rewrites, allowing for more resilient request interception.

## Commands

### Building
- `pnpm build` - Clean and build the project for production (outputs to `lib/` directory)
- `pnpm start` - Start TypeScript compiler in watch mode
- `pnpm clean` - Remove built files from `lib/` directory

### Testing
- `pnpm test` - Run all tests (unit + integration)
- `pnpm test:unit` - Run unit tests only (using Vitest)
- `pnpm test:integration` - Run integration tests (both Node.js and browser)
- `pnpm test:node` - Run Node.js integration tests (using Vitest with custom config)
- `pnpm test:browser` - Run browser integration tests (using Playwright)

### Development
- `pnpm prepare` - Initialize git hooks
- `pnpm release` - Publish a release
- `pnpm prepublishOnly` - Build and test before publishing (runs automatically on publish)

## Architecture

### Core Components

- **`Interceptor`** - Abstract base class for all interceptors with `apply()`, `on()`, and `dispose()` methods
- **`BatchInterceptor`** - Combines multiple interceptors and manages them as a group
- **`RemoteHttpInterceptor`** - Enables request interception in child processes with parent process resolution

### Interceptor Types

The library provides specific interceptors for different request sources:
- **`ClientRequestInterceptor`** - Intercepts `http.get`/`http.request` calls (Node.js only)
- **`XMLHttpRequestInterceptor`** - Intercepts `XMLHttpRequest` (both Node.js and browser)
- **`FetchInterceptor`** - Intercepts `fetch` calls (both Node.js and browser)

### Build System

- **Dual Platform Builds**: Uses `tsup` to build separate bundles for Node.js (`lib/node/`) and browser (`lib/browser/`)
- **Multiple Formats**: Outputs both CommonJS (`.js`) and ES modules (`.mjs`) with TypeScript declarations (`.d.ts`)
- **Package Exports**: Complex export map in `package.json` provides platform-specific entry points

### Request/Response Flow

1. All intercepted requests are normalized to Fetch API `Request` instances
2. Responses use Fetch API `Response` instances as the common format
3. The library handles coercion between different request/response formats (e.g., `http.OutgoingMessage` for `http.ClientRequest`)

### Event System

All interceptors emit:
- `request` - When a request is dispatched (allows inspection and mocking)
- `response` - When any request receives a response (read-only observation)

### Testing Strategy

- **Unit Tests**: Located in `src/` alongside source files (`.test.ts` files), use Vitest
- **Integration Tests**: Located in `test/` directory
- Node.js integration tests use Vitest with custom config
- Browser integration tests use Playwright
- Tests are organized by interceptor type and feature

### Key Directories

- `src/interceptors/` - Individual interceptor implementations
- `src/presets/` - Pre-configured interceptor combinations for Node.js and browser
- `src/utils/` - Utility functions for request/response handling
- `test/` - Integration tests with separate configurations for different environments
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ All HTTP request interceptors emit a "request" event. In the listener to this ev
> There are many ways to describe a request in Node.js but this library coerces different request definitions to a single specification-compliant `Request` instance to make the handling consistent.

```js
interceptor.on('reqest', ({ request, requestId }) => {
interceptor.on('request', ({ request, requestId }) => {
console.log(request.method, request.url)
})
```
Expand Down
3 changes: 0 additions & 3 deletions ossjs.release.config.js

This file was deleted.

40 changes: 21 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mswjs/interceptors",
"description": "Low-level HTTP/HTTPS/XHR/fetch request interception library.",
"version": "0.23.0",
"version": "0.25.11",
"main": "./lib/node/index.js",
"module": "./lib/node/index.mjs",
"types": "./lib/node/index.d.ts",
Expand Down Expand Up @@ -45,10 +45,10 @@
},
"./RemoteHttpInterceptor": {
"browser": null,
"types": "./lib/node/interceptors/RemoteHttpInterceptor.d.ts",
"require": "./lib/node/interceptors/RemoteHttpInterceptor.js",
"import": "./lib/node/interceptors/RemoteHttpInterceptor.mjs",
"default": "./lib/node/interceptors/RemoteHttpInterceptor.js"
"types": "./lib/node/RemoteHttpInterceptor.d.ts",
"require": "./lib/node/RemoteHttpInterceptor.js",
"import": "./lib/node/RemoteHttpInterceptor.mjs",
"default": "./lib/node/RemoteHttpInterceptor.js"
},
"./presets/node": {
"browser": null,
Expand All @@ -73,16 +73,16 @@
},
"scripts": {
"start": "tsc --build -w",
"test": "yarn test:unit && yarn test:integration",
"test": "pnpm test:unit && pnpm test:integration",
"test:unit": "vitest run",
"test:integration": "yarn test:integration:node && yarn test:integration:browser",
"test:integration:node": "vitest run -c test/vitest.config.js",
"test:integration:browser": "playwright test -c test/playwright.config.ts",
"test:integration": "pnpm test:node && pnpm test:browser",
"test:node": "vitest run -c test/vitest.config.js",
"test:browser": "pnpm playwright test -c test/playwright.config.ts",
"clean": "rimraf lib",
"build": "yarn clean && cross-env NODE_ENV=production tsup --splitting",
"prepare": "yarn simple-git-hooks init",
"build": "pnpm clean && cross-env NODE_ENV=production tsup --splitting",
"prepare": "pnpm simple-git-hooks init",
"release": "release publish",
"prepublishOnly": "yarn build && yarn test"
"prepublishOnly": "pnpm build && pnpm test"
},
"files": [
"lib",
Expand All @@ -101,8 +101,8 @@
"@commitlint/cli": "^16.0.2",
"@commitlint/config-conventional": "^16.0.0",
"@open-draft/test-server": "^0.5.1",
"@ossjs/release": "^0.4.0",
"@playwright/test": "^1.31.1",
"@ossjs/release": "^0.7.2",
"@playwright/test": "^1.37.1",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-rate-limit": "^6.0.0",
Expand All @@ -111,7 +111,7 @@
"@types/node": "^16.11.26",
"@types/node-fetch": "2.5.12",
"@types/supertest": "^2.0.11",
"axios": "^0.24.0",
"axios": "^1.6.0",
"body-parser": "^1.19.0",
"commitizen": "^4.2.4",
"cors": "^2.8.5",
Expand All @@ -121,9 +121,10 @@
"express-rate-limit": "^6.3.0",
"follow-redirects": "^1.15.1",
"got": "^11.8.3",
"happy-dom": "^12.10.3",
"hpagent": "^1.2.0",
"jest": "^27.4.3",
"node-fetch": "2.6.7",
"playwright": "^1.31.1",
"rimraf": "^3.0.2",
"simple-git-hooks": "^2.7.0",
"superagent": "^6.1.0",
Expand All @@ -132,17 +133,18 @@
"tsup": "^6.5.0",
"typescript": "^4.9.4",
"vitest": "^0.28.5",
"vitest-environment-miniflare": "^2.14.1",
"wait-for-expect": "^3.0.2",
"web-encoding": "^1.1.5",
"webpack-http-server": "^0.5.0"
},
"dependencies": {
"@open-draft/deferred-promise": "^2.1.0",
"@open-draft/deferred-promise": "^2.2.0",
"@open-draft/logger": "^0.3.0",
"@open-draft/until": "^2.0.0",
"headers-polyfill": "^3.1.0",
"is-node-process": "^1.2.0",
"outvariant": "^1.2.1",
"strict-event-emitter": "^0.5.0"
"strict-event-emitter": "^0.5.1"
},
"resolutions": {
"memfs": "^3.4.13"
Expand Down
Loading