diff --git a/package-lock.json b/package-lock.json index 655b04a07..4f4f74ad2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,11 +41,11 @@ "elliptic": "6.5.7", "escape-goat": "3.0.0", "evt": "1.10.1", - "express": "^4.21.1", + "express": "4.21.1", "fastify": "4.28.1", "fastify-metrics": "11.0.0", "getopts": "2.3.0", - "http-proxy-middleware": "^2.0.7", + "http-proxy-middleware": "2.0.7", "jsonc-parser": "3.0.0", "jsonrpc-lite": "2.2.0", "lru-cache": "6.0.0", @@ -69,6 +69,7 @@ "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", + "undici": "6.21.0", "uuid": "8.3.2", "ws": "7.5.10", "zone-file": "2.0.0-beta.3" @@ -171,6 +172,19 @@ "undici": "^5.25.4" } }, + "node_modules/@actions/http-client/node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/@actions/io": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", @@ -1255,6 +1269,18 @@ "undici": "^5.19.1" } }, + "node_modules/@fastify/reply-from/node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/@fastify/swagger": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/@fastify/swagger/-/swagger-8.15.0.tgz", @@ -16928,14 +16954,12 @@ "dev": true }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", + "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "license": "MIT", "engines": { - "node": ">=14.0" + "node": ">=18.17" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index 89bd0212d..06bbae90d 100644 --- a/package.json +++ b/package.json @@ -147,6 +147,7 @@ "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", + "undici": "6.21.0", "uuid": "8.3.2", "ws": "7.5.10", "zone-file": "2.0.0-beta.3" diff --git a/src/api/routes/core-node-rpc-proxy.ts b/src/api/routes/core-node-rpc-proxy.ts index d1e40999c..37b3e46bf 100644 --- a/src/api/routes/core-node-rpc-proxy.ts +++ b/src/api/routes/core-node-rpc-proxy.ts @@ -152,9 +152,7 @@ export const CoreNodeRpcProxyRouter: FastifyPluginAsync< upstream: `http://${stacksNodeRpcEndpoint}`, rewritePrefix: '/v2', http2: false, - // Use the `node:http` agent for requests https://github.com/fastify/fastify-reply-from?tab=readme-ov-file#globalagent globalAgent: true, - http: {}, preValidation: async (req, reply) => { if (getReqUrl(req).pathname !== '/v2/transactions') { return; diff --git a/tests/api/v2-proxy.test.ts b/tests/api/v2-proxy.test.ts index f96e9e20e..8f97e87b0 100644 --- a/tests/api/v2-proxy.test.ts +++ b/tests/api/v2-proxy.test.ts @@ -9,6 +9,7 @@ import * as nock from 'nock'; import { DbBlock } from '../../src/datastore/common'; import { PgWriteStore } from '../../src/datastore/pg-write-store'; import { migrate } from '../utils/test-helpers'; +import { MockAgent, setGlobalDispatcher, getGlobalDispatcher } from 'undici'; describe('v2-proxy tests', () => { let db: PgWriteStore; @@ -39,6 +40,12 @@ describe('v2-proxy tests', () => { ); return [, () => restoreEnvVars()] as const; }, + () => { + const agent = new MockAgent(); + const originalAgent = getGlobalDispatcher(); + setGlobalDispatcher(agent); + return [agent, () => setGlobalDispatcher(originalAgent)] as const; + }, async () => { const apiServer = await startApiServer({ datastore: db, @@ -46,7 +53,7 @@ describe('v2-proxy tests', () => { }); return [apiServer, apiServer.terminate] as const; }, - async (_, api) => { + async (_, mockAgent, api) => { const primaryStubbedResponse = { cost_scalar_change_by_byte: 0.00476837158203125, estimated_cost: { @@ -77,12 +84,17 @@ describe('v2-proxy tests', () => { transaction_payload: '021af942874ce525e87f21bbe8c121b12fac831d02f4086765742d696e666f0b7570646174652d696e666f00000000', }; - nock(`http://${primaryProxyEndpoint}`) - .post('/v2/fees/transaction') - .once() + + mockAgent + .get(`http://${primaryProxyEndpoint}`) + .intercept({ + path: '/v2/fees/transaction', + method: 'POST', + }) .reply(200, JSON.stringify(primaryStubbedResponse), { - 'Content-Type': 'application/json', + headers: { 'Content-Type': 'application/json' }, }); + const postTxReq = await supertest(api.server) .post(`/v2/fees/transaction`) .set('Content-Type', 'application/json')