From 2fd5edafeac7c7b839bcc4c675c062310cc1caf5 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 29 Nov 2022 12:58:46 +0100 Subject: [PATCH] refactor!: update http request options BREAKING CHANGE: `httpOptions` return property `lookup` was renamed to `dnsLookup`. BREAKING CHANGE: `httpOptions` return property `timeout` was removed, return an `AbortSignal` instance as `signal` property instead. --- certification/runner/api.js | 17 ++++++++++------ docs/README.md | 8 ++++---- lib/helpers/defaults.js | 10 +++++----- lib/helpers/request.js | 30 ++++++++++++++++++---------- package.json | 2 +- test/client_auth/client_auth.test.js | 2 +- 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/certification/runner/api.js b/certification/runner/api.js index 131969593..93ddfc2a9 100644 --- a/certification/runner/api.js +++ b/certification/runner/api.js @@ -4,7 +4,7 @@ import { createWriteStream } from 'node:fs'; import stream from 'node:stream'; import { promisify } from 'node:util'; -import Got from 'got'; +import got from 'got'; // eslint-disable-line import/no-unresolved import ms from 'ms'; import debug from './debug.js'; @@ -18,7 +18,7 @@ class API { constructor({ baseUrl, bearerToken } = {}) { assert(baseUrl, 'argument property "baseUrl" missing'); - const { get, post } = Got.extend({ + const { get, post } = got.extend({ prefixUrl: baseUrl, throwHttpErrors: false, followRedirect: false, @@ -27,14 +27,16 @@ class API { 'content-type': 'application/json', }, responseType: 'json', - retry: 0, - timeout: 10000, + retry: { limit: 0 }, + https: { + rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0', + }, }); this.get = get; this.post = post; - this.stream = Got.extend({ + this.stream = got.extend({ prefixUrl: baseUrl, throwHttpErrors: false, followRedirect: false, @@ -42,7 +44,10 @@ class API { ...(bearerToken ? { authorization: `bearer ${bearerToken}` } : undefined), 'content-type': 'application/json', }, - retry: 0, + retry: { limit: 0 }, + https: { + rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0', + }, }).stream; } diff --git a/docs/README.md b/docs/README.md index 769911253..e76cfab7a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2346,7 +2346,7 @@ _**default value**_: ### httpOptions -Function called whenever calls to an external HTTP(S) resource are being made. You can change the request `timeout` duration, the `agent` used as well as the `lookup` resolver function. +Function called whenever calls to an external HTTP(S) resource are being made. You can change the request timeout through the `signal` option, the `agent` used as well as the `dnsLookup` resolver function. @@ -2354,9 +2354,9 @@ _**default value**_: ```js function httpOptions(url) { return { - timeout: 2500, + signal: undefined, // defaults to AbortSignal.timeout(2500) agent: undefined, // defaults to node's global agents (https.globalAgent or http.globalAgent) - lookup: undefined, // defaults to `dns.lookup()` (https://nodejs.org/api/dns.html#dnslookuphostname-options-callback) + dnsLookup: undefined, // defaults to `dns.lookup()` (https://nodejs.org/api/dns.html#dnslookuphostname-options-callback) }; } ``` @@ -2369,7 +2369,7 @@ To change all request's timeout configure the httpOptions as a function like so: ```js { httpOptions(url) { - return { timeout: 5000 }; + return { signal: AbortSignal.timeout(5000) }; } } ``` diff --git a/lib/helpers/defaults.js b/lib/helpers/defaults.js index d54df1933..94a2e835c 100644 --- a/lib/helpers/defaults.js +++ b/lib/helpers/defaults.js @@ -223,9 +223,9 @@ async function extraTokenClaims(ctx, token) { function httpOptions(url) { return { - timeout: 2500, + signal: undefined, // defaults to AbortSignal.timeout(2500) agent: undefined, // defaults to node's global agents (https.globalAgent or http.globalAgent) - lookup: undefined, // defaults to `dns.lookup()` (https://nodejs.org/api/dns.html#dnslookuphostname-options-callback) + dnsLookup: undefined, // defaults to `dns.lookup()` (https://nodejs.org/api/dns.html#dnslookuphostname-options-callback) }; } @@ -1914,8 +1914,8 @@ function makeDefaults() { * httpOptions * * description: Function called whenever calls to an external HTTP(S) resource are being made. - * You can change the request `timeout` duration, the `agent` used as well as the `lookup` - * resolver function. + * You can change the request timeout through the `signal` option, the `agent` used as well as + * the `dnsLookup` resolver function. * * example: To change the request's timeout * @@ -1924,7 +1924,7 @@ function makeDefaults() { * ```js * { * httpOptions(url) { - * return { timeout: 5000 }; + * return { signal: AbortSignal.timeout(5000) }; * } * } * ``` diff --git a/lib/helpers/request.js b/lib/helpers/request.js index 3c152dc66..798d6030d 100644 --- a/lib/helpers/request.js +++ b/lib/helpers/request.js @@ -1,4 +1,8 @@ -import got from 'got'; +import dns from 'node:dns'; +import http from 'node:http'; +import https from 'node:https'; + +import got from 'got'; // eslint-disable-line import/no-unresolved import pickBy from './_/pick_by.js'; import instance from './weak_cache.js'; @@ -7,30 +11,36 @@ export default async function request(options) { Object.assign(options, { url: new URL(options.url), headers: options.headers || {}, + https: { + rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0', + }, }); // eslint-disable-next-line no-param-reassign options.headers['user-agent'] = undefined; - const { timeout, agent, lookup } = instance(this).configuration('httpOptions')(new URL(options.url)); - const helperOptions = pickBy({ timeout, agent, lookup }, Boolean); + const { + signal = AbortSignal.timeout(2500), + agent = options.url.protocol === 'http:' ? http.globalAgent : https.globalAgent, + dnsLookup = dns.lookup, + } = instance(this).configuration('httpOptions')(new URL(options.url)); + const helperOptions = pickBy({ signal, agent, dnsLookup }, Boolean); - if (helperOptions.timeout !== undefined && typeof helperOptions.timeout !== 'number') { - throw new TypeError('"timeout" http request option must be a number'); + if (helperOptions.signal !== undefined && !(helperOptions.signal instanceof AbortSignal)) { + throw new TypeError('"signal" http request option must be an AbortSignal'); } - if (helperOptions.agent !== undefined && typeof helperOptions.agent !== 'number') { + if (helperOptions.agent !== undefined) { helperOptions.agent = { [options.url.protocol.slice(0, -1)]: helperOptions.agent }; } - if (helperOptions.lookup !== undefined && typeof helperOptions.lookup !== 'function') { - throw new TypeError('"lookup" http request option must be a function'); + if (helperOptions.dnsLookup !== undefined && typeof helperOptions.dnsLookup !== 'function') { + throw new TypeError('"dnsLookup" http request option must be a function'); } return got({ ...options, followRedirect: false, - retry: 0, + retry: { limit: 0 }, throwHttpErrors: false, - timeout: 2500, ...helperOptions, }); } diff --git a/package.json b/package.json index e468cda42..5b4310356 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@koa/cors": "^4.0.0", "debug": "^4.3.4", "ejs": "^3.1.8", - "got": "^11.8.5", + "got": "^12.5.3", "jose": "^4.10.3", "jsesc": "^3.0.2", "koa": "^2.13.4", diff --git a/test/client_auth/client_auth.test.js b/test/client_auth/client_auth.test.js index b390b8834..206e3392e 100644 --- a/test/client_auth/client_auth.test.js +++ b/test/client_auth/client_auth.test.js @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs'; -import got from 'got'; +import got from 'got'; // eslint-disable-line import/no-unresolved import nock from 'nock'; import jose from 'jose2'; import { importJWK } from 'jose';