Skip to content

Commit

Permalink
Add support for aborting a request using AbortSignal (#205)
Browse files Browse the repository at this point in the history
* Add support for aborting a request using AbortSignal

* Update docs

* Attempt fixing tests and types for Node 14.x

* Update README.md

Co-authored-by: Matteo Collina <matteo.collina@gmail.com>

* Ignore from coverage code that isn't used in Node 14.x

Co-authored-by: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
segevfiner and mcollina committed Jul 18, 2022
1 parent b79e88e commit f70243a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 6 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
[![NPM version](https://img.shields.io/npm/v/light-my-request.svg?style=flat)](https://www.npmjs.com/package/light-my-request)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)

Injects a fake HTTP request/response into a node HTTP server for simulating server logic, writing tests, or debugging.
Does not use a socket connection so can be run against an inactive server (server not in listen mode).
Injects a fake HTTP request/response into a node HTTP server for simulating server logic, writing tests, or debugging.
Does not use a socket connection so can be run against an inactive server (server not in listen mode).

## Example

Expand Down Expand Up @@ -165,6 +165,7 @@ Injects a fake request into an HTTP server.
- `server` - Optional http server. It is used for binding the `dispatchFunc`.
- `autoStart` - Automatically start the request as soon as the method
is called. It is only valid when not passing a callback. Defaults to `true`.
- `signal` - An `AbortSignal` that may be used to abort an ongoing request. Requires Node v16+.
- `Request` - Optional type from which the `request` object should inherit
instead of `stream.Readable`
- `callback` - the callback function using the signature `function (err, res)` where:
Expand Down Expand Up @@ -249,8 +250,8 @@ inject(dispatch)
Note: The application would not respond multiple times. If you try to invoking any method after the application has responded, the application would throw an error.

## Acknowledgements
This project has been forked from [`hapi/shot`](https://github.com/hapijs/shot) because we wanted to support *Node ≥ v4* and not only *Node ≥ v8*.
All the credits before the commit [00a2a82](https://github.com/fastify/light-my-request/commit/00a2a82eb773b765003b6085788cc3564cd08326) goes to the `hapi/shot` project [contributors](https://github.com/hapijs/shot/graphs/contributors).
This project has been forked from [`hapi/shot`](https://github.com/hapijs/shot) because we wanted to support *Node ≥ v4* and not only *Node ≥ v8*.
All the credits before the commit [00a2a82](https://github.com/fastify/light-my-request/commit/00a2a82eb773b765003b6085788cc3564cd08326) goes to the `hapi/shot` project [contributors](https://github.com/hapijs/shot/graphs/contributors).
Since the commit [db8bced](https://github.com/fastify/light-my-request/commit/db8bced10b4367731688c8738621d42f39680efc) the project will be maintained by the Fastify team.

## License
Expand Down
8 changes: 7 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ declare namespace LightMyRequest {

function isInjection (obj: http.IncomingMessage | http.ServerResponse): boolean

interface AbortSignal {
readonly aborted: boolean;
}

interface InjectOptions {
url?: string | {
pathname: string
Expand Down Expand Up @@ -56,7 +60,9 @@ declare namespace LightMyRequest {
validate?: boolean
payload?: InjectPayload
server?: http.Server
cookies?: { [k: string]: string }
cookies?: { [k: string]: string },
signal?: AbortSignal,
Request?: object,
}

interface Response {
Expand Down
8 changes: 7 additions & 1 deletion lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/* eslint no-prototype-builtins: 0 */

const { Readable } = require('stream')
const { Readable, addAbortSignal } = require('stream')
const util = require('util')
const cookie = require('cookie')
const assert = require('assert')
Expand Down Expand Up @@ -129,6 +129,12 @@ function Request (options) {
configurable: true
})

const signal = options.signal
/* istanbul ignore if */
if (signal) {
addAbortSignal(signal, this)
}

// we keep both payload and body for compatibility reasons
let payload = options.payload || options.body || null
const payloadResume = payload && typeof payload.resume === 'function'
Expand Down
17 changes: 17 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1834,3 +1834,20 @@ test('Can parse URLs with single leading slash', (t) => {
const parsedURL = parseURL('https://example.com/test', undefined)
t.equal(parsedURL.href, 'https://example.com/test')
})

test('Can abort a request using AbortController/AbortSignal', (t) => {
t.plan(1)

const dispatch = function (req, res) {}

const controller = new AbortController()
const promise = inject(dispatch, {
method: 'GET',
url: 'http://example.com:8080/hello',
signal: controller.signal
})
controller.abort()
const wanted = new Error('The operation was aborted')
wanted.name = 'AbortError'
t.rejects(promise, wanted)
}, { skip: globalThis.AbortController == null })

0 comments on commit f70243a

Please sign in to comment.