diff --git a/api/package-lock.json b/api/package-lock.json index feec31c..9da3f1d 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -24,7 +24,8 @@ "mongoose-sequence": "^5.3.1", "morgan": "^1.10.0", "multer": "^1.4.3", - "swagger-ui-express": "4.3.0" + "swagger-ui-express": "4.3.0", + "url": "^0.10.3" }, "bin": { "api": "build/src/server.js" @@ -2883,7 +2884,7 @@ "node_modules/busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", "dependencies": { "dicer": "0.2.5", "readable-stream": "1.1.x" @@ -3677,7 +3678,7 @@ "node_modules/dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", "dependencies": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" @@ -7590,9 +7591,10 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/multer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", - "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", "dependencies": { "append-field": "^1.0.0", "busboy": "^0.2.11", @@ -8552,6 +8554,15 @@ "node": ">=0.6" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9942,6 +9953,15 @@ "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, "node_modules/url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -9954,6 +9974,11 @@ "node": ">=4" } }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -12629,7 +12654,7 @@ "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", "requires": { "dicer": "0.2.5", "readable-stream": "1.1.x" @@ -13267,7 +13292,7 @@ "dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", "requires": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" @@ -16220,9 +16245,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", - "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "requires": { "append-field": "^1.0.0", "busboy": "^0.2.11", @@ -16933,6 +16958,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -17963,6 +17993,22 @@ "xdg-basedir": "^4.0.0" } }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", diff --git a/api/package.json b/api/package.json index da52b7d..c3a0292 100644 --- a/api/package.json +++ b/api/package.json @@ -63,7 +63,8 @@ "mongoose-sequence": "^5.3.1", "morgan": "^1.10.0", "multer": "^1.4.3", - "swagger-ui-express": "4.3.0" + "swagger-ui-express": "4.3.0", + "url": "^0.10.3" }, "devDependencies": { "@types/bcryptjs": "^2.4.2", diff --git a/api/src/routes/appStream/index.ts b/api/src/routes/appStream/index.ts index cf52017..4a607e5 100644 --- a/api/src/routes/appStream/index.ts +++ b/api/src/routes/appStream/index.ts @@ -1,10 +1,16 @@ import path from 'path' -import express from 'express' +import express, { Request } from 'express' import { folderExists } from '@sasjs/utils' -import { addEntryToAppStreamConfig, getFilesFolder } from '../../utils' +import { + addEntryToAppStreamConfig, + getFilesFolder, + getFullUrl +} from '../../utils' import { appStreamHtml } from './appStreamHtml' +const appStreams: { [key: string]: string } = {} + const router = express.Router() router.get('/', async (req, res) => { @@ -44,7 +50,7 @@ export const publishAppStream = async ( streamServiceName = `AppStreamName${appCount + 1}` } - router.use(`/${streamServiceName}`, express.static(pathToDeployment)) + appStreams[streamServiceName] = pathToDeployment addEntryToAppStreamConfig( streamServiceName, @@ -64,4 +70,24 @@ export const publishAppStream = async ( return {} } +router.get(`/*`, function (req: Request, res, next) { + const reqPath = req.path.replace(/^\//, '') + + // Redirecting to url with trailing slash for base appStream URL only + if (reqPath.split('/').length === 1 && !reqPath.endsWith('/')) + return res.redirect(301, `${getFullUrl(req)}/`) + + const appStream = reqPath.split('/')[0] + const appStreamFilesPath = appStreams[appStream] + if (appStreamFilesPath) { + const resourcePath = reqPath.split('/')[1] || 'index.html' + + req.url = resourcePath + + return express.static(appStreamFilesPath)(req, res, next) + } + + return res.send("There's no App Stream available here.") +}) + export default router diff --git a/api/src/utils/getServerUrl.ts b/api/src/utils/getServerUrl.ts new file mode 100644 index 0000000..905217a --- /dev/null +++ b/api/src/utils/getServerUrl.ts @@ -0,0 +1,15 @@ +import express from 'express' +import url from 'url' + +export const getFullUrl = (req: express.Request) => + url.format({ + protocol: req.protocol, + host: req.get('host'), + pathname: req.originalUrl + }) + +export const getServerUrl = (req: express.Request) => + url.format({ + protocol: req.protocol, + host: req.get('x-forwarded-host') || req.get('host') + }) diff --git a/api/src/utils/index.ts b/api/src/utils/index.ts index 4bb2022..09254ba 100644 --- a/api/src/utils/index.ts +++ b/api/src/utils/index.ts @@ -10,6 +10,7 @@ export * from './generateRefreshToken' export * from './getCertificates' export * from './getDesktopFields' export * from './getPreProgramVariables' +export * from './getServerUrl' export * from './instantiateLogger' export * from './isDebugOn' export * from './parseLogToArray'