@keq-request/exception
Middleware for throwing/catching exceptions, with control over whether thrown exceptions trigger retry.
Installation
- npm
- pnpm
- yarn
Usage
import { request, RequestException } from "keq"
import {
throwException,
catchException,
} from "@keq-request/exception"
request
.use(
catchException((err) => {
if (err instanceof RequestException && err.statusCode === 401) {
context.redirect("/login")
return
}
throw err
})
)
// throwException's callback always runs after `await next()`
// You can access the Response in the callback
.use(
throwException(async (ctx) => {
if (ctx.response && ctx.response.status >= 400) {
const body = await ctx.response.json()
throw new RequestException(ctx.response.status, body.message)
}
})
)RequestException(statusCode[, errorMessage[, options]])
| Parameter | Default | Description |
|---|---|---|
| statusCode | - | HTTP status code |
| message | '' | Error message |
| options.fatal | false | Set to true to terminate the retry mechanism |
| options.response | - | Associated Response object |
Middleware
validateStatusCode
Validates the Response status and throws the corresponding RequestException:
statusin range200-399: no exception thrownstatus = 400: throwsBadRequestException(statusText)status = 401: throwsUnauthorizedException(statusText)status = 403: throwsForbiddenException(statusText)status = 404: throwsNotFoundedException(statusText)status = 405: throwsMethodNotAllowedException(statusText)status = 406: throwsNotAcceptableException(statusText)status = 407: throwsProxyAuthenticationRequiredException(statusText)status = 408: throwsRequestTimeoutException(statusText)status = 409: throwsConflictException(statusText)status = 412: throwsPreconditionFailedException(statusText)status = 413: throwsContentTooLargeException(statusText)status = 414: throwsUriTooLongException(statusText)status = 415: throwsUnsupportedMediaTypeException(statusText)status = 418: throwsImATeapotException(statusText)status = 429: throwsTooManyRequestsException(statusText)statusis other400-499value: throwsRequestException(status, statusText, { fatal: true })status = 500: throwsInternalServerErrorException(statusText)status = 501: throwsNotImplementedException(statusText)status = 502: throwsBadGatewayException(statusText)status = 503: throwsServiceUnavailableException(statusText)status = 504: throwsGatewayTimeoutException(statusText)statusis other500-599value: throwsRequestException(status, statusText, { fatal: false })
Example
import { request } from "keq"
import { validateStatusCode } from "@keq-request/exception"
request.use(validateStatusCode())clarifyFetchFailed
Node.js native fetch throws a TypeError on network errors with a message of just "fetch failed" — the real cause (e.g., ECONNREFUSED, ENOTFOUND, ETIMEDOUT) is hidden in the .cause property. The clarifyFetchFailed middleware expands the .cause chain into the error's message, making logs and error messages more readable.
Effect
// Before
TypeError: fetch failed
// After
TypeError: fetch failed: connect ECONNREFUSED 127.0.0.1:3000
Example
import { request } from "keq"
import { clarifyFetchFailed } from "@keq-request/exception"
request.use(clarifyFetchFailed())