{"_id":"95thinterceptors","name":"95thinterceptors","dist-tags":{"latest":"0.17.0"},"versions":{"0.17.0":{"name":"95thinterceptors","description":"Low-level HTTP/HTTPS/XHR/fetch request interception library.","version":"0.17.0","main":"lib/index.js","typings":"lib/index.d.ts","author":{"name":"Artem Zakharchenko"},"license":"MIT","engines":{"node":">=14"},"scripts":{"start":"tsc --build -w","test":"yarn test:internal && yarn test:integration","test:internal":"jest","test:integration":"yarn test:integration:node && yarn test:integration:browser","test:integration:node":"jest --c test/jest.node.config.js --runInBand","test:integration:browser":"jest --c test/jest.browser.config.js","clean":"rimraf lib","build":"yarn clean && tsc --build","prepare":"yarn simple-git-hooks init","release":"release publish","prepublishOnly":"yarn build && yarn test"},"repository":{"type":"git","url":"https://github.com/mswjs/interceptors"},"devDependencies":{"@commitlint/cli":"^16.0.2","@commitlint/config-conventional":"^16.0.0","@open-draft/test-server":"^0.4.2","@ossjs/release":"^0.3.0","@types/cors":"^2.8.12","@types/express":"^4.17.13","@types/express-rate-limit":"^6.0.0","@types/follow-redirects":"^1.14.1","@types/jest":"^27.0.3","@types/node":"^16.11.26","@types/node-fetch":"2.5.12","@types/supertest":"^2.0.11","@types/xmldom":"^0.1.31","axios":"^0.24.0","body-parser":"^1.19.0","commitizen":"^4.2.4","cors":"^2.8.5","cz-conventional-changelog":"3.3.0","express":"^4.17.3","express-rate-limit":"^6.3.0","follow-redirects":"^1.15.1","got":"^11.8.3","jest":"^27.4.3","node-fetch":"2.6.7","page-with":"^0.5.1","rimraf":"^3.0.2","simple-git-hooks":"^2.7.0","superagent":"^6.1.0","supertest":"^6.1.6","ts-jest":"^27.1.1","typescript":"4.3.5","wait-for-expect":"^3.0.2"},"dependencies":{"@open-draft/until":"^1.0.3","@xmldom/xmldom":"^0.7.5","debug":"^4.3.3","headers-polyfill":"^3.0.4","outvariant":"^1.2.1","strict-event-emitter":"^0.2.4"},"keywords":["request","intercept","http","https","xmlhttprequest","xhr","fetch","low-level","mock"],"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}},"licenseText":"MIT License\n\nCopyright (c) 2018–present Artem Zakharchenko\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"95thinterceptors@0.17.0","dist":{"shasum":"4d2c8d8f1498e2f120db718c72ac340f52e50314","integrity":"sha512-j2qYprWVz2W21LiB95XuL4PEd5PgmvxHo/Vpt7r49Iei8mk1S4AsDLfsAi9jScIcQvmk/lmoB2qpPmA77sy/4A==","tarball":"https://registry.npmjs.org/95thinterceptors/-/95thinterceptors-0.17.0.tgz","fileCount":188,"unpackedSize":376691,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCNNvZIWv/yM8u/NFkLAPuztGdeZ1LCZ+Tfmef+2jv6AIhAKeJs+rIB3W1PMdnlYjAITuFmYmFPfowwCwRQFtyy5bj"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJinM0vACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqZuBAAhSJ9UrmF3HXHPMTl+GSmIrk7DxKXwckrLeBtqu99sBrBRKie\r\nKGiGe0VMoxjz3gibWI1Wq6UNAWtioTYiyCnnCm4N4b7VRzBrfNhoggTTXTTt\r\nzwsaT06pFxy5aQNJIFTPfpczLR4oRSE2bUL9gKB28hw6QXiEEMMLHdr2FOPN\r\nYBP/vs0eOMT3gwdG70Nq1yJb0tBOn3/kQH4P/J3GyPRRAZwWQBB2ov5z9hc2\r\ny6F3hEpIat19rzvS7aUqhIl6VtTlMAlape15kUutHkmk3dhqU6oHxp8bPfhd\r\nykg3nDi+9jhqlm16yfFh06P9vZrP7MAmHmfL6oxzVoPcgWzX1DkFkLgzsjg/\r\nv8TlyevvenjoCbxI9tLv9xtw85iSGjj1pEIJCy2tz0z+K8ptISxVu6JlVLfk\r\nEaNjX5T6sJS98R1kxoj7TUhTTyF5Ae0Q+bgE356Y819jeNCtyIMEpuyte97W\r\n4NC8wLOjcN7tP9+kBOoMYGDC7PyX4pD7oLzJsmjEBttVn7mQdrQ8j8CsaT2h\r\n5q77LplRhEX+4Yn/9Ymhy3GRWdpTP/e6UHN+Vv6AMvQWe0/7bdL2CQV9tJji\r\nq6qSrHoLmnSK/RkwYXcMWRapv9i/8o7pvSLj/S4YJOqyMXrMttOzOdFVJaAX\r\nxgIrb1sKSdRp9Ln14kg0S0Q+cg/ysyLLiRo=\r\n=Lewk\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"vargwin","email":"user.gurwinder@gmail.com"},"directories":{},"maintainers":[{"name":"vargwin","email":"user.gurwinder@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/95thinterceptors_0.17.0_1654443311676_0.7677648276207858"},"_hasShrinkwrap":false}},"time":{"created":"2022-06-05T15:35:11.675Z","0.17.0":"2022-06-05T15:35:11.878Z","modified":"2022-06-05T15:35:12.014Z"},"maintainers":[{"name":"vargwin","email":"user.gurwinder@gmail.com"}],"description":"Low-level HTTP/HTTPS/XHR/fetch request interception library.","keywords":["request","intercept","http","https","xmlhttprequest","xhr","fetch","low-level","mock"],"repository":{"type":"git","url":"https://github.com/mswjs/interceptors"},"author":{"name":"Artem Zakharchenko"},"license":"MIT","readme":"[![Latest version](https://img.shields.io/npm/v/@mswjs/interceptors.svg)](https://www.npmjs.com/package/@mswjs/interceptors)\n\n# `@mswjs/interceptors`\n\nLow-level HTTP/HTTPS/XHR/fetch request interception library.\n\n**Intercepts any requests issued by:**\n\n- `http.get`/`http.request`\n- `https.get`/`https.request`\n- `XMLHttpRequest`\n- `fetch`\n- Any third-party libraries that use the modules above (i.e. `request`, `node-fetch`, `supertest`, etc.)\n\n## Motivation\n\nWhile there are a lot of network communication mocking libraries, they tend to use request interception as an implementation detail, giving you a high-level API that includes request matching, timeouts, retries, and so forth.\n\nThis library is a strip-to-bone implementation that provides as little abstraction as possible to execute arbitrary logic upon any request. It's primarily designed as an underlying component for high-level API mocking solutions such as [Mock Service Worker](https://github.com/mswjs/msw).\n\n### How is this library different?\n\nA traditional API mocking implementation in Node.js looks roughly like this:\n\n```js\nimport http from 'http'\n\nfunction applyMock() {\n  // Store the original request module.\n  const originalHttpRequest = http.request\n\n  // Rewrite the request module entirely.\n  http.request = function (...args) {\n    // Decide whether to handle this request before\n    // the actual request happens.\n    if (shouldMock(args)) {\n      // If so, never create a request, respond to it\n      // using the mocked response from this blackbox.\n      return coerceToResponse.bind(this, mock)\n    }\n\n    // Otherwise, construct the original request\n    // and perform it as-is (receives the original response).\n    return originalHttpRequest(...args)\n  }\n}\n```\n\nThis library deviates from such implementation and uses _class extensions_ instead of module rewrites. Such deviation is necessary because, unlike other solutions that include request matching and can determine whether to mock requests _before_ they actually happen, this library is not opinionated about the mocked/bypassed nature of the requests. Instead, it _intercepts all requests_ and delegates the decision of mocking to the end consumer.\n\n```js\nclass NodeClientRequest extends ClientRequest {\n  async end(...args) {\n    // Check if there's a mocked response for this request.\n    // You control this in the \"resolver\" function.\n    const mockedResponse = await resolver(isomorphicRequest)\n\n    // If there is a mocked response, use it to respond to this\n    // request, finalizing it afterward as if it received that\n    // response from the actual server it connected to.\n    if (mockedResponse) {\n      this.respondWith(mockedResponse)\n      this.finish()\n      return\n    }\n\n    // Otherwise, perform the original \"ClientRequest.prototype.end\" call.\n    return super.end(...args)\n  }\n}\n```\n\nBy extending the native modules, this library actually constructs requests as soon as they are constructed by the consumer. This enables all the request input validation and transformations done natively by Node.js—something that traditional solutions simply cannot do (they replace `http.ClientRequest` entirely). The class extension allows to fully utilize Node.js internals instead of polyfilling them, which results in more resilient mocks.\n\n## What this library does\n\nThis library extends (or patches, where applicable) the following native modules:\n\n- `http.get`/`http.request`\n- `https.get`/`https.request`\n- `XMLHttpRequest`\n- `fetch`\n\nOnce extended, it intercepts and normalizes all requests to the _isomorphic request instances_. The isomorphic request is an abstract representation of the request coming from different sources (`ClientRequest`, `XMLHttpRequest`, `window.Request`, etc.) that allows us to handle such requests in the same, unified manner.\n\nYou can respond to an isomorphic request using an _isomorphic response_. In a similar way, the isomorphic response is a representation of the response to use for different requests. Responding to requests differs substantially when using modules like `http` or `XMLHttpRequest`. This library takes the responsibility for coercing isomorphic responses into appropriate responses depending on the request module automatically.\n\n## What this library doesn't do\n\n- Does **not** provide any request matching logic;\n- Does **not** decide how to handle requests.\n\n## Getting started\n\n```bash\nnpm install @mswjs/interceptors\n```\n\n## API\n\n### Individual interceptors\n\nThere are multiple individual interceptors exported from this library:\n\n- `ClientRequestInterceptor`\n- `XMLHttpRequestInterceptor`\n- `FetchInterceptor`\n\nAll aforementioned interceptors implement the same HTTP request interception contract, meaning that they allow you to handle intercepted requests in the same way, regardless of the request origin (`http`/`XMLHttpRequest`/`fetch`).\n\nTo use multiple interceptors at once, consider [`BatchInterceptor`](#BatchInterceptor).\n\n```js\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/lib/interceptors/ClientRequest'\n\nconst interceptor = new ClientRequestInterceptor()\ninterceptor.on('request', (request) => {\n  // Introspect request or mock its response\n  // via \"request.respondWith()\".\n})\n```\n\n### `BatchInterceptor`\n\nApplies multiple request interceptors at the same time.\n\n```js\nimport { BatchInterceptor } from '@mswjs/interceptors'\nimport nodeInterceptors from '@mswjs/interceptors/lib/presets/node'\n\nconst interceptor = BatchInterceptor({\n  name: 'my-interceptor',\n  interceptors: nodeInterceptors,\n})\n\ninterceptor.on('request', (request) => {\n  // Inspect the intercepted \"request\".\n  // Optionally, return a mocked response.\n})\n```\n\n> Using the `/presets/node` interceptors preset is the recommended way to ensure all requests get intercepted, regardless of their origin.\n\n### `RemoteHttpInterceptor`\n\nEnables request interception in the current process while delegating the response resolution logic to the _parent process_. **Requires the current process to be a child process**. Requires the parent process to establish a resolver by calling the `createRemoteResolver` function.\n\n```js\n// child.js\nimport { RemoteHttpInterceptor } from '@mswjs/interceptors/lib/RemoteHttpInterceptor'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/lib/interceptors/ClientRequest'\n\nconst interceptor = new RemoteHttpInterceptor({\n  // Alternatively, you can use presets.\n  interceptors: [new ClientRequestInterceptor()],\n})\n\ninterceptor.apply()\n\nprocess.on('disconnect', () => {\n  interceptor.dispose()\n})\n```\n\nYou can still listen to and handle any requests in the child process via the `request` event listener. Keep in mind that a single request can only be responded to once.\n\n### `RemoteHttpResolver`\n\nResolves an intercepted request in the given child `process`. Requires for that child process to enable request interception by calling the `createRemoteInterceptor` function.\n\n```js\n// parent.js\nimport { spawn } from 'child_process'\nimport { RemoteHttpResolver } from '@mswjs/interceptors/lib/RemoteHttpInterceptor'\n\nconst appProcess = spawn('node', ['app.js'], {\n  stdio: ['inherit', 'inherit', 'inherit', 'ipc'],\n})\n\nconst resolver = new RemoteHttpResolver({\n  process: appProcess,\n})\n\nresolver.on('request', (request) => {\n  // Optionally, return a mocked response\n  // for a request that occurred in the \"appProcess\".\n})\n```\n\n### Methods\n\n#### `apply`\n\nApplies interceptor, enabling the interception of requests in the current process.\n\n```js\ninterceptor.apply()\n```\n\nThe same interceptor can be applied multiple times. If that happens, each subsequent interceptor instance will reusing a single running instance instead of applying itself repeatedly. Each interceptor instance should still be disposed individually.\n\n#### `on`\n\nListens to the interceptor events.\n\nEach interceptor decides what event map to implement. Currently, all exported interceptors implement an HTTP request event map that consists of the following events:\n\n- `request`, signals when a new request happens;\n- `response`, signals when a response was sent.\n\n```js\ninterceptor.on('request', (request) => {\n  console.log('[%s] %s', request.method, request.url.toString())\n})\n\ninterceptor.on('response', (request, response) => {\n  console.log(\n    'Received response to [%s] %s:',\n    request.method,\n    request.url.href,\n    response\n  )\n})\n```\n\n#### `dispose`\n\nDisposes of the applied interceptor. This cleans up all the side-effects introduced by the interceptor (i.e. restores augmented modules).\n\n```js\ninterceptor.dispose()\n```\n\n## Special mention\n\nThe following libraries were used as an inspiration to write this low-level API:\n\n- [`node`](https://github.com/nodejs/node)\n- [`nock`](https://github.com/nock/nock)\n- [`mock-xmlhttprequest`](https://github.com/berniegp/mock-xmlhttprequest)\n","readmeFilename":"README.md"}