It is a modern http client, based on fetch, because it is implemented internally using the onion model, so you can use middleware to intercept requests and responses elegantly.
Resreq targets modern browsers and Deno
pnpm install resreq
or
import Resreq from 'https://esm.sh/resreq'
If you are using a lower version of node, you may need to add some polyfill.
import fetch, { Headers, Request, Response } from 'node-fetch'
import AbortController from 'abort-controller'
globalThis.fetch = fetch
globalThis.Headers = Headers
globalThis.Request = Request
globalThis.Response = Response
globalThis.AbortController = AbortController
import Resreq from 'resreq'
const resreq = new Resreq({
baseURL: 'https://example.com',
responseType: 'json'
})
const res = await resreq.request({
url: '/api/user',
method: 'GET',
params: { foo: 'bar' }
})
console.log(res) // Object
const res = await resreq.get('/api/download', {
responseType: 'blob'
})
console.log(res) // Blob
Cancel request
const resreq = new Resreq()
const abortController = new AbortController()
resreq.get('https://example.com/api', {
signal: abortController.signal
})
.catch((error) => {
console.log(error) // Abort error
})
abortController.abort() // request cancel
Use Middlewares
const resreq = new Resreq({
baseURL: 'https://example.com'
})
// Intercepting responses and requests using middleware
resreq.use((next) => async (req) => {
try {
console.log(req) // Request can be changed here
const res = await next(req)
console.log(res) // Response can be changed here
return res
} catch (error) {
console.log(error) // Catch errors here
throw error
}
})
const res = await resreq.get('/api', {
params: { foo: 'bar' }
})
console.log(res)
new Resreq(options?:Options)
Create a resreq instance and configure the global options.
const resreq = new Resreq({
baseURL: 'https://example.com',
timeout: 10000,
responseType: 'json',
throwHttpError: true,
onDownloadProgress(progress, chunk) {
console.log(progress, chunk)
}
})
resreq.request(options?:Options)
Use ''request'' to send the request and configure the options.
const resreq = new Resreq({
baseURL: 'https://example.com'
})
const res = await resreq.request({
url: '/api',
method: 'GET',
params: { foo: 'bar' },
throwHttpError: true,
onDownloadProgress(progress, chunk) {
console.log(progress, chunk)
}
})
console.log(res)
resreq[method](options?:Options)
Use ''method'' to send the request and configure the options
const resreq = new Resreq({
baseURL: 'https://example.com'
})
const res = await resreq.get('/api', {
params: { foo: 'bar' },
throwHttpError: true,
onDownloadProgress(progress, chunk) {
console.log(progress, chunk)
}
})
console.log(res)
resreq.use(middleware:Middleware)
Add headers using middleware.
import Resreq, { Middleware } from 'resreq'
const resreq = new Resreq({
baseURL: 'https://example.com'
})
// Implement a middleware that set token
const setAccessToken: Middleware = (next) => (req) => {
req.headers.set('Access-Token', 'foo-bar')
return next(req)
}
// Register middleware
resreq.use(setAccessToken)
await resreq.get('/api')
Rewriting headers using middleware.
import Resreq, { Req } from 'resreq'
const resreq = new Resreq({
baseURL: 'https://example.com'
})
resreq.use((next) => async (req) => {
// Create a new request with Req
const _req = new Req(req, {
headers: {
'X-Custom-Header': 'bar'
}
})
console.log(_req.headers.get('Content-Type')) // null
console.log(_req.headers.get('X-Custom-Header')) // bar
return await next(_req)
})
await resreq.get('/api', {
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'foo'
}
})
Req(request: Req, init: ReqInit | Request)
Res(response: Res, init: ResInit | Response)
In the middleware, use new Req()
and new Res()
to rewrite the request and response.
import Resreq, { Req, Res } from 'resreq'
const resreq = new Resreq({
baseURL: 'https://example.com',
})
resreq.use((next) => async (req) => {
const _req = new Req(req, {
url: 'https://example.com/mock'
})
const res = await next(_req)
return new Res(res, {
body: { foo: 'bar' }
status: 200,
})
})
const res: Response = await resreq.get('/api')
console.log(res.status) // 200
console.log(await res.json()) // { foo: 'bar' }
Warning Req & Res extends from Request and Response; to create a new request and response in the middleware, use
new Req()
andnew Res()
.To access the contents of the
body
in the current middleware, please useRes.clone()
to ensure that the res received by the next middleware are unlocked.
Options
Options extends from the RequestInit type with some additional properties
interface Options extends Omit<RequestInit, 'body'> {
baseURL?: string
url?: string
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'PATCH'
params?: Record<string, any>
body?: BodyInit | Record<string, any>
meta?: Record<string, any>
timeout?: number
responseType?: 'json' | 'arrayBuffer' | 'blob' | 'formData' | 'text' | null | false
throwHttpError?: boolean
onDownloadProgress?: ProgressCallback
}
resreq[method]()
to form a complete request address, the default value is ' '.resreq.get
request are automatically added to the url via the new URLSearchParams method.Record<string, any>
, which means you can pass object
directly, instead of JSON.stringify(object)
, which will automatically add Content-Type: application/json
request headers.Res.meta
and Req.meta
.To avoid adding complexity, new Resreq(options)
and resreq[method](options)
, in which 'options' are of the same type.
The options defined in new Resreq(options)
will take effect globally, resreq[method](options)
, will override the "global options", except for the following options which will not be overridden.
meta: The meta within the method will be shallow merged with the global meta.
headers: The headers defined in the method are merged into the global headers.
onDownloadProgress: Defining onDownloadProgress in a method and the global onDownloadProgress are both retained.
ReqInit
Options extends from the RequestInit type with some additional properties.
interface ReqInit extends Omit<RequestInit, 'body'> {
url?: string
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'PATCH'
meta?: Record<string, any>
timeout?: number
responseType?: ResponseType
throwHttpError?: boolean
body?: BodyInit | Record<string, any>
onDownloadProgress?: ProgressCallback
}
Note That its 'headers' behave differently than 'Options.headers', which overrides the global headers.
ResInit
ResInit extends from the ResponseInit type with some additional properties.
interface ResInit extends ResponseInit {
meta?: Record<string, any>
body?: BodyInit | Record<string, any> | null
timeout?: number
responseType?: ResponseType
throwHttpError?: boolean
onDownloadProgress?: ProgressCallback
}
Middleware
The middleware must call next(req) to return a promise.
type Middleware = (next: Next) => (req: Req) => Promise<Res>
Some of the inspiration for this project came from their.
This project is licensed under the MIT License - see the LICENSE file for details.
Generated using TypeDoc