From 5a200cee148323620157e1c60d7e371e059a81e9 Mon Sep 17 00:00:00 2001 From: Oleksii Savran Date: Thu, 22 Oct 2020 20:19:07 +0200 Subject: [PATCH] Proxy upgrade --- workspaces/ui-express/package.json | 3 +- .../server/middleware/geonamesHttpProxy.ts | 19 +++-- .../ui-express/server/middleware/httpProxy.ts | 85 +++++++++++++------ workspaces/ui-express/server/server.ts | 7 +- 4 files changed, 75 insertions(+), 39 deletions(-) diff --git a/workspaces/ui-express/package.json b/workspaces/ui-express/package.json index 7ccf1bbf..45986972 100644 --- a/workspaces/ui-express/package.json +++ b/workspaces/ui-express/package.json @@ -58,11 +58,11 @@ "debug": "^4.1.1", "es-cookie": "^1.3.2", "express": "^4.17.1", - "express-http-proxy": "^1.6.0", "fast-glob": "^3.2.2", "flattenjs": "^2.0.0", "form-data": "^3.0.0", "history": "^4.10.1", + "http-proxy-middleware": "^1.0.6", "i18next": "^19.4.0", "i18next-browser-languagedetector": "^4.0.2", "i18next-express-middleware": "^1.9.1", @@ -76,6 +76,7 @@ "lodash": "^4.17.19", "minimist": "^1.2.5", "moment": "^2.24.0", + "multer": "^1.4.2", "normalize.css": "^8.0.1", "prop-types": "^15.7.2", "query-string": "^6.12.0", diff --git a/workspaces/ui-express/server/middleware/geonamesHttpProxy.ts b/workspaces/ui-express/server/middleware/geonamesHttpProxy.ts index 6aa6f31a..8d55eab5 100644 --- a/workspaces/ui-express/server/middleware/geonamesHttpProxy.ts +++ b/workspaces/ui-express/server/middleware/geonamesHttpProxy.ts @@ -1,18 +1,19 @@ -import * as proxy from 'express-http-proxy'; +import { createProxyMiddleware } from 'http-proxy-middleware'; import config from '../config'; +import { Request } from 'express'; const geonamesApiUrl = 'https://secure.geonames.org'; -const geonamesHttpProxy = proxy(geonamesApiUrl, { - parseReqBody: false, +const geonamesHttpProxy = createProxyMiddleware({ + target: geonamesApiUrl, - proxyReqPathResolver: (req) => { - const path = `${req.url}&username=${config.geonamesUsername}`; + pathRewrite: (path: string, req: Request) => { + let updatedPath = path.replace('/proxy/api/geonames', ''); + updatedPath = `${updatedPath}&username=${config.geonamesUsername}`; // remove all headers from request - req.headers = {}; - - console.log(`HTTP proxy to ${geonamesApiUrl}${path}`); - return path; + delete req.headers; + console.log(`HTTP proxy to ${geonamesApiUrl}${updatedPath}`); + return updatedPath; }, }); diff --git a/workspaces/ui-express/server/middleware/httpProxy.ts b/workspaces/ui-express/server/middleware/httpProxy.ts index 69e75049..e3322ccc 100644 --- a/workspaces/ui-express/server/middleware/httpProxy.ts +++ b/workspaces/ui-express/server/middleware/httpProxy.ts @@ -1,39 +1,70 @@ -import * as proxy from 'express-http-proxy'; +import { Request, Response } from 'express'; +import { ClientRequest } from 'http'; +import FormData from 'form-data'; +import { forOwn } from 'lodash'; + import config from '../config'; import refreshAuthToken from './refreshAuthToken'; -const httpProxy = proxy(config.apiUrl, { - parseReqBody: false, - timeout: config.apiTimeout, +import { createProxyMiddleware } from 'http-proxy-middleware'; - filter: (req, res) => { - if (req.url.startsWith('/oauth/') || req.url.startsWith('/token') || req.url.startsWith('/google')) { - // console.log('Will proxy /oauth'); - if (req.query.grant_type === 'refresh_token' && !req.query.refresh_token) { - refreshAuthToken(req, res); - return true; - } - return true; +const filter = (path: string, req: Request) => { + if (req.url.startsWith('/oauth/') || req.url.startsWith('/token') || req.url.startsWith('/google')) { + console.log('Will proxy /oauth'); + return true; + } + // Not proxying the request + console.log(`Not proxying ${req.url}`); + return false; +}; + +const options = { + target: config.apiUrl, + + pathRewrite: (path: string, req: Request) => { + // console.log('path', path); + let updatedPath = path.replace('/proxy', ''); + if (updatedPath.startsWith('/google/verify-token')) { + updatedPath = `${updatedPath}&clientId=${config.clientId}`; } - // Not proxying the request - console.log(`Not proxying ${req.url}`); - return false; + + console.log(`HTTP proxy to ${config.apiUrl}${updatedPath}`); + return updatedPath; }, - proxyReqPathResolver: (req) => { - let path = req.url; - if (path.startsWith('/oauth/token')) { - const grantType = req.query.grant_type; - if (grantType === 'client_credentials' || grantType === 'password' || grantType === 'refresh_token') { - path = `${path}&client_id=${config.clientId}&client_secret=${config.clientSecret}`; + onProxyReq(proxyReq: ClientRequest, req: Request, res: Response) { + if (proxyReq.path.startsWith('/oauth/token')) { + if (req.query.grant_type === 'refresh_token' && !req.query.refresh_token) { + console.log('refreshAuthToken'); + refreshAuthToken(req, res); } - } else if (path.startsWith('/google/verify-token')) { - path = `${path}&clientId=${config.clientId}`; - } - console.log(`HTTP proxy to ${config.apiUrl}${path}`); - return path; + const form = new FormData(); + + forOwn(req.body, (value, key) => { + if (key !== 'client_id' && key !== 'client_secret') { + form.append(key, value); + } + }); + form.append('client_id', config.clientId); + form.append('client_secret', config.clientSecret); + delete req.body; + + const headers = form.getHeaders(); + proxyReq.setHeader('Content-Type', headers['content-type']); + proxyReq.setHeader('Content-Length', form.getLengthSync()); + + // form.getLength((err, length) => { // requires socket.pause()? + // proxyReq.setHeader('Content-Length', length); + // form.pipe(proxyReq); + // }); + + form.pipe(proxyReq); + } }, -}); +}; + +// Proxy configuration +const httpProxy = createProxyMiddleware(filter, options); export default httpProxy; diff --git a/workspaces/ui-express/server/server.ts b/workspaces/ui-express/server/server.ts index e54b0c7a..98d86d0b 100644 --- a/workspaces/ui-express/server/server.ts +++ b/workspaces/ui-express/server/server.ts @@ -5,7 +5,8 @@ import * as express from 'express'; import * as path from 'path'; import * as cookieParser from 'cookie-parser'; import * as compression from 'compression'; -import {readFileSync} from 'fs'; +import { readFileSync } from 'fs'; +import multer from 'multer'; import config from './config'; import prerenderer from './middleware/prerenderer'; @@ -17,6 +18,8 @@ import { AccessionService } from '@genesys/client/service'; import AccessionFilter from '@genesys/client/model/accession/AccessionFilter'; import geonamesHttpProxy from './middleware/geonamesHttpProxy'; const i18nextMiddleware = require('i18next-express-middleware'); // has no proper import yet + +const upload = multer(); const app = express(); // This reads the ssr-template.html compiled to ssr-compiled.html by webpack @@ -104,7 +107,7 @@ app.use('/api', (req, res) => { } }); // Proxy all requests starting with /proxy -app.use('/proxy', httpProxy); +app.use('/proxy', upload.none(), httpProxy); app.use('/proxy/api/geonames', geonamesHttpProxy); // Prevent access to manifest.json app.use(/^\/manifest.json$/, (req, res) => { -- GitLab