From fc2acbe4b20795cb82a597c9eb70eeac8e9fdfe7 Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Wed, 20 Dec 2023 10:39:32 +0900 Subject: [PATCH] feat: expose headerNameToString --- docs/api/Util.md | 25 +++++++++++++++++++++++++ index.js | 4 ++-- lib/core/util.js | 8 ++++++-- test/types/util.test-d.ts | 38 ++++++++++++++++++++++++++++++++++++++ types/index.d.ts | 1 + types/util.d.ts | 31 +++++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 docs/api/Util.md create mode 100644 test/types/util.test-d.ts create mode 100644 types/util.d.ts diff --git a/docs/api/Util.md b/docs/api/Util.md new file mode 100644 index 00000000000..2393d079dfc --- /dev/null +++ b/docs/api/Util.md @@ -0,0 +1,25 @@ +# Util + +Utility API for third-party implementations of the dispatcher API. + +## `parseHeaders(headers, [obj])` + +Receives a header object and returns the parsed value. + +Arguments: + +- **headers** `Record | (Buffer | string | (Buffer | string)[])[]` (required) - Header object. + +- **obj** `Record` (optional) - Object to specify a proxy object. The parsed value is assigned to this object. But, if **headers** is an object, it is not used. + +Returns: `Record` If **headers** is an object, it is **headers**. Otherwise, if **obj** is specified, it is equivalent to **obj**. + +## `headerNameToString(value)` + +Retrieves a header name and returns its lowercase value. + +Arguments: + +- **value** `string | Buffer` (required) - Header name. + +Returns: `string` diff --git a/index.js b/index.js index 6898fb757d9..5fc0d9727ef 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,6 @@ const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global') const DecoratorHandler = require('./lib/handler/DecoratorHandler') const RedirectHandler = require('./lib/handler/RedirectHandler') const createRedirectInterceptor = require('./lib/interceptor/redirectInterceptor') -const { parseHeaders } = require('./lib/core/util') let hasCrypto try { @@ -47,7 +46,8 @@ module.exports.createRedirectInterceptor = createRedirectInterceptor module.exports.buildConnector = buildConnector module.exports.errors = errors module.exports.util = { - parseHeaders + parseHeaders: util.parseHeaders, + headerNameToString: util.headerNameToString } function makeDispatcher (fn) { diff --git a/lib/core/util.js b/lib/core/util.js index 6c2e1e55d21..7cd411d9f3e 100644 --- a/lib/core/util.js +++ b/lib/core/util.js @@ -221,7 +221,9 @@ function parseKeepAliveTimeout (val) { } /** - * @param {string | Buffer} value + * Retrieves a header name and returns its lowercase value. + * @param {string | Buffer} value Header name + * @returns {string} */ function headerNameToString (value) { return typeof value === 'string' @@ -230,7 +232,9 @@ function headerNameToString (value) { } /** - * @param {Buffer} value + * Receive the buffer as a string and return its lowercase value. + * @param {Buffer} value Header name + * @returns {string} */ function bufferToLowerCasedHeaderName (value) { return tree.lookup(value) ?? value.toString('latin1').toLowerCase() diff --git a/test/types/util.test-d.ts b/test/types/util.test-d.ts new file mode 100644 index 00000000000..9879fd31507 --- /dev/null +++ b/test/types/util.test-d.ts @@ -0,0 +1,38 @@ +import { expectAssignable } from 'tsd'; +import { util } from '../../types/util'; + +expectAssignable>( + util.parseHeaders({ 'content-type': 'text/plain' }) +); + +expectAssignable>( + //@ts-ignore + util.parseHeaders({ 'content-type': 'text/plain' }, {}) +); + +expectAssignable>( + util.parseHeaders({} as Record | string[], {}) +); + +expectAssignable>( + util.parseHeaders(['content-type', 'text/plain']) +); + +expectAssignable>( + util.parseHeaders([Buffer.from('content-type'), Buffer.from('text/plain')]) +); + +expectAssignable>( + util.parseHeaders( + [Buffer.from('content-type'), Buffer.from('text/plain')], + {} + ) +); + +expectAssignable>( + util.parseHeaders([Buffer.from('content-type'), [Buffer.from('text/plain')]]) +); + +expectAssignable(util.headerNameToString('content-type')); + +expectAssignable(util.headerNameToString(Buffer.from('content-type'))); diff --git a/types/index.d.ts b/types/index.d.ts index 0ea8bdc217d..8b35475219b 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -17,6 +17,7 @@ import ProxyAgent from'./proxy-agent' import RetryHandler from'./retry-handler' import { request, pipeline, stream, connect, upgrade } from './api' +export * from './util' export * from './cookies' export * from './fetch' export * from './file' diff --git a/types/util.d.ts b/types/util.d.ts new file mode 100644 index 00000000000..2a604148fd8 --- /dev/null +++ b/types/util.d.ts @@ -0,0 +1,31 @@ +export namespace util { + /** + * Retrieves a header name and returns its lowercase value. + * @param value Header name + */ + export function headerNameToString(value: string | Buffer): string; + + /** + * Receives a header object and returns the parsed value. + * @param headers Header object + */ + export function parseHeaders( + headers: + | Record + | (Buffer | string | (Buffer | string)[])[] + ): Record; + /** + * Receives a header object and returns the parsed value. + * @param headers Header object + * @param obj Object to specify a proxy object. Used to assign parsed values. But, if `headers` is an object, it is not used. + * @returns If `headers` is an object, it is `headers`. Otherwise, if `obj` is specified, it is equivalent to `obj`. + */ + export function parseHeaders< + H extends + | Record + | (Buffer | string | (Buffer | string)[])[] + >( + headers: H, + obj?: H extends any[] ? Record : never + ): Record; +}