Type: object<string, Function[]>
This option represents the hooks to run. Thrown errors will be automatically converted to RequestError
.
Type: InitHook[]
Default: []
(plainRequestOptions: OptionsInit, options: Options) => void
Called with the plain request options, right before their normalization.
The second argument represents the current Options
instance.
Note:
- This hook must be synchronous.
Note:
- This is called every time options are merged.
Note:
- The
options
object may not have theurl
property. To modify it, use abeforeRequest
hook instead.
Note:
- This hook is called when a new instance of
Options
is created.- Do not confuse this with the creation of
Request
orgot(…)
.
Note:
- When using
got(url)
orgot(url, undefined, defaults)
this hook will not be called.
This is especially useful in conjunction with got.extend()
when the input needs custom handling.
For example, this can be used to fix typos to migrate from older versions faster.
import got from 'got';
const instance = got.extend({
hooks: {
init: [
plain => {
if ('followRedirects' in plain) {
plain.followRedirect = plain.followRedirects;
delete plain.followRedirects;
}
}
]
}
});
// Normally, the following would throw:
const response = await instance(
'https://example.com',
{
followRedirects: true
}
);
// There is no option named `followRedirects`, but we correct it in an `init` hook.
Or you can create your own option and store it in a context:
import got from 'got';
const instance = got.extend({
hooks: {
init: [
(plain, options) => {
if ('secret' in plain) {
options.context.secret = plain.secret;
delete plain.secret;
}
}
],
beforeRequest: [
options => {
options.headers.secret = options.context.secret;
}
]
}
});
const {headers} = await instance(
'https://httpbin.org/anything',
{
secret: 'passphrase'
}
).json();
console.log(headers.Secret);
//=> 'passphrase'
Type: BeforeRequestHook[]
Default: []
(options: Options) => Promisable<void | Response | ResponseLike>
Called right before making the request with options.createNativeRequestOptions()
.
This hook is especially useful in conjunction with got.extend()
when you want to sign your request.
Note:
- Got will make no further changes to the request before it is sent.
Note:
- Changing
options.json
oroptions.form
has no effect on the request. You should changeoptions.body
instead. If needed, update theoptions.headers
accordingly.
import got from 'got';
const response = await got.post(
'https://httpbin.org/anything',
{
json: {payload: 'old'},
hooks: {
beforeRequest: [
options => {
options.body = JSON.stringify({payload: 'new'});
options.headers['content-length'] = options.body.length.toString();
}
]
}
}
);
Tip:
- You can indirectly override the
request
function by early returning aClientRequest
-like instance or aIncomingMessage
-like instance. This is very useful when creating a custom cache mechanism.- Read more about this tip.
Type: BeforeRedirectHook[]
Default: []
(updatedOptions: Options, plainResponse: PlainResponse) => Promisable<void>
The equivalent of beforeRequest
but when redirecting.
Tip:
- This is especially useful when you want to avoid dead sites.
import got from 'got';
const response = await got('https://example.com', {
hooks: {
beforeRedirect: [
(options, response) => {
if (options.hostname === 'deadSite') {
options.hostname = 'fallbackSite';
}
}
]
}
});
Type: BeforeRetryHook[]
Default: []
(error: RequestError, retryCount: number) => Promisable<void>
The equivalent of beforeError
but when retrying. Additionally, there is a second argument retryCount
, the current retry number.
Note:
- When using the Stream API, this hook is ignored.
Note:
- When retrying, the
beforeRequest
hook is called afterwards.
Note:
- If no retry occurs, the
beforeError
hook is called instead.
This hook is especially useful when you want to retrieve the cause of a retry.
import got from 'got';
await got('https://httpbin.org/status/500', {
hooks: {
beforeRetry: [
(error, retryCount) => {
console.log(`Retrying [${retryCount}]: ${error.code}`);
// Retrying [1]: ERR_NON_2XX_3XX_RESPONSE
}
]
}
});
Type: AfterResponseHook[]
Default: []
(response: Response, retryWithMergedOptions: (options: OptionsInit) => never) => Promisable<Response | CancelableRequest<Response>>
Each function should return the response. This is especially useful when you want to refresh an access token.
Note:
- When using the Stream API, this hook is ignored.
Note:
- Calling the
retryWithMergedOptions
function will triggerbeforeRetry
hooks. If the retry is successful, all remainingafterResponse
hooks will be called. In case of an error,beforeRetry
hooks will be called instead. Meanwhile theinit
,beforeRequest
,beforeRedirect
as well as already executedafterResponse
hooks will be skipped.
import got from 'got';
const instance = got.extend({
hooks: {
afterResponse: [
(response, retryWithMergedOptions) => {
// Unauthorized
if (response.statusCode === 401) {
// Refresh the access token
const updatedOptions = {
headers: {
token: getNewToken()
}
};
// Update the defaults
instance.defaults.options.merge(updatedOptions);
// Make a new retry
return retryWithMergedOptions(updatedOptions);
}
// No changes otherwise
return response;
}
],
beforeRetry: [
error => {
// This will be called on `retryWithMergedOptions(...)`
}
]
},
mutableDefaults: true
});
Type: BeforeErrorHook[]
Default: []
(error: RequestError) => Promisable<RequestError>
Called with a RequestError
instance. The error is passed to the hook right before it's thrown.
This is especially useful when you want to have more detailed errors.
import got from 'got';
await got('https://api.github.com/repos/sindresorhus/got/commits', {
responseType: 'json',
hooks: {
beforeError: [
error => {
const {response} = error;
if (response && response.body) {
error.name = 'GitHubError';
error.message = `${response.body.message} (${response.statusCode})`;
}
return error;
}
]
}
});