From 304b116c6d558ed5d95d427d765327a9d2ba4d25 Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:17:27 +0530 Subject: [PATCH] Add a CLI for running a proxy server (#495) --- packages/cli/README.md | 22 +++++++++++ packages/cli/package.json | 4 +- packages/cli/src/index.ts | 1 + packages/cli/src/proxy.ts | 79 +++++++++++++++++++++++++++++++++++++++ yarn.lock | 44 +++++++++++++++++++++- 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 packages/cli/src/proxy.ts diff --git a/packages/cli/README.md b/packages/cli/README.md index 65ef7168..6ae971c0 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -94,3 +94,25 @@ A basic CLI to to fetch and compare watcher GQL response. ``` * The diff for latest and previous GQL responses is shown + +## proxy + +Runs a proxy server pointed to the given upstream endpoint + +* Install dependencies and build: + + ```bash + # In repo root + yarn + + # In packages/cli + yarn build + ``` + +* Run the proxy server: + + ```bash + yarn proxy --upstream --origin-header [ORIGN_HEADER] --port [PROXY_SERVER_PORT] + + # For details, run: yarn proxy --help + ``` diff --git a/packages/cli/package.json b/packages/cli/package.json index 908f0eea..1e0338c9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -9,7 +9,8 @@ "clean": "rm -rf ./dist", "copy-assets": "copyfiles -u 1 src/**/*.gql dist/", "chat": "DEBUG='vulcanize:*, laconic:*' node dist/chat.js", - "compare-gql": "DEBUG='vulcanize:*' node dist/compare-gql.js" + "compare-gql": "DEBUG='vulcanize:*' node dist/compare-gql.js", + "proxy": "DEBUG='laconic:*' node dist/proxy.js" }, "dependencies": { "@apollo/client": "^3.7.1", @@ -31,6 +32,7 @@ "graphql": "^15.5.0", "graphql-request": "^6.1.0", "graphql-subscriptions": "^2.0.0", + "http-proxy-middleware": "^2.0.6", "js-yaml": "^4.0.0", "json-diff": "^0.5.4", "lodash": "^4.17.21", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5b381481..0a2d219f 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -17,3 +17,4 @@ export * from './fill'; export * from './create-state-gql'; export * from './peer'; export * from './utils'; +export * from './proxy'; diff --git a/packages/cli/src/proxy.ts b/packages/cli/src/proxy.ts new file mode 100644 index 00000000..db57ddaa --- /dev/null +++ b/packages/cli/src/proxy.ts @@ -0,0 +1,79 @@ +// +// Copyright 2023 Vulcanize, Inc. +// + +import debug from 'debug'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import express from 'express'; +import { createProxyMiddleware } from 'http-proxy-middleware'; +import cors from 'cors'; + +const log = debug('laconic:proxy'); + +interface Arguments { + port: number; + upstream: string; + originHeader?: string; +} + +async function main (): Promise { + const argv: Arguments = _getArgv(); + + const app = express(); + + // Enable CORS + app.use(cors()); + + const upstreamEndpoint: string = argv.upstream; + if (!upstreamEndpoint) { + throw new Error('Upstream endpoint not provided'); + } + + // Create a proxy + const proxyMiddleware = createProxyMiddleware({ + target: upstreamEndpoint, + changeOrigin: true, // Enable CORS bypass + logLevel: 'debug', // Set log level as needed + onProxyReq: (proxyReq) => { + if (argv.originHeader) { + proxyReq.setHeader('Origin', argv.originHeader); + } + } + }); + + // Use the proxy middleware for incoming requests + app.use('/', proxyMiddleware); + + // Start the server + app.listen(argv.port, () => { + log(`Proxy server listening on port ${argv.port}`); + }); +} + +function _getArgv (): any { + return yargs(hideBin(process.argv)).parserConfiguration({ + 'parse-numbers': false + }).env( + 'PROXY' + ).options({ + port: { + type: 'number', + describe: 'Port to listen on (env: PROXY_PORT)', + default: 4000 + }, + upstream: { + type: 'string', + describe: 'Upstream endpoint (env: PROXY_UPSTREAM)', + demandOption: true + }, + originHeader: { + type: 'string', + describe: 'Origin header to be used (env: PROXY_ORIGIN_HEADER)' + } + }).argv; +} + +main().catch(err => { + log(err); +}); diff --git a/yarn.lock b/yarn.lock index 71842345..bff11b65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3671,6 +3671,13 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/http-proxy@^1.17.8": + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== + dependencies: + "@types/node" "*" + "@types/js-yaml@^4.0.3", "@types/js-yaml@^4.0.4": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" @@ -8010,7 +8017,7 @@ eventemitter3@4.0.4: resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -eventemitter3@^4.0.4, eventemitter3@^4.0.7: +eventemitter3@^4.0.0, eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -8401,6 +8408,11 @@ flow-stoplight@^1.0.0: resolved "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz" integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= +follow-redirects@^1.0.0: + version "1.15.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== + follow-redirects@^1.12.1: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" @@ -9418,6 +9430,26 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" +http-proxy-middleware@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" @@ -10107,6 +10139,11 @@ is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" @@ -14207,6 +14244,11 @@ require-package-name@^2.0.1: resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" integrity sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz"