diff --git a/README.md b/README.md index faa0494..cf767a5 100755 --- a/README.md +++ b/README.md @@ -35,7 +35,10 @@ $ npm install -D json-caching-proxy -I, --header [header] change the response header property for identifying cached responses -l, --log print log output to console -t, --timeout change the timeout for proxy server - -d, --deleteCookieDomain Remove the Domain portion of all cookies + -d, --deleteCookieDomain remove the Domain portion of all cookies + -o, --overrideCors [url] override Access-Control-Allow-Origin + -z, --useCorsCredentials set Access-Control-Allow-Credentials to true + ``` #### Example - basic JSON caching with output @@ -43,11 +46,20 @@ $ npm install -D json-caching-proxy $ json-caching-proxy -u http://remote:8080 -l ``` +#### Example - Bypassing CORS when proxying to a 3rd party api server +``` +$ json-caching-proxy -u http://cors-api.example.com -o localhost:9000 -z +``` +This use case occurs when developing a browser application against an api server on a different host with CORS restrictions. +In this example we might be running a dev server that's hosting a frontend application on http://localhost:9000 and there is +browser javascript that needs to fetch from http://cors-api.example.com. The `-z` option tells the proxy to set up auth headers +in case the code uses cookies or tokens (e.g. Bearer tokens) + #### Example - hydrating the cache -You may have a HAR file that was generated elsewhere (e.g. Chrome Developer tools). You can load this file and initialize the cache ``` $ json-caching-proxy -u http://remote:8080 -p 3001 -H chromeDevTools.har -l ``` +You may have a HAR file that was generated elsewhere (e.g. Chrome Developer tools). You can load this file and initialize the cache #### Example - advanced arguments ``` @@ -79,7 +91,10 @@ $ json-caching-proxy -u http://remote:8080 -p 3001 -b time:dc -e '/keepalive' -H "dataRecord": true, "commandPrefix": "proxy", "proxyHeaderIdentifier": "proxy-cache-playback", - "proxyTimeout": 500000 + "proxyTimeout": 500000, + "deleteCookieDomain": true, + "overrideCors": "localhost:8080", + "useCorsCredentials": true } ``` ``` @@ -108,7 +123,9 @@ let jsonCachingProxy = new JsonCachingProxy({ dataRecord: true, showConsoleOutput: false, proxyTimeout: 500000, - deleteCookieDomain: true + deleteCookieDomain: true, + overrideCors: "localhost:8080", + useCorsCredentials: true }); jsonCachingProxy.start(); diff --git a/bin.js b/bin.js index 5f8dabb..716eba1 100755 --- a/bin.js +++ b/bin.js @@ -22,10 +22,10 @@ function isDef (val) { program .version(version) .option('-c, --config [path]', 'load a config file of options. Command line args will be overridden') - .option('-u, --url [url]', 'remote server (e.g. https://network:8080)') - .option('-p, --port [number]', 'port for the local proxy server', parseInt) + .option('-u, --url [url]', 'set target server (e.g. https://network:8080)') + .option('-p, --port [number]', 'set port for the local proxy server', parseInt) .option('-H, --har [path]', 'load entries from a HAR file and hydrate the cache') - .option('-b, --bust [list]', 'a list of cache busting query params to ignore. (e.g. --bust _:cacheSlayer:time:dc)', list) + .option('-b, --bust [list]', 'set cache busting query params to ignore. (e.g. --bust _:cacheSlayer:time:dc)', list) .option('-e, --exclude [regex]', 'exclude specific routes from cache, (e.g. --exclude "GET /api/keep-alive/.*")') .option('-a, --all', 'cache everything from the remote server (Default is to cache just JSON responses)') .option('-P, --disablePlayback', 'disables cache playback') @@ -34,7 +34,9 @@ program .option('-I, --header [header]', 'change the response header property for identifying cached responses') .option('-l, --log', 'print log output to console') .option('-t, --timeout [number]', 'proxy timeout in milliseconds', parseInt) - .option('-d, --deleteCookieDomain', 'Remove the Domain portion of all cookies') + .option('-d, --deleteCookieDomain', 'remove the Domain portion of all cookies') + .option('-o, --overrideCors [url]', 'override Access-Control-Allow-Origin') + .option('-z, --useCorsCredentials', 'set Access-Control-Allow-Credentials to true') .parse(process.argv); let configOptions = {}; @@ -67,6 +69,12 @@ let dataRecord = isDef(configOptions.dataRecord) ? configOptions.dataRecord : is let showConsoleOutput = isDef(configOptions.showConsoleOutput) ? configOptions.showConsoleOutput : isDef(program.log) ? program.log : false; let proxyTimeout = configOptions.proxyTimeout ? parseInt(configOptions.proxyTimeout, 10) : program.timeout; let deleteCookieDomain = isDef(configOptions.deleteCookieDomain) ? configOptions.deleteCookieDomain : isDef(program.deleteCookieDomain) ? program.deleteCookieDomain : false; +let overrideCors = isDef(configOptions.overrideCors) ? configOptions.overrideCors : isDef(program.overrideCors) ? program.overrideCors : false; +let useCorsCredentials = isDef(configOptions.useCorsCredentials) ? configOptions.useCorsCredentials : isDef(program.useCorsCredentials) ? program.useCorsCredentials : false; + +if (overrideCors === true) { + overrideCors = '*'; +} let excludedRouteMatchers; if (configOptions.excludedRouteMatchers && configOptions.excludedRouteMatchers.length > 0) { @@ -98,7 +106,9 @@ let jsonCachingProxy = new JsonCachingProxy({ proxyHeaderIdentifier, showConsoleOutput, proxyTimeout, - deleteCookieDomain + deleteCookieDomain, + overrideCors, + useCorsCredentials }); jsonCachingProxy.start(); diff --git a/index.js b/index.js index bb5ca6c..5e24927 100755 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const npmPackage = require('./package.json'); const crypto = require('crypto'); const express = require('express'); const proxy = require('express-http-proxy'); +const cors = require('cors'); const bodyParser = require('body-parser'); const urlUtil = require('url'); const chalk = require('chalk'); @@ -27,6 +28,8 @@ class JsonCachingProxy { showConsoleOutput: false, proxyTimeout: 3600000, // one hour deleteCookieDomain: false, // Removes the domain portion from all cookies + overrideCors: false, + useCorsCredentials: false }; // Ignore undefined values and combine the options with defaults @@ -45,6 +48,11 @@ class JsonCachingProxy { this.excludedParamMap = this.options.cacheBustingParams.reduce((map, param) => { map[param] = true; return map }, {}); + if (this.options.overrideCors) { + this.app.use(cors({credentials: this.options.useCorsCredentials, origin: this.options.overrideCors})); + this.app.options('*', cors({credentials: this.options.useCorsCredentials, origin: this.options.overrideCors})); + } + if (this.options.showConsoleOutput) { this.log = console.log; this.err = console.error; @@ -362,6 +370,10 @@ class JsonCachingProxy { res.location(urlUtil.parse(location).path); } + if (this.options.overrideCors && this.options.overrideCors !== '*') { + res.header('access-control-allow-origin', this.options.overrideCors); + } + if (this.options.deleteCookieDomain && res._headers['set-cookie']) { res.header('set-cookie', this.removeCookiesDomain(res._headers['set-cookie'] || [])); } @@ -398,7 +410,7 @@ class JsonCachingProxy { this.server.setTimeout(this.options.proxyTimeout); this.log(chalk.bold(`\JSON Caching Proxy Started:`)); - this.log(chalk.gray(`==============\n`)); + this.log(chalk.gray(`===========================\n`)); this.log(`Remote server url: \t${chalk.bold(this.options.remoteServerUrl)}`); this.log(`Proxy running on port: \t${chalk.bold(this.options.proxyPort)}`); this.log(`Proxy Timeout: \t\t${chalk.bold(this.options.proxyTimeout)}`); @@ -408,6 +420,8 @@ class JsonCachingProxy { this.log(`Proxy response header: \t${chalk.bold(this.options.proxyHeaderIdentifier)}`); this.log(`Cache all: \t\t${chalk.bold(this.options.cacheEverything)}`); this.log(`Delete cookies domain: \t${chalk.bold(this.options.deleteCookieDomain)}`); + this.log(`Override CORS origin: \t${chalk.bold(this.options.overrideCors)}`); + this.log(`Use CORS Credentials: \t${chalk.bold(this.options.useCorsCredentials)}`); this.log(`Cache busting params: \t${chalk.bold(this.options.cacheBustingParams)}`); this.log(`Excluded routes: `); this.options.excludedRouteMatchers.forEach((regExp) => { diff --git a/jsdoc/JsonCachingProxy.html b/jsdoc/JsonCachingProxy.html index 60dfb9f..526bbc5 100644 --- a/jsdoc/JsonCachingProxy.html +++ b/jsdoc/JsonCachingProxy.html @@ -142,7 +142,7 @@