diff --git a/package-lock.json b/package-lock.json index d9c7832..f61e33b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@humanwhocodes/env": "^3.0.2", - "@krutoo/fetch-tools": "^0.0.12", + "@krutoo/fetch-tools": "^0.0.15", "@opentelemetry/api": "^1.4.1", "@opentelemetry/exporter-prometheus": "^0.38.0", "@opentelemetry/exporter-trace-otlp-http": "^0.39.1", @@ -26,6 +26,7 @@ "accepts": "^1.3.8", "dotenv": "^16.3.1", "express": "^4.18.2", + "http-proxy-middleware": "^3.0.0", "jsesc": "^3.0.2", "middleware-axios": "^2.1.6", "pino": "^8.14.1", @@ -3673,9 +3674,9 @@ } }, "node_modules/@krutoo/fetch-tools": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@krutoo/fetch-tools/-/fetch-tools-0.0.12.tgz", - "integrity": "sha512-qooqX0k7DoJF49j/9X6WnveUPpjSwlvBdko2LIrV2BcUhezZZ+a4etBs8gKMmaPZytZ7xF/JuFVlk4O7f8zjxA==" + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@krutoo/fetch-tools/-/fetch-tools-0.0.15.tgz", + "integrity": "sha512-MCPqnnWvF6jlbiwFmvVrkxATxWfQIUWMyBxvEj+2TueIBR8W0DQFpU3Is4X1Cie0oWzjBaaT8e3BfuYrVcGQsA==" }, "node_modules/@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", @@ -4642,6 +4643,14 @@ "hoist-non-react-statics": "^3.3.0" } }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -5971,12 +5980,12 @@ "integrity": "sha512-tbaUB1QpTIj4cKY8c1rvNAvEQXA+ekzHmbe4jzNfW3QWsF9GnnP/BRWyl6/qqS53heoYJ93naaFcm/jooONH8g==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -5984,7 +5993,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -6020,7 +6029,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -6422,6 +6430,14 @@ "safe-buffer": "~5.1.1" } }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -7824,6 +7840,11 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -7881,16 +7902,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -7921,14 +7942,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -8067,7 +8080,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -8151,7 +8163,6 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], - "peer": true, "engines": { "node": ">=4.0" }, @@ -8734,6 +8745,19 @@ "node": ">= 0.8" } }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -8748,6 +8772,33 @@ "node": ">= 6" } }, + "node_modules/http-proxy-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", + "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", + "dependencies": { + "@types/http-proxy": "^1.17.10", + "debug": "^4.3.4", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.5" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -9074,7 +9125,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9128,7 +9178,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -9161,7 +9210,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -12508,7 +12556,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -13022,7 +13069,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -13495,9 +13541,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -13852,8 +13898,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/reselect": { "version": "4.1.8", @@ -15052,7 +15097,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -18488,9 +18532,9 @@ } }, "@krutoo/fetch-tools": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@krutoo/fetch-tools/-/fetch-tools-0.0.12.tgz", - "integrity": "sha512-qooqX0k7DoJF49j/9X6WnveUPpjSwlvBdko2LIrV2BcUhezZZ+a4etBs8gKMmaPZytZ7xF/JuFVlk4O7f8zjxA==" + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@krutoo/fetch-tools/-/fetch-tools-0.0.15.tgz", + "integrity": "sha512-MCPqnnWvF6jlbiwFmvVrkxATxWfQIUWMyBxvEj+2TueIBR8W0DQFpU3Is4X1Cie0oWzjBaaT8e3BfuYrVcGQsA==" }, "@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", @@ -19206,6 +19250,14 @@ "hoist-non-react-statics": "^3.3.0" } }, + "@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "requires": { + "@types/node": "*" + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -20260,12 +20312,12 @@ "integrity": "sha512-tbaUB1QpTIj4cKY8c1rvNAvEQXA+ekzHmbe4jzNfW3QWsF9GnnP/BRWyl6/qqS53heoYJ93naaFcm/jooONH8g==" }, "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "requires": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -20273,7 +20325,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -20307,7 +20359,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -20589,6 +20640,11 @@ "safe-buffer": "~5.1.1" } }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -21614,6 +21670,11 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -21656,16 +21717,16 @@ } }, "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -21693,11 +21754,6 @@ "vary": "~1.1.2" }, "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -21811,7 +21867,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -21875,8 +21930,7 @@ "follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "peer": true + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "for-each": { "version": "0.3.3", @@ -22302,6 +22356,16 @@ "toidentifier": "1.0.1" } }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, "http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -22313,6 +22377,26 @@ "debug": "4" } }, + "http-proxy-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", + "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", + "requires": { + "@types/http-proxy": "^1.17.10", + "debug": "^4.3.4", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.5" + }, + "dependencies": { + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + } + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -22532,8 +22616,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finalizationregistry": { "version": "1.0.2", @@ -22569,7 +22652,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -22589,8 +22671,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { "version": "1.0.7", @@ -25112,7 +25193,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -25485,8 +25565,7 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pify": { "version": "4.0.1", @@ -25816,9 +25895,9 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "requires": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -26076,8 +26155,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "reselect": { "version": "4.1.8", @@ -26982,7 +27060,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } diff --git a/package.json b/package.json index da8c29f..f3d27ff 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ }, "dependencies": { "@humanwhocodes/env": "^3.0.2", - "@krutoo/fetch-tools": "^0.0.12", + "@krutoo/fetch-tools": "^0.0.15", "@opentelemetry/api": "^1.4.1", "@opentelemetry/exporter-prometheus": "^0.38.0", "@opentelemetry/exporter-trace-otlp-http": "^0.39.1", @@ -63,6 +63,7 @@ "accepts": "^1.3.8", "dotenv": "^16.3.1", "express": "^4.18.2", + "http-proxy-middleware": "^3.0.0", "jsesc": "^3.0.2", "middleware-axios": "^2.1.6", "pino": "^8.14.1", diff --git a/src/http/index.ts b/src/http/index.ts index 5cf3784..e88ee63 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -13,6 +13,12 @@ export type { ResponseErrorInit, } from './types'; export { configureFetch, applyMiddleware } from '@krutoo/fetch-tools'; -export { log, defaultHeaders, validateStatus } from '@krutoo/fetch-tools/middleware'; +export { + type ProxyOptions, + log, + proxy, + defaultHeaders, + validateStatus, +} from '@krutoo/fetch-tools/middleware'; export { StatusError, ResponseError } from './errors'; export { FetchUtil } from './utils'; diff --git a/src/preset/bun/index.ts b/src/preset/bun/index.ts index 414dec2..b420305 100644 --- a/src/preset/bun/index.ts +++ b/src/preset/bun/index.ts @@ -43,6 +43,7 @@ export function PresetBun(customize?: PresetTuner) { preset.set(KnownToken.Http.serve, provideServe); preset.set(KnownToken.Http.Serve.serviceRoutes, provideServiceRoutes); preset.set(KnownToken.Http.Serve.middleware, provideServeMiddleware); + preset.set(KnownToken.Http.Serve.Proxy.config, () => null); // http api preset.set(KnownToken.Http.Api.knownHosts, provideKnownHttpApiHosts); diff --git a/src/preset/bun/providers/serve.ts b/src/preset/bun/providers/serve.ts index b42e2f6..0457e47 100644 --- a/src/preset/bun/providers/serve.ts +++ b/src/preset/bun/providers/serve.ts @@ -1,31 +1,47 @@ /* eslint-disable require-jsdoc, jsdoc/require-jsdoc */ import { Resolve } from '../../../di'; import { KnownToken } from '../../../tokens'; -import { Handler } from '../../../http'; -import { route, router } from '@krutoo/fetch-tools'; +import { Handler, proxy } from '../../../http'; +import { router, applyMiddleware } from '@krutoo/fetch-tools'; import { applyServerMiddleware } from '../../server/utils/apply-server-middleware'; export function provideServe(resolve: Resolve): Handler { - const middleware = resolve(KnownToken.Http.Serve.middleware); - const routes = resolve(KnownToken.Http.Serve.routes); + const config = resolve(KnownToken.Config.base); + const pageRoutes = resolve(KnownToken.Http.Serve.pageRoutes); const serviceRoutes = resolve(KnownToken.Http.Serve.serviceRoutes); + const middleware = resolve(KnownToken.Http.Serve.middleware); + const proxyConfig = resolve(KnownToken.Http.Serve.Proxy.config); + + const enhance = + config.env === 'development' && proxyConfig + ? applyMiddleware( + ...(Array.isArray(proxyConfig) ? proxyConfig.map(proxy) : [proxy(proxyConfig)]), + ) + : identity; - const enhance = applyServerMiddleware(...middleware); + const builder = router.builder(); - return router( - // маршруты с промежуточными слоями - ...routes.map(([pattern, handler]) => { - const enhancedHandler = enhance(handler); + // маршруты с промежуточными слоями + for (const [pattern, handler] of pageRoutes) { + const path = typeof pattern === 'string' ? pattern : pattern.path; + const method = typeof pattern === 'string' ? 'get' : pattern.method; + const pageHandler = applyServerMiddleware(...middleware)(handler); - return route.get(pattern, request => enhancedHandler(request, { events: new EventTarget() })); - }), + builder[method](path, request => pageHandler(request, { events: new EventTarget() })); + } - // @todo вместо routes обрабатывать pageRoutes с помощью route.get() из новой версии fetch-tools (для явности) - // @todo также добавить apiRoutes и обрабатывать их с помощью с помощью route()? + // служебные маршруты (к ним не применяются промежуточные слои) + for (const [pattern, handler] of serviceRoutes) { + const path = typeof pattern === 'string' ? pattern : pattern.path; + const method = typeof pattern === 'string' ? 'get' : pattern.method; + + builder[method](path, request => handler(request, { events: new EventTarget() })); + } + + // @todo также добавить apiRoutes? + return enhance(builder.build()); +} - // служебные маршруты (без промежуточных слоев) - ...serviceRoutes.map(([pattern, handler]) => - route(pattern, request => handler(request, { events: new EventTarget() })), - ), - ); +function identity(value: T): T { + return value; } diff --git a/src/preset/node/index.ts b/src/preset/node/index.ts index 2849b5e..86ea476 100644 --- a/src/preset/node/index.ts +++ b/src/preset/node/index.ts @@ -21,6 +21,7 @@ import { provideTracer } from './providers/tracer'; import { provideTracerProvider } from './providers/tracer-provider'; import { provideTracerProviderResource } from './providers/tracer-provider-resource'; import { provideMainExpressApp } from './providers/main-express-app'; +import { ExpressRouteList } from './types'; /** * Возвращает preset с зависимостями по умолчанию для frontend-микросервисов на Node.js. @@ -50,6 +51,7 @@ export function PresetNode(customize?: PresetTuner): Preset { // fetch preset.set(KnownToken.Http.fetch, provideFetch); preset.set(KnownToken.Http.Fetch.middleware, () => []); + preset.set(KnownToken.Http.Serve.Proxy.config, () => null); // axios preset.set(KnownToken.Axios.factory, provideAxiosFactory); @@ -58,9 +60,12 @@ export function PresetNode(customize?: PresetTuner): Preset { // express preset.set(KnownToken.Express.app, provideMainExpressApp); preset.set(KnownToken.Express.pageRoutes, () => []); - preset.set(KnownToken.Express.serviceRoutes, resolve => [ - ['/healthcheck', resolve(KnownToken.Express.Handlers.healthCheck)], - ]); + preset.set( + KnownToken.Express.serviceRoutes, + (resolve): ExpressRouteList => [ + ['/healthcheck', resolve(KnownToken.Express.Handlers.healthCheck)], + ], + ); preset.set(KnownToken.Express.middleware, resolve => [ resolve(KnownToken.Express.Middleware.request), resolve(KnownToken.Express.Middleware.log), @@ -91,6 +96,8 @@ export function PresetNode(customize?: PresetTuner): Preset { return preset; } +export type { ExpressHandlerContext, ExpressRouteList } from './types'; + // доступные утилиты export { getClientIp } from './utils/get-client-ip'; export { getForwardedHeaders } from './utils/get-forwarded-headers'; diff --git a/src/preset/node/providers/main-express-app.ts b/src/preset/node/providers/main-express-app.ts index 078f3b7..f980ef9 100644 --- a/src/preset/node/providers/main-express-app.ts +++ b/src/preset/node/providers/main-express-app.ts @@ -1,6 +1,7 @@ -import express from 'express'; import type { Resolve } from '../../../di'; import { KnownToken } from '../../../tokens'; +import express from 'express'; +import { createProxyMiddleware } from 'http-proxy-middleware'; /** * Провайдер основного express-приложения. @@ -8,24 +9,54 @@ import { KnownToken } from '../../../tokens'; * @return Основное express-приложение. */ export function provideMainExpressApp(resolve: Resolve): express.Application { + const config = resolve(KnownToken.Config.base); const pageRoutes = resolve(KnownToken.Express.pageRoutes); const serviceRoutes = resolve(KnownToken.Express.serviceRoutes); const middleware = resolve(KnownToken.Express.middleware); const endMiddleware = resolve(KnownToken.Express.endMiddleware); + const proxyConfig = resolve(KnownToken.Http.Serve.Proxy.config); const app = express(); + if (config.env === 'development' && proxyConfig) { + const proxyConfigs = Array.isArray(proxyConfig) ? proxyConfig : [proxyConfig]; + + for (const { target, filter } of proxyConfigs) { + // ВАЖНО: так как не можем предоставить web-интерфейс Request бросаем ошибку + if (typeof filter === 'function') { + throw new Error('Currently function is not supported for proxy "filter"'); + } + + const proxyPaths = Array.isArray(filter) ? filter : [filter]; + + app.use( + createProxyMiddleware({ + target, + changeOrigin: true, + pathFilter: inputPath => proxyPaths.some(proxyPath => inputPath.startsWith(proxyPath)), + }), + ); + } + } + // маршруты страниц for (const [routePath, routeHandler] of pageRoutes) { - app.use(routePath, middleware); - app.get(routePath, routeHandler); - app.use(routePath, endMiddleware); + const path = typeof routePath === 'string' ? routePath : routePath.path; + const method = typeof routePath === 'string' ? 'get' : routePath.method; + + app.use(path, middleware); + app[method](path, routeHandler); + app.use(path, endMiddleware); } // служебные маршруты (к ним не применяются промежуточные слои) for (const [routePath, routeHandler] of serviceRoutes) { - app.get(routePath, routeHandler); + const path = typeof routePath === 'string' ? routePath : routePath.path; + const method = typeof routePath === 'string' ? 'get' : routePath.method; + + app[method](path, routeHandler); } + // @todo также добавить apiRoutes? return app; } diff --git a/src/preset/node/types.ts b/src/preset/node/types.ts index bf85cfe..e858add 100644 --- a/src/preset/node/types.ts +++ b/src/preset/node/types.ts @@ -1,10 +1,13 @@ -import type { Request, Response, NextFunction } from 'express'; +import type express from 'express'; +import type { RouteInfo } from '../server/types'; /** * Контекст обработчика express. */ export interface ExpressHandlerContext { - readonly req: Request; - readonly res: Response; - readonly next: NextFunction; + readonly req: express.Request; + readonly res: express.Response; + readonly next: express.NextFunction; } + +export type ExpressRouteList = Array<[string | RouteInfo, express.Handler]>; diff --git a/src/preset/server/index.ts b/src/preset/server/index.ts index 216901e..dbce021 100644 --- a/src/preset/server/index.ts +++ b/src/preset/server/index.ts @@ -4,6 +4,8 @@ export type { ServerHandlerContext, PageResponseFormatter, PageResponseFormatResult, + RouteInfo, + RouteList, } from './types'; export { PAGE_HANDLER_EVENT_TYPE, PAGE_FORMAT_PRIORITY } from './constants'; diff --git a/src/preset/server/types.ts b/src/preset/server/types.ts index 4e43854..ea06d3c 100644 --- a/src/preset/server/types.ts +++ b/src/preset/server/types.ts @@ -39,3 +39,10 @@ export interface PageResponseFormatter { export interface RenderToString { (jsx: JSX.Element): string | Promise; } + +export interface RouteInfo { + method: 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head'; + path: string; +} + +export type RouteList = Array<[string | RouteInfo, ServerHandler]>; diff --git a/src/tokens.ts b/src/tokens.ts index b084a6d..082045b 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -13,11 +13,11 @@ import type { BasicTracerProvider, SpanExporter } from '@opentelemetry/sdk-trace import type { Resource } from '@opentelemetry/resources'; import type { ElementType, ReactNode, JSX } from 'react'; import type { KnownHttpApiKey, PageAssets } from './preset/isomorphic/types'; -import type { ExpressHandlerContext } from './preset/node/types'; +import type { ExpressHandlerContext, ExpressRouteList } from './preset/node/types'; import type { SpecificExtras } from './preset/server/utils/specific-extras'; import type { CreateAxiosDefaults } from 'axios'; import type { AxiosInstanceWrapper, Middleware as AxiosMiddleware } from 'middleware-axios'; -import type { Handler, LogHandler, LogHandlerFactory, Middleware } from './http'; +import type { Handler, LogHandler, LogHandlerFactory, Middleware, ProxyOptions } from './http'; import type { HttpApiHostPool } from './preset/isomorphic/utils/http-api-host-pool'; import type { ServerHandlerContext, @@ -25,6 +25,7 @@ import type { ServerMiddleware, PageResponseFormatter, RenderToString, + RouteList, } from './preset/server/types'; /** @@ -98,13 +99,17 @@ export const KnownToken = { /** Токены компонентов функции обработки входящего HTTP-запроса. */ Serve: { /** Токен списка маршрутов. */ - routes: createToken>('serve/routes'), + pageRoutes: createToken('serve/page-routes'), /** Токен списка "служебных" маршрутов. К "служебным" маршрутам не применяются промежуточные слои. */ - serviceRoutes: createToken>('serve/service-routes'), + serviceRoutes: createToken('serve/service-routes'), /** Токен списка промежуточных слоев обработки входящего HTTP-запроса. */ middleware: createToken('serve/middleware'), + + Proxy: { + config: createToken('proxy/config'), + }, }, /** Токены компонентов обработчиков входящих HTTP-запросов. */ @@ -177,10 +182,10 @@ export const KnownToken = { app: createToken('express/app'), /** Токен списка маршрутов страниц. */ - pageRoutes: createToken>('express/page-routes'), + pageRoutes: createToken('express/page-routes'), /** Токен списка служебных маршрутов. */ - serviceRoutes: createToken>('express/service-routes'), + serviceRoutes: createToken('express/service-routes'), /** Токен списка промежуточных слоев для публичных маршрутов. */ middleware: