diff --git a/src/_utils.ts b/src/_utils.ts index 9700f26..069c388 100644 --- a/src/_utils.ts +++ b/src/_utils.ts @@ -1,3 +1,14 @@ +import httpNative from "node:http"; +import httpsNative from "node:https"; +import type tls from "node:tls"; +import type { Url as LegacyURL } from "node:url"; +import net from "node:net"; +import type { + ProxyServerOptions, + ProxyTarget, + ProxyTargetDetailed, +} from "./types"; + const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i; /** @@ -15,19 +26,29 @@ export const isSSL = /^https|wss/; * common.setupOutgoing(outgoing, options, req) * // => { host: ..., hostname: ...} * - * @param {Object} Outgoing Base object to be filled with required properties - * @param {Object} Options Config object passed to the proxy - * @param {ClientRequest} Req Request Object - * @param {String} Forward String to select forward or target + * @param outgoing Base object to be filled with required properties + * @param options Config object passed to the proxy + * @param req Request Object + * @param forward String to select forward or target * - * @return {Object} Outgoing Object with all required properties set + * @return Outgoing Object with all required properties set * * @api private */ -export function setupOutgoing(outgoing, options, req, forward?) { +export function setupOutgoing( + outgoing: httpNative.RequestOptions & httpsNative.RequestOptions, + options: ProxyServerOptions & { + target: ProxyTarget; + forward?: ProxyTarget; + }, + req: httpNative.IncomingMessage, + forward?: "forward" | "target", +): httpNative.RequestOptions | httpsNative.RequestOptions { outgoing.port = - options[forward || "target"].port || - (isSSL.test(options[forward || "target"].protocol) ? 443 : 80); + (options[forward || "target"] as URL).port || + (isSSL.test((options[forward || "target"] as URL).protocol ?? "http") + ? 443 + : 80); for (const e of [ "host", @@ -40,10 +61,13 @@ export function setupOutgoing(outgoing, options, req, forward?) { "ca", "ciphers", "secureProtocol", - ]) { - outgoing[e] = options[forward || "target"][e]; + ] as const) { + const value = (options[forward || "target"] as ProxyTargetDetailed)[e]; + // @ts-expect-error -- this mapping is valid + outgoing[e] = value; } + // @ts-expect-error - options.method is undocumented outgoing.method = options.method || req.method; outgoing.headers = { ...req.headers }; @@ -55,11 +79,13 @@ export function setupOutgoing(outgoing, options, req, forward?) { outgoing.auth = options.auth; } + // @ts-expect-error - options.ca is undocumented if (options.ca) { + // @ts-expect-error - options.ca is undocumented outgoing.ca = options.ca; } - if (isSSL.test(options[forward || "target"].protocol)) { + if (isSSL.test((options[forward || "target"] as URL).protocol ?? "http")) { outgoing.rejectUnauthorized = options.secure === undefined ? true : options.secure; } @@ -85,10 +111,10 @@ export function setupOutgoing(outgoing, options, req, forward?) { const target = options[forward || "target"]; const targetPath = target && options.prependPath !== false - ? target.pathname || target.path || "" + ? (target as URL).pathname || (target as LegacyURL).path || "" : ""; - const parsed = new URL(req.url, "http://localhost"); + const parsed = new URL(req.url!, "http://localhost"); let outgoingPath = options.toProxy ? req.url : parsed.pathname + parsed.search || ""; @@ -103,10 +129,12 @@ export function setupOutgoing(outgoing, options, req, forward?) { if (options.changeOrigin) { outgoing.headers.host = - requiresPort(outgoing.port, options[forward || "target"].protocol) && - !hasPort(outgoing.host) + requiresPort( + outgoing.port, + (options[forward || "target"] as URL).protocol, + ) && !hasPort(outgoing.host) ? outgoing.host + ":" + outgoing.port - : outgoing.host; + : (outgoing.host ?? undefined); } return outgoing; } @@ -144,14 +172,14 @@ export function joinURL( * common.setupSocket(socket) * // => Socket * - * @param {Socket} Socket instance to setup + * @param socket instance to setup * - * @return {Socket} Return the configured socket. + * @return Return the configured socket. * * @api private */ -export function setupSocket(socket) { +export function setupSocket(socket: net.Socket): net.Socket { socket.setTimeout(0); socket.setNoDelay(true); @@ -163,13 +191,13 @@ export function setupSocket(socket) { /** * Get the port number from the host. Or guess it based on the connection type. * - * @param {Request} req Incoming HTTP request. + * @param req Incoming HTTP request. * - * @return {String} The port number. + * @return The port number. * * @api private */ -export function getPort(req) { +export function getPort(req: httpNative.IncomingMessage): string { const res = req.headers.host ? req.headers.host.match(/:(\d+)/) : ""; if (res) { return res[1]; @@ -180,26 +208,45 @@ export function getPort(req) { /** * Check if the request has an encrypted connection. * - * @param {Request} req Incoming HTTP request. + * @param req Incoming HTTP request. * - * @return {Boolean} Whether the connection is encrypted or not. + * @return Whether the connection is encrypted or not. * * @api private */ -export function hasEncryptedConnection(req) { - return Boolean(req.connection.encrypted || req.connection.pair); +export function hasEncryptedConnection( + req: httpNative.IncomingMessage, +): boolean { + return Boolean( + // req.connection.pair probably does not exist anymore + (req.connection as tls.TLSSocket).encrypted || (req.connection as any).pair, + ); } /** * Rewrites or removes the domain of a cookie header * - * @param {String|Array} Header - * @param {Object} Config, mapping of domain to rewritten domain. - * '*' key to match any domain, null value to remove the domain. + * @param header + * @param config, mapping of domain to rewritten domain. + * '*' key to match any domain, null value to remove the domain. * * @api private */ -export function rewriteCookieProperty(header, config, property) { +export function rewriteCookieProperty( + header: string, + config: Record, + property: string, +): string; +export function rewriteCookieProperty( + header: string | string[], + config: Record, + property: string, +): string | string[]; +export function rewriteCookieProperty( + header: string | string[], + config: Record, + property: string, +): string | string[] { if (Array.isArray(header)) { return header.map(function (headerElement) { return rewriteCookieProperty(headerElement, config, property); @@ -226,12 +273,12 @@ export function rewriteCookieProperty(header, config, property) { /** * Check the host and see if it potentially has a port in it (keep it simple) * - * @returns {Boolean} Whether we have one or not + * @returns Whether we have one or not * * @api private */ -export function hasPort(host: string) { - return !!~host.indexOf(":"); +export function hasPort(host: string | null | undefined): boolean { + return host ? !!~host.indexOf(":") : false; } /** @@ -239,12 +286,15 @@ export function hasPort(host: string) { * * Ported from https://github.com/unshiftio/requires-port/blob/master/index.js * - * @returns {Boolean} Whether the port is required for the protocol + * @returns Whether the port is required for the protocol * * @api private */ -export function requiresPort(_port: string, _protocol: string) { - const protocol = _protocol.split(":")[0]; +export function requiresPort( + _port: string | number, + _protocol: string | undefined, +): boolean { + const protocol = _protocol?.split(":")[0]; const port = +_port; if (!port) return false; diff --git a/src/middleware/_utils.ts b/src/middleware/_utils.ts index acd4796..7dd9d35 100644 --- a/src/middleware/_utils.ts +++ b/src/middleware/_utils.ts @@ -1,22 +1,31 @@ import type { IncomingMessage, OutgoingMessage } from "node:http"; +import type { Socket } from "node:net"; import type { ProxyServer } from "../server"; -import type { ProxyServerOptions } from "../types"; +import type { ProxyServerOptions, ProxyTargetDetailed } from "../types"; -export type ProxyMiddleware = ( +export type ResOfType = T extends "ws" + ? T extends "web" + ? OutgoingMessage | Socket + : Socket + : T extends "web" + ? OutgoingMessage + : never; + +export type ProxyMiddleware = ( req: IncomingMessage, - res: OutgoingMessage, - opts?: ProxyServerOptions & { target: URL; forward: URL }, - server?: ProxyServer, + res: T, + opts: ProxyServerOptions & { + target: URL | ProxyTargetDetailed; + forward: URL; + }, + server: ProxyServer, head?: Buffer, - callback?: ( - err: any, - req: IncomingMessage, - socket: OutgoingMessage, - url?: any, - ) => void, + callback?: (err: any, req: IncomingMessage, socket: T, url?: any) => void, ) => void | true; -export function defineProxyMiddleware(m: ProxyMiddleware) { +export function defineProxyMiddleware< + T extends OutgoingMessage | Socket = OutgoingMessage, +>(m: ProxyMiddleware) { return m; } @@ -24,7 +33,10 @@ export type ProxyOutgoingMiddleware = ( req: IncomingMessage, res: OutgoingMessage, proxyRes: IncomingMessage, - opts?: ProxyServerOptions & { target: URL; forward: URL }, + opts: ProxyServerOptions & { + target: URL | ProxyTargetDetailed; + forward: URL; + }, ) => void | true; export function defineProxyOutgoingMiddleware(m: ProxyOutgoingMiddleware) { diff --git a/src/middleware/web-incoming.ts b/src/middleware/web-incoming.ts index 16600c3..cfc1f7c 100644 --- a/src/middleware/web-incoming.ts +++ b/src/middleware/web-incoming.ts @@ -1,10 +1,12 @@ -import httpNative from "node:http"; -import httpsNative from "node:https"; +import type { ClientRequest, OutgoingMessage } from "node:http"; +import type { ProxyTargetDetailed } from "../types"; +import nodeHTTP from "node:http"; +import nodeHTTPS from "node:https"; import { getPort, hasEncryptedConnection, setupOutgoing } from "../_utils"; import { webOutgoingMiddleware } from "./web-outgoing"; import { ProxyMiddleware, defineProxyMiddleware } from "./_utils"; -const nativeAgents = { http: httpNative, https: httpsNative }; +const nativeAgents = { http: nodeHTTP, https: nodeHTTPS }; /** * Sets `content-length` to '0' if request is of DELETE type. @@ -43,7 +45,7 @@ export const XHeaders = defineProxyMiddleware((req, res, options) => { proto: encrypted ? "https" : "http", }; - for (const header of ["for", "port", "proto"]) { + for (const header of ["for", "port", "proto"] as const) { req.headers["x-forwarded-" + header] = (req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + @@ -95,7 +97,7 @@ export const stream = defineProxyMiddleware( ).request(setupOutgoing(options.ssl || {}, options, req)); // Enable developers to modify the proxyReq before headers are sent - proxyReq.on("socket", (socket) => { + proxyReq.on("socket", (_socket) => { if (server && !proxyReq.getHeader("expect")) { server.emit("proxyReq", proxyReq, req, res, options); } @@ -119,9 +121,15 @@ export const stream = defineProxyMiddleware( req.on("error", proxyError); proxyReq.on("error", proxyError); - function createErrorHandler(proxyReq, url) { - return function proxyError(err) { - if (req.socket.destroyed && err.code === "ECONNRESET") { + function createErrorHandler( + proxyReq: ClientRequest, + url: URL | ProxyTargetDetailed, + ) { + return function proxyError(err: Error) { + if ( + req.socket.destroyed && + (err as NodeJS.ErrnoException).code === "ECONNRESET" + ) { server.emit("econnreset", err, req, res, url); return proxyReq.abort(); } @@ -173,9 +181,5 @@ export const stream = defineProxyMiddleware( }, ); -export const webIncomingMiddleware: readonly ProxyMiddleware[] = [ - deleteLength, - timeout, - XHeaders, - stream, -] as const; +export const webIncomingMiddleware: readonly ProxyMiddleware[] = + [deleteLength, timeout, XHeaders, stream] as const; diff --git a/src/middleware/web-outgoing.ts b/src/middleware/web-outgoing.ts index 90cdddb..e124c6d 100644 --- a/src/middleware/web-outgoing.ts +++ b/src/middleware/web-outgoing.ts @@ -38,7 +38,10 @@ export const setRedirectHostRewrite = defineProxyOutgoingMiddleware( proxyRes.headers.location && redirectRegex.test(String(proxyRes.statusCode)) ) { - const target = new URL(options.target); + const target = + options.target instanceof URL + ? options.target + : new URL(options.target as string | URL); // TODO: handle legacy url? const u = new URL(proxyRes.headers.location); // Make sure the redirected host matches the target host before rewriting @@ -48,7 +51,7 @@ export const setRedirectHostRewrite = defineProxyOutgoingMiddleware( if (options.hostRewrite) { u.host = options.hostRewrite; - } else if (options.autoRewrite) { + } else if (options.autoRewrite && req.headers.host) { u.host = req.headers.host; } if (options.protocolRewrite) { @@ -73,11 +76,23 @@ export const setRedirectHostRewrite = defineProxyOutgoingMiddleware( */ export const writeHeaders = defineProxyOutgoingMiddleware( (req, res, proxyRes, options) => { - let rewriteCookieDomainConfig = options.cookieDomainRewrite; - let rewriteCookiePathConfig = options.cookiePathRewrite; + const rewriteCookieDomainConfig = + typeof options.cookieDomainRewrite === "string" + ? // also test for '' + { "*": options.cookieDomainRewrite } + : options.cookieDomainRewrite; + const rewriteCookiePathConfig = + typeof options.cookiePathRewrite === "string" + ? // also test for '' + { "*": options.cookiePathRewrite } + : options.cookiePathRewrite; + const preserveHeaderKeyCase = options.preserveHeaderKeyCase; - let rawHeaderKeyMap; - const setHeader = function (key, header) { + let rawHeaderKeyMap: Record | undefined; + const setHeader = function ( + key: string, + header: string | string[] | undefined, + ) { if (header === undefined) { return; } @@ -94,16 +109,6 @@ export const writeHeaders = defineProxyOutgoingMiddleware( res.setHeader(String(key).trim(), header); }; - if (typeof rewriteCookieDomainConfig === "string") { - // also test for '' - rewriteCookieDomainConfig = { "*": rewriteCookieDomainConfig }; - } - - if (typeof rewriteCookiePathConfig === "string") { - // also test for '' - rewriteCookiePathConfig = { "*": rewriteCookiePathConfig }; - } - // message.rawHeaders is added in: v0.11.6 // https://nodejs.org/api/http.html#http_message_rawheaders if (preserveHeaderKeyCase && proxyRes.rawHeaders !== undefined) { diff --git a/src/middleware/ws-incoming.ts b/src/middleware/ws-incoming.ts index a621b6a..81522a9 100644 --- a/src/middleware/ws-incoming.ts +++ b/src/middleware/ws-incoming.ts @@ -1,5 +1,5 @@ -import http from "node:http"; -import https from "node:https"; +import nodeHTTP from "node:http"; +import nodeHTTPS from "node:https"; import { getPort, hasEncryptedConnection, @@ -8,52 +8,60 @@ import { setupSocket, } from "../_utils"; import { ProxyMiddleware, defineProxyMiddleware } from "./_utils"; +import type { Socket } from "node:net"; /** * WebSocket requests must have the `GET` method and * the `upgrade:websocket` header */ -export const checkMethodAndHeader = defineProxyMiddleware((req, socket) => { - if (req.method !== "GET" || !req.headers.upgrade) { - socket.destroy(); - return true; - } - - if (req.headers.upgrade.toLowerCase() !== "websocket") { - socket.destroy(); - return true; - } -}); +export const checkMethodAndHeader = defineProxyMiddleware( + (req, socket) => { + if (req.method !== "GET" || !req.headers.upgrade) { + socket.destroy(); + return true; + } + + if (req.headers.upgrade.toLowerCase() !== "websocket") { + socket.destroy(); + return true; + } + }, +); /** * Sets `x-forwarded-*` headers if specified in config. */ -export const XHeaders = defineProxyMiddleware((req, socket, options) => { - if (!options.xfwd) { - return; - } - - const values = { - for: req.connection.remoteAddress || req.socket.remoteAddress, - port: getPort(req), - proto: hasEncryptedConnection(req) ? "wss" : "ws", - }; - - for (const header of ["for", "port", "proto"]) { - req.headers["x-forwarded-" + header] = - (req.headers["x-forwarded-" + header] || "") + - (req.headers["x-forwarded-" + header] ? "," : "") + - values[header]; - } -}); +export const XHeaders = defineProxyMiddleware( + (req, socket, options) => { + if (!options.xfwd) { + return; + } + + const values = { + for: req.connection.remoteAddress || req.socket.remoteAddress, + port: getPort(req), + proto: hasEncryptedConnection(req) ? "wss" : "ws", + }; + + for (const header of ["for", "port", "proto"] as const) { + req.headers["x-forwarded-" + header] = + (req.headers["x-forwarded-" + header] || "") + + (req.headers["x-forwarded-" + header] ? "," : "") + + values[header]; + } + }, +); /** * Does the actual proxying. Make the request and upgrade it * send the Switching Protocols request and pipe the sockets. */ -export const stream = defineProxyMiddleware( +export const stream = defineProxyMiddleware( (req, socket, options, server, head, callback) => { - const createHttpHeader = function (line, headers) { + const createHttpHeader = function ( + line: string, + headers: nodeHTTP.OutgoingHttpHeaders, + ) { return ( Object.keys(headers) // eslint-disable-next-line unicorn/no-array-reduce @@ -80,12 +88,11 @@ export const stream = defineProxyMiddleware( setupSocket(socket); if (head && head.length > 0) { - // @ts-expect-error socket.unshift(head); } const proxyReq = ( - isSSL.test(options.target.protocol) ? https : http + isSSL.test(options.target.protocol || "http") ? nodeHTTPS : nodeHTTP ).request(setupOutgoing(options.ssl || {}, options, req)); // Enable developers to modify the proxyReq before headers are sent @@ -162,7 +169,7 @@ export const stream = defineProxyMiddleware( }, ); -export const websocketIncomingMiddleware: readonly ProxyMiddleware[] = [ +export const websocketIncomingMiddleware: readonly ProxyMiddleware[] = [ checkMethodAndHeader, XHeaders, stream, diff --git a/src/server.ts b/src/server.ts index 38de66d..488eee8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -5,14 +5,17 @@ import { EventEmitter } from "node:events"; import { webIncomingMiddleware } from "./middleware/web-incoming"; import { websocketIncomingMiddleware } from "./middleware/ws-incoming"; import { ProxyServerOptions } from "./types"; -import { ProxyMiddleware } from "./middleware/_utils"; +import { ProxyMiddleware, type ResOfType } from "./middleware/_utils"; +import type net from "node:net"; // eslint-disable-next-line unicorn/prefer-event-target export class ProxyServer extends EventEmitter { private _server?: http.Server | https.Server; - _webPasses: ProxyMiddleware[] = [...webIncomingMiddleware]; - _wsPasses: ProxyMiddleware[] = [...websocketIncomingMiddleware]; + _webPasses: ProxyMiddleware[] = [ + ...webIncomingMiddleware, + ]; + _wsPasses: ProxyMiddleware[] = [...websocketIncomingMiddleware]; options: ProxyServerOptions; @@ -25,7 +28,7 @@ export class ProxyServer extends EventEmitter { ws: ( req: http.IncomingMessage, - socket: http.OutgoingMessage, + socket: net.Socket, opts: ProxyServerOptions, head?: any, ) => Promise; @@ -49,8 +52,8 @@ export class ProxyServer extends EventEmitter { * @param port - Port to listen on * @param hostname - The hostname to listen on */ - listen(port: number, hostname?: string) { - const closure = (req, res) => { + listen(port: number, hostname: string) { + const closure = (req: http.IncomingMessage, res: http.ServerResponse) => { this.web(req, res); }; @@ -85,11 +88,15 @@ export class ProxyServer extends EventEmitter { } } - before(type: "ws" | "web", passName: string, pass: ProxyMiddleware) { + before( + type: Type, + passName: string, + pass: ProxyMiddleware>, + ) { if (type !== "ws" && type !== "web") { throw new Error("type must be `web` or `ws`"); } - const passes = type === "ws" ? this._wsPasses : this._webPasses; + const passes = this._getPasses(type); let i: false | number = false; for (const [idx, v] of passes.entries()) { if (v.name === passName) { @@ -102,11 +109,15 @@ export class ProxyServer extends EventEmitter { passes.splice(i, 0, pass); } - after(type: "ws" | "web", passName: string, pass: ProxyMiddleware) { + after( + type: Type, + passName: string, + pass: ProxyMiddleware>, + ) { if (type !== "ws" && type !== "web") { throw new Error("type must be `web` or `ws`"); } - const passes = type === "ws" ? this._wsPasses : this._webPasses; + const passes = this._getPasses(type); let i: boolean | number = false; for (const [idx, v] of passes.entries()) { if (v.name === passName) { @@ -118,6 +129,15 @@ export class ProxyServer extends EventEmitter { } passes.splice(i++, 0, pass); } + + /** @internal */ + _getPasses( + type: Type, + ): ProxyMiddleware>[] { + return (type === "ws" + ? this._wsPasses + : this._webPasses) as unknown as ProxyMiddleware>[]; + } } /** @@ -140,29 +160,32 @@ export function createProxyServer(options: ProxyServerOptions = {}) { // --- Internal --- -function _createProxyFn(type: "web" | "ws", server: ProxyServer) { +function _createProxyFn( + type: Type, + server: ProxyServer, +) { + type Res = ResOfType; return function ( + this: ProxyServer, req: http.IncomingMessage, - res: http.OutgoingMessage, - opts: ProxyServerOptions, - head: any, + res: Res, + opts?: ProxyServerOptions, + head?: any, ): Promise { const requestOptions = { ...opts, ...server.options }; - for (const key of ["target", "forward"]) { + for (const key of ["target", "forward"] as const) { if (typeof requestOptions[key] === "string") { requestOptions[key] = new URL(requestOptions[key]); } } if (!requestOptions.target && !requestOptions.forward) { - return this.emit( - "error", - new Error("Must provide a proper URL as target"), - ); + this.emit("error", new Error("Must provide a proper URL as target")); + return Promise.resolve(); } - let _resolve: () => void; + let _resolve!: () => void; let _reject: (error: any) => void; const callbackPromise = new Promise((resolve, reject) => { _resolve = resolve; @@ -176,7 +199,7 @@ function _createProxyFn(type: "web" | "ws", server: ProxyServer) { _reject(error); }); - for (const pass of type === "ws" ? server._wsPasses : server._webPasses) { + for (const pass of server._getPasses(type)) { const stop = pass( req, res, diff --git a/src/types.ts b/src/types.ts index 23fbb65..4cb53d9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,5 @@ import type * as stream from "node:stream"; +import type { Url as LegacyURL } from "node:url"; export interface ProxyTargetDetailed { host: string; @@ -15,15 +16,17 @@ export interface ProxyTargetDetailed { secureProtocol?: string; } -type ProxyTarget = ProxyTargetUrl | ProxyTargetDetailed; - -type ProxyTargetUrl = string | Partial; +export type ProxyTarget = + | string + | URL + | Partial + | ProxyTargetDetailed; export interface ProxyServerOptions { - /** URL string to be parsed with the url module. */ + /** URL string to be parsed. */ target?: ProxyTarget; - /** URL string to be parsed with the url module. */ - forward?: ProxyTargetUrl; + /** URL string to be parsed. */ + forward?: Exclude; /** Object to be passed to http(s).request. */ agent?: any; /** Object to be passed to https.createServer(). */ diff --git a/test/_utils.test.ts b/test/_utils.test.ts index ea7e16a..6237ca5 100644 --- a/test/_utils.test.ts +++ b/test/_utils.test.ts @@ -20,6 +20,7 @@ describe("lib/http-proxy/common.js", () => { socketPath: "are", port: "you", }, + // @ts-expect-error headers: { fizz: "bang", overwritten: true }, localAddress: "local.address", auth: "username:pass", @@ -65,7 +66,7 @@ describe("lib/http-proxy/common.js", () => { method: "i", url: "am", headers: { pro: "xy", overwritten: false }, - }, + } as any, ); expect(outgoing.headers.connection).to.eql("upgrade"); }); @@ -81,14 +82,14 @@ describe("lib/http-proxy/common.js", () => { hostname: "how", socketPath: "are", port: "you", - }, + } as any, headers: { connection: "keep-alive, upgrade" }, // this is what Firefox sets }, { method: "i", url: "am", headers: { pro: "xy", overwritten: false }, - }, + } as any, ); expect(outgoing.headers.connection).to.eql("keep-alive, upgrade"); }); @@ -112,7 +113,7 @@ describe("lib/http-proxy/common.js", () => { method: "i", url: "am", headers: { pro: "xy", overwritten: false }, - }, + } as any, ); expect(outgoing.headers.connection).to.eql("close"); }); @@ -135,18 +136,16 @@ describe("lib/http-proxy/common.js", () => { method: "i", url: "am", headers: { pro: "xy", overwritten: false }, - }, + } as any, ); expect(outgoing.headers.connection).to.eql("close"); }); it("should set the agent to false if none is given", () => { const outgoing = {} as any; - common.setupOutgoing( - outgoing, - { target: "http://localhost" }, - { url: "/" }, - ); + common.setupOutgoing(outgoing, { target: "http://localhost" }, { + url: "/", + } as any); expect(outgoing.agent).to.eql(false); }); @@ -167,7 +166,7 @@ describe("lib/http-proxy/common.js", () => { method: "i", url: "am", headers: { pro: "xy" }, - }, + } as any, ); expect(outgoing.host).to.eql("how"); @@ -184,11 +183,9 @@ describe("lib/http-proxy/common.js", () => { it("should keep the original target path in the outgoing path", () => { const outgoing = {} as any; - common.setupOutgoing( - outgoing, - { target: { path: "some-path" } }, - { url: "am" }, - ); + common.setupOutgoing(outgoing, { target: { path: "some-path" } }, { + url: "am", + } as any); expect(outgoing.path).to.eql("some-path/am"); }); @@ -205,7 +202,7 @@ describe("lib/http-proxy/common.js", () => { }, { url: "am", - }, + } as any, "forward", ); @@ -222,7 +219,7 @@ describe("lib/http-proxy/common.js", () => { host: "whatever.com", }, }, - { url: "/" }, + { url: "/" } as any, ); expect(outgoing.port).to.eql(443); @@ -236,7 +233,7 @@ describe("lib/http-proxy/common.js", () => { target: { path: "hellothere" }, prependPath: false, }, - { url: "hi" }, + { url: "hi" } as any, ); expect(outgoing.path).to.eql("/hi"); @@ -249,7 +246,7 @@ describe("lib/http-proxy/common.js", () => { { target: { path: "/forward" }, }, - { url: "/static/path" }, + { url: "/static/path" } as any, ); expect(outgoing.path).to.eql("/forward/static/path"); @@ -262,7 +259,9 @@ describe("lib/http-proxy/common.js", () => { { target: { path: "/forward" }, }, - { url: "/?foo=bar//&target=http://foobar.com/?a=1%26b=2&other=2" }, + { + url: "/?foo=bar//&target=http://foobar.com/?a=1%26b=2&other=2", + } as any, ); expect(outgoing.path).to.eql( @@ -279,10 +278,10 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse("http://sometarget.com:80"), + target: URL.parse("http://sometarget.com:80")!, toProxy: true, }, - { url: google }, + { url: google } as any, ); expect(outgoing.path).to.eql("/" + google); @@ -295,10 +294,10 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse("http://sometarget.com:80"), + target: URL.parse("http://sometarget.com:80")!, toProxy: true, }, - { url: google }, + { url: google } as any, ); expect(outgoing.path).to.eql("/" + google); @@ -311,10 +310,10 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse("http://sometarget.com:80"), + target: URL.parse("http://sometarget.com:80")!, toProxy: true, }, - { url: google }, + { url: google } as any, ); expect(outgoing.path).to.eql("/" + google); @@ -327,10 +326,10 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse(myEndpoint), + target: URL.parse(myEndpoint)!, ignorePath: true, }, - { url: "/more/crazy/pathness" }, + { url: "/more/crazy/pathness" } as any, ); expect(outgoing.path).to.eql("/some/crazy/path/whoooo"); @@ -342,11 +341,11 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse(myEndpoint), + target: URL.parse(myEndpoint)!, ignorePath: true, prependPath: false, }, - { url: "/more/crazy/pathness" }, + { url: "/more/crazy/pathness" } as any, ); expect(outgoing.path).to.eql("/"); @@ -360,10 +359,10 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse(myEndpoint), + target: URL.parse(myEndpoint)!, changeOrigin: true, }, - { url: "/" }, + { url: "/" } as any, ); expect(outgoing.headers.host).to.eql("mycouch.com:6984"); @@ -381,7 +380,7 @@ describe("lib/http-proxy/common.js", () => { }, changeOrigin: true, }, - { url: "/" }, + { url: "/" } as any, ); expect(outgoing.headers.host).to.eql("mycouch.com:6984"); }); @@ -410,7 +409,7 @@ describe("lib/http-proxy/common.js", () => { { method: "i", url: "am", - }, + } as any, ); expect(outgoing.pfx).eql("my-pfx"); @@ -427,10 +426,11 @@ describe("lib/http-proxy/common.js", () => { common.setupOutgoing( outgoing, { - target: URL.parse("https://whooooo.com"), + target: "https://whooooo.com", + // @ts-expect-error method: "POST", }, - { method: "GET", url: "" }, + { method: "GET", url: "" } as any, ); expect(outgoing.method).eql("POST"); @@ -439,7 +439,9 @@ describe("lib/http-proxy/common.js", () => { // url.parse('').path => null it("should not pass null as last arg to #urlJoin", () => { const outgoing = {} as any; - common.setupOutgoing(outgoing, { target: { path: "" } }, { url: "" }); + common.setupOutgoing(outgoing, { target: { path: "" } }, { + url: "", + } as any); expect(outgoing.path).toBe("/"); // leading slash is new in httpxy }); @@ -463,7 +465,7 @@ describe("lib/http-proxy/common.js", () => { socketConfig.keepalive = bol; }, }; - const returnValue = common.setupSocket(stubSocket); + const returnValue = common.setupSocket(stubSocket as any); expect(socketConfig.timeout).to.eql(0); expect(socketConfig.nodelay).to.eql(true); diff --git a/tsconfig.json b/tsconfig.json index 462b4d6..e9588d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "module": "ESNext", "moduleResolution": "Node", "esModuleInterop": true, - "strict": false + "strict": true }, "include": ["src"] }