From f61188035a51fad9e37cd1dd322fb5cfe33af8ec Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 13:22:35 -0400 Subject: [PATCH 01/25] [dist] make tests work reliably, add package-lock.json --- .gitignore | 1 + .travis.yml | 8 +- package-lock.json | 3418 +++++++++++++++++++++++++++++++++++ package.json | 27 +- test/lib-http-proxy-test.js | 1 + 5 files changed, 3431 insertions(+), 24 deletions(-) create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore index fdd88f86d..347bedbb4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ notes primus-proxy.js tes.js npm-debug.log +.nyc_output diff --git a/.travis.yml b/.travis.yml index 975e73b04..c687bb062 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,8 @@ sudo: false language: node_js node_js: - - "0.10" - - "0.12" - - "4.2" - "6" - -before_install: - - travis_retry npm install -g npm@2.14.5 - - travis_retry npm install + - "8" script: - npm test diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..d02391c37 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3418 @@ +{ + "name": "http-proxy", + "version": "1.16.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=", + "dev": true, + "optional": true + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "bufferutil": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.2.1.tgz", + "integrity": "sha1-N75dNuHgZJIiHmjUdLGsWOUQy9c=", + "dev": true, + "optional": true, + "requires": { + "bindings": "1.2.1", + "nan": "2.10.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "engine.io": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", + "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", + "dev": true, + "requires": { + "accepts": "1.3.5", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "ws": "3.3.3" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.2" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eventemitter3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.0.1.tgz", + "integrity": "sha512-QOCPu979MMWX9XNlfRZoin+Wm+bK1SP7vv3NGUniYwuSJK/+cPA10blMaeRgzg31RvoSFk6FsCDVa4vNryBTGA==" + }, + "expect.js": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", + "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "nyc": { + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.7.1.tgz", + "integrity": "sha512-EGePURSKUEpS1jWnEKAMhY+GWZzi7JC+f8iBDOATaOsLZW5hM/9eYx2dHGaEXa1ITvMm44CJugMksvP3NwMQMw==", + "dev": true, + "requires": { + "archy": "1.0.0", + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.5.1", + "debug-log": "1.0.1", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "2.1.0", + "foreground-child": "1.5.6", + "glob": "7.1.2", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.1.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.3", + "istanbul-lib-source-maps": "1.2.3", + "istanbul-reports": "1.4.0", + "md5-hex": "1.3.0", + "merge-source-map": "1.1.0", + "micromatch": "2.3.11", + "mkdirp": "0.5.1", + "resolve-from": "2.0.0", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "spawn-wrap": "1.4.2", + "test-exclude": "4.2.1", + "yargs": "11.1.0", + "yargs-parser": "8.1.0" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "atob": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-generator": { + "version": "6.26.1", + "bundled": true, + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "core-js": "2.5.5", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.5" + } + }, + "babel-traverse": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.5" + } + }, + "babel-types": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "base": { + "version": "0.11.2", + "bundled": true, + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.3.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "class-utils": { + "version": "0.3.6", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true, + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "core-js": { + "version": "2.5.5", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "which": "1.3.0" + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "define-property": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend-shallow": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "bundled": true, + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "4.0.2", + "signal-exit": "3.0.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "bundled": true, + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "get-value": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "has-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true, + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "invariant": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-odd": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.1", + "bundled": true, + "dev": true, + "requires": { + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.3", + "bundled": true, + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "istanbul-reports": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + }, + "lodash": { + "version": "4.17.5", + "bundled": true, + "dev": true + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "bundled": true, + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "merge-source-map": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true, + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "pascalcase": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "preserve": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "bundled": true, + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true, + "dev": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "ret": { + "version": "0.1.15", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-regex": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "set-value": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true, + "dev": true + }, + "source-map-resolve": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.6", + "mkdirp": "0.5.1", + "os-homedir": "1.0.2", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "which": "1.3.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "split-string": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "3.1.10", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "braces": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "to-fast-properties": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "trim-right": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "union-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "bundled": true, + "dev": true + }, + "use": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "which": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "11.1.0", + "bundled": true, + "dev": true, + "requires": { + "cliui": "4.0.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "cliui": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "socket.io": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.0.tgz", + "integrity": "sha512-KS+3CNWWNtLbVN5j0/B+1hjxRzey+oTK6ejpAOoxMZis6aXeB8cUtfuvjHl97tuZx+t/qD/VyqFMjuzu2Js6uQ==", + "dev": true, + "requires": { + "debug": "3.1.0", + "engine.io": "3.2.0", + "has-binary2": "1.0.2", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.1.0", + "socket.io-parser": "3.2.0" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.0.tgz", + "integrity": "sha512-TvKPpL0cBON5LduQfR8Rxrr+ktj70bLXGvqHCL3er5avBXruB3gpnbaud5ikFYVfANH1gCABAvo0qN8Axpg2ew==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "3.1.0", + "engine.io-client": "3.2.1", + "has-binary2": "1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.2.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "sse": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/sse/-/sse-0.0.6.tgz", + "integrity": "sha1-MZJGHfo4x4Qk3Zv46gJWGaElqhA=", + "dev": true, + "requires": { + "options": "0.0.6" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "utf-8-validate": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.2.2.tgz", + "integrity": "sha1-i7hxpHQeCFxwSHynrNvX1tNgKes=", + "dev": true, + "optional": true, + "requires": { + "bindings": "1.2.1", + "nan": "2.4.0" + }, + "dependencies": { + "nan": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz", + "integrity": "sha1-+zxZ1F/k7/4hXwuJD4rfbrMtIjI=", + "dev": true, + "optional": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-0.8.1.tgz", + "integrity": "sha1-a2UnO5kZPF8Gekz1gJWY93fjt1k=", + "dev": true, + "requires": { + "bufferutil": "1.2.1", + "options": "0.0.6", + "ultron": "1.0.2", + "utf-8-validate": "1.2.2" + }, + "dependencies": { + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + } + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 3718993c3..950cbfea0 100644 --- a/package.json +++ b/package.json @@ -12,33 +12,26 @@ ], "main": "index.js", "dependencies": { - "eventemitter3": "2.0.x", - "requires-port": "1.x.x" + "eventemitter3": "^3.0.0", + "requires-port": "^1.0.0" }, "devDependencies": { - "async": "*", - "blanket": "*", - "coveralls": "*", - "dox": "*", - "expect.js": "*", - "mocha": "*", - "mocha-lcov-reporter": "*", + "async": "^2.0.0", + "expect.js": "~0.3.1", + "mocha": "^3.5.3", + "nyc": "^11.7.1", "semver": "^5.0.3", - "socket.io": "*", - "socket.io-client": "*", + "socket.io": "^2.1.0", + "socket.io-client": "^2.1.0", "sse": "0.0.6", "ws": "^0.8.0" }, "scripts": { - "coveralls": "mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js", - "blanket": { - "pattern": "lib/http-proxy" - }, "test": "mocha test/*-test.js", - "test-cov": "mocha --require blanket -R html-cov > cov/coverage.html" + "test-cov": "nyc npm test" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" }, "license": "MIT" } diff --git a/test/lib-http-proxy-test.js b/test/lib-http-proxy-test.js index 06702be05..ec6273f94 100644 --- a/test/lib-http-proxy-test.js +++ b/test/lib-http-proxy-test.js @@ -483,6 +483,7 @@ describe('lib/http-proxy.js', function() { proxyServer.on('close', function() { proxyServer.close(); server.close(); + destiny.close(); if (count == 1) { done(); } }); From f6c396fc94c3dfb7f5088364225459dfcd34490e Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:10:05 -0400 Subject: [PATCH 02/25] [wip] proper tests and reporting --- .gitignore | 1 + .travis.yml | 6 ++++-- README.md | 9 ++------- package.json | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 347bedbb4..02593a904 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ primus-proxy.js tes.js npm-debug.log .nyc_output +coverage diff --git a/.travis.yml b/.travis.yml index c687bb062..956c0fcbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,12 @@ language: node_js node_js: - "6" - "8" - script: - npm test - +after_success: + - bash <(curl -s https://codecov.io/bash) +matrix: + fast_finish: true notifications: email: - travis@nodejitsu.com diff --git a/README.md b/README.md index 40367e111..c66a58aa2 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,7 @@ node-http-proxy ======= -

- -    - - -

+[![Build Status](https://travis-ci.org/nodejitsu/node-http-proxy.svg?branch=master)](https://travis-ci.org/nodejitsu/node-http-proxy) `node-http-proxy` is an HTTP programmable proxying library that supports websockets. It is suitable for implementing components such as reverse @@ -341,7 +336,7 @@ proxyServer.listen(8015); * **cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values: * `false` (default): disable cookie rewriting * String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`. - * Object: mapping of domains to new domains, use `"*"` to match all domains. + * Object: mapping of domains to new domains, use `"*"` to match all domains. For example keep one domain unchanged, rewrite one domain and remove other domains: ``` cookieDomainRewrite: { diff --git a/package.json b/package.json index 950cbfea0..8950610ff 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,8 @@ "ws": "^0.8.0" }, "scripts": { - "test": "mocha test/*-test.js", - "test-cov": "nyc npm test" + "mocha": "mocha test/*-test.js", + "test": "nyc --reporter=text --reporter=lcov npm run mocha" }, "engines": { "node": ">=4.0.0" From d2d9f2b34164edcc1dfdcf5eb0f15f25636462a1 Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:16:33 -0400 Subject: [PATCH 03/25] [dist][test] codecov config --- codecov.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..9937c4cc4 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +coverage: + parsers: + javascript: + enable_partials: yes + status: + project: + default: + target: "80%" + patch: + enabled: false From 66d133743e9fd155a1ee1cd663f6586e816fb9d5 Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:22:46 -0400 Subject: [PATCH 04/25] [fix] move badges --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index c66a58aa2..e7eebc34a 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,7 @@

-node-http-proxy -======= - -[![Build Status](https://travis-ci.org/nodejitsu/node-http-proxy.svg?branch=master)](https://travis-ci.org/nodejitsu/node-http-proxy) +# node-http-proxy [![Build Status](https://travis-ci.org/nodejitsu/node-http-proxy.svg?branch=master)](https://travis-ci.org/nodejitsu/node-http-proxy) [![codecov](https://codecov.io/gh/nodejitsu/node-http-proxy/branch/master/graph/badge.svg)](https://codecov.io/gh/nodejitsu/node-http-proxy) `node-http-proxy` is an HTTP programmable proxying library that supports websockets. It is suitable for implementing components such as reverse From 5be846ba7cf4ba8f793feb6b9f9be01cf34742af Mon Sep 17 00:00:00 2001 From: Sean Willis Date: Tue, 20 Feb 2018 17:50:59 -0800 Subject: [PATCH 05/25] Adding ability to set cookie path --- lib/http-proxy/common.js | 29 ++++++++++--------- lib/http-proxy/passes/web-outgoing.js | 10 ++++++- ...lib-http-proxy-passes-web-outgoing-test.js | 11 +++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js index aa9700234..c00994cde 100644 --- a/lib/http-proxy/common.js +++ b/lib/http-proxy/common.js @@ -5,7 +5,7 @@ var common = exports, var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, isSSL = /^https|wss/, - cookieDomainRegex = /(;\s*domain=)([^;]+)/i; + cookieProps = ['domain', 'path']; /** * Simple Regex for testing if protocol is https @@ -211,27 +211,30 @@ common.urlJoin = function() { * * @api private */ -common.rewriteCookieDomain = function rewriteCookieDomain(header, config) { +common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) { + if(cookieProps.indexOf(property) === -1) //Property not supported + return header; + if (Array.isArray(header)) { return header.map(function (headerElement) { - return rewriteCookieDomain(headerElement, config); + return rewriteCookieProperty(headerElement, config, property); }); } - return header.replace(cookieDomainRegex, function(match, prefix, previousDomain) { - var newDomain; - if (previousDomain in config) { - newDomain = config[previousDomain]; + return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)"), function(match, prefix, previousValue) { + var newValue; + if (previousValue in config) { + newValue = config[previousValue]; } else if ('*' in config) { - newDomain = config['*']; + newValue = config['*']; } else { - //no match, return previous domain + //no match, return previous value return match; } - if (newDomain) { - //replace domain - return prefix + newDomain; + if (newValue) { + //replace value + return prefix + newValue; } else { - //remove domain + //remove value return ''; } }); diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index cff86a700..05ded881c 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -84,12 +84,16 @@ module.exports = { // <-- */ writeHeaders: function writeHeaders(req, res, proxyRes, options) { var rewriteCookieDomainConfig = options.cookieDomainRewrite, + rewriteCookiePathConfig = options.cookiePathRewrite, preserveHeaderKeyCase = options.preserveHeaderKeyCase, rawHeaderKeyMap, setHeader = function(key, header) { if (header == undefined) return; if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { - header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); + header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, 'domain'); + } + if (rewriteCookiePathConfig && key.toLowerCase() === 'set-cookie') { + header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, 'path'); } res.setHeader(String(key).trim(), header); }; @@ -98,6 +102,10 @@ module.exports = { // <-- rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig }; } + if (typeof rewriteCookiePathConfig === 'string') { //also test for '' + rewriteCookiePathConfig = { '*': rewriteCookiePathConfig }; + } + // message.rawHeaders is added in: v0.11.6 // https://nodejs.org/api/http.html#http_message_rawheaders if (preserveHeaderKeyCase && proxyRes.rawHeaders != undefined) { diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index ae86904da..aef521cf0 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -298,6 +298,17 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { .to.contain('hello; domain=my.domain; path=/'); }); + it('rewrites path', function() { + var options = { + cookiePathRewrite: '/dummyPath' + }; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/dummyPath'); + }); + it('rewrites domain', function() { var options = { cookieDomainRewrite: 'my.new.domain' From 98b646980f46fff4695b35be89b8feb72a4832e1 Mon Sep 17 00:00:00 2001 From: Sean Willis Date: Tue, 20 Feb 2018 20:40:49 -0800 Subject: [PATCH 06/25] Forgot 'i' flag when changing from regex shorthand to string. --- lib/http-proxy/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js index c00994cde..8fae2cd25 100644 --- a/lib/http-proxy/common.js +++ b/lib/http-proxy/common.js @@ -220,7 +220,7 @@ common.rewriteCookieProperty = function rewriteCookieProperty(header, config, pr return rewriteCookieProperty(headerElement, config, property); }); } - return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)"), function(match, prefix, previousValue) { + return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)", 'i'), function(match, prefix, previousValue) { var newValue; if (previousValue in config) { newValue = config[previousValue]; From 7370b0686451430951f4b7b48da0af61f747d48c Mon Sep 17 00:00:00 2001 From: Sean Willis Date: Tue, 20 Feb 2018 20:53:39 -0800 Subject: [PATCH 07/25] Updating docs and adding more tests. --- README.md | 12 ++++++++ ...lib-http-proxy-passes-web-outgoing-test.js | 28 ++++++++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e7eebc34a..4a56ff691 100644 --- a/README.md +++ b/README.md @@ -342,6 +342,18 @@ proxyServer.listen(8015); "*": "" } ``` +* **cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values: + * `false` (default): disable cookie rewriting + * String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. + * Object: mapping of paths to new paths, use `"*"` to match all paths. + For example keep one path unchanged, rewrite one path and remove other paths: + ``` + cookiePathRewrite: { + "/unchanged.path/": "/unchanged.path/", + "/old.path/": "/new.path/", + "*": "" + } + ``` * **headers**: object with extra headers to be added to target requests. * **proxyTimeout**: timeout (in millis) when proxy receives no response from target diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index aef521cf0..a509cf1ae 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -289,7 +289,18 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { expect(this.res.headers['set-cookie']).to.have.length(2); }); - it('does not rewrite domain', function() { + it('rewrites path', function() { + var options = { + cookiePathRewrite: '/dummyPath' + }; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/dummyPath'); + }); + + it('does not rewrite path', function() { var options = {}; httpProxy.writeHeaders({}, this.res, this.proxyRes, options); @@ -298,15 +309,24 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { .to.contain('hello; domain=my.domain; path=/'); }); - it('rewrites path', function() { + it('removes path', function() { var options = { - cookiePathRewrite: '/dummyPath' + cookiePathRewrite: '' }; httpProxy.writeHeaders({}, this.res, this.proxyRes, options); expect(this.res.headers['set-cookie']) - .to.contain('hello; domain=my.domain; path=/dummyPath'); + .to.contain('hello; domain=my.domain'); + }); + + it('does not rewrite domain', function() { + var options = {}; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/'); }); it('rewrites domain', function() { From 58df2a4db06ada85cc3bcd056b7549369de6ed73 Mon Sep 17 00:00:00 2001 From: Sean Willis Date: Wed, 21 Feb 2018 10:19:34 -0800 Subject: [PATCH 08/25] Removing unnecessary check since this is a private API --- lib/http-proxy/common.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js index 8fae2cd25..b2f302cad 100644 --- a/lib/http-proxy/common.js +++ b/lib/http-proxy/common.js @@ -4,8 +4,7 @@ var common = exports, required = require('requires-port'); var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, - isSSL = /^https|wss/, - cookieProps = ['domain', 'path']; + isSSL = /^https|wss/; /** * Simple Regex for testing if protocol is https @@ -212,9 +211,6 @@ common.urlJoin = function() { * @api private */ common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) { - if(cookieProps.indexOf(property) === -1) //Property not supported - return header; - if (Array.isArray(header)) { return header.map(function (headerElement) { return rewriteCookieProperty(headerElement, config, property); From b5b7a838b80424cda250590b246e3d64def7af9c Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:38:15 -0400 Subject: [PATCH 09/25] [fix] slightly more tolerant --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 9937c4cc4..cafdd1ced 100644 --- a/codecov.yml +++ b/codecov.yml @@ -5,6 +5,6 @@ coverage: status: project: default: - target: "80%" + target: "70%" patch: enabled: false From 4269f88eaa1b4ddd742710b8c48861d27027d580 Mon Sep 17 00:00:00 2001 From: jlaamanen Date: Wed, 31 Jan 2018 09:00:24 +0200 Subject: [PATCH 10/25] Added timeout option to docs --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a56ff691..258245d02 100644 --- a/README.md +++ b/README.md @@ -355,7 +355,8 @@ proxyServer.listen(8015); } ``` * **headers**: object with extra headers to be added to target requests. -* **proxyTimeout**: timeout (in millis) when proxy receives no response from target +* **proxyTimeout**: timeout (in millis) for outgoing proxy requests +* **timeout**: timeout (in millis) for incoming requests **NOTE:** `options.ws` and `options.ssl` are optional. From 528a68853c566a6ac63d5d6c0c61b03eaafb7851 Mon Sep 17 00:00:00 2001 From: Aydin Date: Tue, 23 Jan 2018 12:40:08 +0100 Subject: [PATCH 11/25] Update common.js Add method parameter to options for overriding the proxy-outgoing HTTP-method --- lib/http-proxy/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js index b2f302cad..6513e81d8 100644 --- a/lib/http-proxy/common.js +++ b/lib/http-proxy/common.js @@ -39,7 +39,7 @@ common.setupOutgoing = function(outgoing, options, req, forward) { function(e) { outgoing[e] = options[forward || 'target'][e]; } ); - outgoing.method = req.method; + outgoing.method = options.method || req.method; outgoing.headers = extend({}, req.headers); if (options.headers){ From e9fff4576fb2aa132ac0041326b7c32004435acf Mon Sep 17 00:00:00 2001 From: "shaohui.tsh" Date: Thu, 7 Dec 2017 11:12:37 +0800 Subject: [PATCH 12/25] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0response?= =?UTF-8?q?=E8=87=AA=E5=A4=84=E7=90=86=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http-proxy/passes/web-incoming.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 5cb0b03d3..2e72f312a 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -162,16 +162,19 @@ module.exports = { proxyReq.on('response', function(proxyRes) { if(server) { server.emit('proxyRes', proxyRes, req, res); } - for(var i=0; i < web_o.length; i++) { - if(web_o[i](req, res, proxyRes, options)) { break; } - } // Allow us to listen when the proxy has completed proxyRes.on('end', function () { server.emit('end', req, res, proxyRes); }); - proxyRes.pipe(res); + if(!options.selfHandleResponse) { + for(var i=0; i < web_o.length; i++) { + if(web_o[i](req, res, proxyRes, options)) { break; } + } + + proxyRes.pipe(res); + } }); //proxyReq.end(); From 2f6f2e0ff915446d509efa52086872f6b8e22a4d Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:50:52 -0400 Subject: [PATCH 13/25] [dist] document the feature --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 258245d02..ac466d08e 100644 --- a/README.md +++ b/README.md @@ -345,7 +345,7 @@ proxyServer.listen(8015); * **cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values: * `false` (default): disable cookie rewriting * String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. - * Object: mapping of paths to new paths, use `"*"` to match all paths. + * Object: mapping of paths to new paths, use `"*"` to match all paths. For example keep one path unchanged, rewrite one path and remove other paths: ``` cookiePathRewrite: { @@ -357,6 +357,7 @@ proxyServer.listen(8015); * **headers**: object with extra headers to be added to target requests. * **proxyTimeout**: timeout (in millis) for outgoing proxy requests * **timeout**: timeout (in millis) for incoming requests +* **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event **NOTE:** `options.ws` and `options.ssl` are optional. From 52d8fa1d4170251b52d2ec532e3beb152e7ea68c Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 16:57:35 -0400 Subject: [PATCH 14/25] [test] for override method feature --- test/lib-http-proxy-common-test.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/lib-http-proxy-common-test.js b/test/lib-http-proxy-common-test.js index ef99ca109..58233f754 100644 --- a/test/lib-http-proxy-common-test.js +++ b/test/lib-http-proxy-common-test.js @@ -251,7 +251,7 @@ describe('lib/http-proxy/common.js', function () { expect(outgoing.path).to.eql('/' + google); }); - + it('should not replace :\ to :\\ when no http word before', function () { var outgoing = {}; var google = 'http://google.com:/join/join.js' @@ -262,7 +262,7 @@ describe('lib/http-proxy/common.js', function () { expect(outgoing.path).to.eql('/' + google); }); - + describe('when using ignorePath', function () { it('should ignore the path of the `req.url` passed in but use the target path', function () { var outgoing = {}; @@ -347,6 +347,16 @@ describe('lib/http-proxy/common.js', function () { expect(outgoing.secureProtocol).eql('my-secure-protocol'); }); + it('should handle overriding the `method` of the http request', function () { + var outgoing = {}; + common.setupOutgoing(outgoing, { + target: url.parse('https://whooooo.com'), + method: 'POST' , + }, { method: 'GET', url: '' }); + + expect(outgoing.method).eql('POST'); + }); + // url.parse('').path => null it('should not pass null as last arg to #urlJoin', function(){ var outgoing = {}; From 48f372b29a5a0e4ef0a8ba14bc7a917db4b2f5d5 Mon Sep 17 00:00:00 2001 From: carpsareokiguess Date: Mon, 30 Oct 2017 22:31:05 +0100 Subject: [PATCH 15/25] fix small typos in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ac466d08e..9eb56bbd3 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ http.createServer(function (req, res) { **[Back to top](#table-of-contents)** #### Setup a stand-alone proxy server with custom server logic -This example show how you can proxy a request using your own HTTP server +This example shows how you can proxy a request using your own HTTP server and also you can put your own logic to handle the request. ```js @@ -229,7 +229,7 @@ http.createServer(function (req, res) { **[Back to top](#table-of-contents)** #### Using HTTPS -You can activate the validation of a secure SSL certificate to the target connection (avoid self signed certs), just set `secure: true` in the options. +You can activate the validation of a secure SSL certificate to the target connection (avoid self-signed certs), just set `secure: true` in the options. ##### HTTPS -> HTTP From 93e48b13e2977c66f4c5e06d8b41d10ade66750b Mon Sep 17 00:00:00 2001 From: Radu Serbanescu Date: Mon, 16 Oct 2017 18:32:45 +0300 Subject: [PATCH 16/25] Add use case for proxy to HTTPS using a PKCS12 client certificate --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 9eb56bbd3..64cbb4f30 100644 --- a/README.md +++ b/README.md @@ -265,6 +265,24 @@ httpProxy.createServer({ }).listen(443); ``` +##### HTTP -> HTTPS (using a PKCS12 client certificate) + +```js +// +// Create an HTTP proxy server with an HTTPS target +// +httpProxy.createProxyServer({ + target: { + protocol: 'https:', + host: 'my-domain-name', + port: 443, + pfx: fs.readFileSync('path/to/certificate.p12'), + passphrase: 'password', + }, + changeOrigin: true, +}).listen(8000); +``` + **[Back to top](#table-of-contents)** #### Proxying WebSockets From c0a5022d75e98b14dbbf4defd211d159ab44fb59 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 11 Sep 2017 13:31:13 +0100 Subject: [PATCH 17/25] Add detail about "buffer" option --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 64cbb4f30..5971e5ab3 100644 --- a/README.md +++ b/README.md @@ -376,7 +376,24 @@ proxyServer.listen(8015); * **proxyTimeout**: timeout (in millis) for outgoing proxy requests * **timeout**: timeout (in millis) for incoming requests * **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event +* **buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: + ``` + 'use strict'; + + const streamify = require('stream-array'); + const HttpProxy = require('http-proxy'); + const proxy = new HttpProxy(); + + module.exports = (req, res, next) => { + + proxy.web(req, res, { + target: 'http://localhost:4003/', + buffer: streamify(req.rawBody) + }, next); + + }; + ``` **NOTE:** `options.ws` and `options.ssl` are optional. `options.target` and `options.forward` cannot both be missing @@ -386,6 +403,7 @@ If you are using the `proxyServer.listen` method, the following options are also * **ssl**: object to be passed to https.createServer() * **ws**: true/false, if you want to proxy websockets + **[Back to top](#table-of-contents)** ### Listening for proxy events From 2399f8523f67a016518f4253322f3ac7c7042024 Mon Sep 17 00:00:00 2001 From: n30n0v Date: Thu, 17 Aug 2017 18:22:44 +0300 Subject: [PATCH 18/25] Add followRedirects option --- README.md | 1 + lib/http-proxy/passes/web-incoming.js | 13 +++++-- package.json | 3 +- ...lib-http-proxy-passes-web-incoming-test.js | 37 +++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5971e5ab3..f290c4caf 100644 --- a/README.md +++ b/README.md @@ -375,6 +375,7 @@ proxyServer.listen(8015); * **headers**: object with extra headers to be added to target requests. * **proxyTimeout**: timeout (in millis) for outgoing proxy requests * **timeout**: timeout (in millis) for incoming requests +* **followRedirects**: true/false, Default: false - specify whether you want to follow redirects * **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event * **buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 2e72f312a..419a5dfb6 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -1,12 +1,15 @@ -var http = require('http'), - https = require('https'), +var httpNative = require('http'), + httpsNative = require('https'), web_o = require('./web-outgoing'), - common = require('../common'); + common = require('../common'), + followRedirects = require('follow-redirects'); web_o = Object.keys(web_o).map(function(pass) { return web_o[pass]; }); +var nativeAgents = { http: httpNative, https: httpsNative }; + /*! * Array of passes. * @@ -99,6 +102,10 @@ module.exports = { // And we begin! server.emit('start', req, res, options.target || options.forward); + var agents = options.followRedirects ? followRedirects : nativeAgents; + var http = agents.http; + var https = agents.https; + if(options.forward) { // If forward enable, so just pipe the request var forwardReq = (options.forward.protocol === 'https:' ? https : http).request( diff --git a/package.json b/package.json index 8950610ff..2f01cf795 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "main": "index.js", "dependencies": { "eventemitter3": "^3.0.0", - "requires-port": "^1.0.0" + "requires-port": "^1.0.0", + "follow-redirects": "^1.0.0" }, "devDependencies": { "async": "^2.0.0", diff --git a/test/lib-http-proxy-passes-web-incoming-test.js b/test/lib-http-proxy-passes-web-incoming-test.js index 7a34a58bc..cffe1af1e 100644 --- a/test/lib-http-proxy-passes-web-incoming-test.js +++ b/test/lib-http-proxy-passes-web-incoming-test.js @@ -1,6 +1,7 @@ var webPasses = require('../lib/http-proxy/passes/web-incoming'), httpProxy = require('../lib/http-proxy'), expect = require('expect.js'), + url = require('url'), http = require('http'); describe('lib/http-proxy/passes/web.js', function() { @@ -413,3 +414,39 @@ describe('#createProxyServer.web() using own http server', function () { http.request('http://127.0.0.1:8080/test2', function() {}).end(); }); }); + +describe('#followRedirects', function () { + it('should proxy the request follow redirects', function (done) { + var proxy = httpProxy.createProxyServer({ + target: 'http://127.0.0.1:8080', + followRedirects: true + }); + + function requestHandler(req, res) { + proxy.web(req, res); + } + + var proxyServer = http.createServer(requestHandler); + + var source = http.createServer(function(req, res) { + + if (url.parse(req.url).pathname === '/redirect') { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end('ok'); + } + + res.writeHead(301, { 'Location': '/redirect' }); + res.end(); + }); + + proxyServer.listen('8081'); + source.listen('8080'); + + http.request('http://127.0.0.1:8081', function(res) { + source.close(); + proxyServer.close(); + expect(res.statusCode).to.eql(200); + done(); + }).end(); + }); +}); From 54dd4f4421196ed616cadb9f66670ce0461f329d Mon Sep 17 00:00:00 2001 From: Gustav Tiger Date: Tue, 20 Jun 2017 13:38:28 +0200 Subject: [PATCH 19/25] Include websocket non-upgrade response When the server do not accept the upgrade request for websockets the server's response was previously not included and sent back. Now the proxy will include the response in these cases. Fixes #890. --- lib/http-proxy/passes/ws-incoming.js | 40 ++++++++++++++++------------ test/lib-http-proxy-test.js | 1 - 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/http-proxy/passes/ws-incoming.js b/lib/http-proxy/passes/ws-incoming.js index cf3796cde..270f23f45 100644 --- a/lib/http-proxy/passes/ws-incoming.js +++ b/lib/http-proxy/passes/ws-incoming.js @@ -77,6 +77,24 @@ module.exports = { * @api private */ stream : function stream(req, socket, options, head, server, clb) { + + var createHttpHeader = function(line, headers) { + return Object.keys(headers).reduce(function (head, key) { + var value = headers[key]; + + if (!Array.isArray(value)) { + head.push(key + ': ' + value); + return head; + } + + for (var i = 0; i < value.length; i++) { + head.push(key + ': ' + value[i]); + } + return head; + }, [line]) + .join('\r\n') + '\r\n\r\n'; + } + common.setupSocket(socket); if (head && head.length) socket.unshift(head); @@ -93,7 +111,10 @@ module.exports = { proxyReq.on('error', onOutgoingError); proxyReq.on('response', function (res) { // if upgrade event isn't going to happen, close the socket - if (!res.upgrade) socket.end(); + if (!res.upgrade) { + socket.write(createHttpHeader('HTTP/' + res.httpVersion + ' ' + res.statusCode + ' ' + res.statusMessage, res.headers)); + res.pipe(socket); + } }); proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) { @@ -119,22 +140,7 @@ module.exports = { // Remark: Handle writing the headers to the socket when switching protocols // Also handles when a header is an array // - socket.write( - Object.keys(proxyRes.headers).reduce(function (head, key) { - var value = proxyRes.headers[key]; - - if (!Array.isArray(value)) { - head.push(key + ': ' + value); - return head; - } - - for (var i = 0; i < value.length; i++) { - head.push(key + ': ' + value[i]); - } - return head; - }, ['HTTP/1.1 101 Switching Protocols']) - .join('\r\n') + '\r\n\r\n' - ); + socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers)); proxySocket.pipe(socket).pipe(proxySocket); diff --git a/test/lib-http-proxy-test.js b/test/lib-http-proxy-test.js index ec6273f94..b507a0052 100644 --- a/test/lib-http-proxy-test.js +++ b/test/lib-http-proxy-test.js @@ -415,7 +415,6 @@ describe('lib/http-proxy.js', function() { client.on('error', function (err) { expect(err).to.be.an(Error); - expect(err.code).to.be('ECONNRESET'); proxyServer.close(); done(); }); From f9e99e14a72a8c988d924835c8cbfd3f33ea4320 Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 18:06:55 -0400 Subject: [PATCH 20/25] [dist] update package-lock.json --- package-lock.json | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d02391c37..1824f1ad3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -163,7 +163,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -263,6 +262,14 @@ "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", "dev": true }, + "follow-redirects": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "requires": { + "debug": "3.1.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -507,8 +514,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "nan": { "version": "2.10.0", From b0a4489b1d2c3dceb87cb85b64ec5ea84420775c Mon Sep 17 00:00:00 2001 From: Thiago Bustamante Date: Fri, 26 May 2017 11:05:29 -0300 Subject: [PATCH 21/25] Fix "Can't set headers after they are sent" errors This PR tries to fix "Can't set headers after they are sent" errors. That are a lot of situations where this error can occurs. In my case, it is happening because I have others middlewares (in an expressjs application that tries to proxy requests). Some of those middlewares (like [passportjs](http://passportjs.org/), or [cors](https://www.npmjs.com/package/cors)) can run ```res.end()``` and when the proxy receive a response, it is already finished. So, it is necessary to test if we can write on the user response when the proxy response is ready. I think it could also fix #930, #1168, #908 --- lib/http-proxy/passes/web-incoming.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 419a5dfb6..e8521d671 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -170,21 +170,23 @@ module.exports = { proxyReq.on('response', function(proxyRes) { if(server) { server.emit('proxyRes', proxyRes, req, res); } - // Allow us to listen when the proxy has completed - proxyRes.on('end', function () { - server.emit('end', req, res, proxyRes); - }); - - if(!options.selfHandleResponse) { + if(!res.headersSent && !options.selfHandleResponse) { for(var i=0; i < web_o.length; i++) { if(web_o[i](req, res, proxyRes, options)) { break; } } - - proxyRes.pipe(res); } - }); - //proxyReq.end(); + if (!res.finished) { + // Allow us to listen when the proxy has completed + proxyRes.on('end', function () { + if (server) server.emit('end', req, res, proxyRes); + }); + // We do this separately since we are also checking for res.finished + if (!options.selfHandleResponse) proxyRes.pipe(res); + } else { + if (server) server.emit('end', req, res, proxyRes); + } + }); } }; From 74c07c9a52e324e4882ead35f25beb64753e7ca2 Mon Sep 17 00:00:00 2001 From: Jake Furler Date: Wed, 14 Jun 2017 14:46:54 +1000 Subject: [PATCH 22/25] issue #953: stop using writeHead object.keys in web-incoming.js results in a non-deterministic ordering of keys, which means that in web-outgoing writeHead might be called before setHeader, which throws an error --- lib/http-proxy/passes/web-outgoing.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index 05ded881c..46352f6e3 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -137,9 +137,10 @@ module.exports = { // <-- writeStatusCode: function writeStatusCode(req, res, proxyRes) { // From Node.js docs: response.writeHead(statusCode[, statusMessage][, headers]) if(proxyRes.statusMessage) { - res.writeHead(proxyRes.statusCode, proxyRes.statusMessage); + res.statusCode = proxyRes.statusCode; + res.statusMessage = proxyRes.statusMessage; } else { - res.writeHead(proxyRes.statusCode); + res.statusCode = proxyRes.statusCode; } } From ad6bbd7949d0b960e0d6751087e64ebd112e20d1 Mon Sep 17 00:00:00 2001 From: guoxiangyang Date: Thu, 8 Jun 2017 00:45:00 +0800 Subject: [PATCH 23/25] add support for modify response --- README.md | 26 ++++++++++++++++++++++++++ lib/http-proxy/passes/web-incoming.js | 4 ++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f290c4caf..736caac73 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,7 @@ proxyServer.listen(8015); * **timeout**: timeout (in millis) for incoming requests * **followRedirects**: true/false, Default: false - specify whether you want to follow redirects * **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event +* **modifyResponse**: do not pipe proxyRes to res, so you can respond to client with your own response. It still goes through all out going web passes unlike selfHandleRequest * **buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: ``` @@ -395,6 +396,7 @@ proxyServer.listen(8015); }; ``` + **NOTE:** `options.ws` and `options.ssl` are optional. `options.target` and `options.forward` cannot both be missing @@ -485,6 +487,30 @@ proxy.close(); ### Miscellaneous +### Modify response + +``` + + var option = { + target: target, + modifyResponse : true + }; + proxy.on('proxyRes', function (proxyRes, req, res) { + var body = new Buffer(''); + proxyRes.on('data', function (data) { + body = Buffer.concat([body, data]); + }); + proxyRes.on('end', function () { + body = body.toString(); + console.log("res from proxied server:", body); + res.end("my response to cli"); + }); + }); + proxy.web(req, res, option); + + +``` + #### ProxyTable API A proxy table API is available through this add-on [module](https://github.com/donasaur/http-proxy-rules), which lets you define a set of rules to translate matching routes to target routes that the reverse proxy will talk to. diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index e8521d671..eeff92ce8 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -181,8 +181,8 @@ module.exports = { proxyRes.on('end', function () { if (server) server.emit('end', req, res, proxyRes); }); - // We do this separately since we are also checking for res.finished - if (!options.selfHandleResponse) proxyRes.pipe(res); + // We pipe to the response unless its expected to be handled by the user + if (!options.selfHandleResponse && !options.modifyResponse) proxyRes.pipe(res); } else { if (server) server.emit('end', req, res, proxyRes); } From ebfee65bf97dcaab4d2c80e9bc4343f83e6a8f6d Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Thu, 19 Apr 2018 20:13:13 -0400 Subject: [PATCH 24/25] [test] add test for selfHandleRequest and remove modifyResponse as selfHandleRequest is the only way that functionality works --- .travis.yml | 1 + README.md | 8 ++- lib/http-proxy/passes/web-incoming.js | 2 +- package-lock.json | 72 +++++++++++++++++++ package.json | 1 + ...lib-http-proxy-passes-web-incoming-test.js | 40 +++++++++++ 6 files changed, 120 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 956c0fcbe..564cffd83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ sudo: false language: node_js node_js: + - "4" - "6" - "8" script: diff --git a/README.md b/README.md index 736caac73..7bb26c9a1 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,6 @@ proxyServer.listen(8015); * **timeout**: timeout (in millis) for incoming requests * **followRedirects**: true/false, Default: false - specify whether you want to follow redirects * **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event -* **modifyResponse**: do not pipe proxyRes to res, so you can respond to client with your own response. It still goes through all out going web passes unlike selfHandleRequest * **buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: ``` @@ -487,13 +486,16 @@ proxy.close(); ### Miscellaneous +If you want to handle your own response after receiving the proxyRes, you can do +so with `selfHandleResponse` + ### Modify response ``` var option = { - target: target, - modifyResponse : true + target: target, + selfHandleResponse : true }; proxy.on('proxyRes', function (proxyRes, req, res) { var body = new Buffer(''); diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index eeff92ce8..995a0db4d 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -182,7 +182,7 @@ module.exports = { if (server) server.emit('end', req, res, proxyRes); }); // We pipe to the response unless its expected to be handled by the user - if (!options.selfHandleResponse && !options.modifyResponse) proxyRes.pipe(res); + if (!options.selfHandleResponse) proxyRes.pipe(res); } else { if (server) server.emit('end', req, res, proxyRes); } diff --git a/package-lock.json b/package-lock.json index 1824f1ad3..104c174f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,6 +103,12 @@ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "bufferutil": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.2.1.tgz", @@ -153,12 +159,30 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -359,6 +383,12 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, "json3": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", @@ -3254,6 +3284,27 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -3341,6 +3392,15 @@ "options": "0.0.6" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "supports-color": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", @@ -3356,6 +3416,12 @@ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -3382,6 +3448,12 @@ } } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 2f01cf795..2ca6b6083 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "devDependencies": { "async": "^2.0.0", + "concat-stream": "^1.6.2", "expect.js": "~0.3.1", "mocha": "^3.5.3", "nyc": "^11.7.1", diff --git a/test/lib-http-proxy-passes-web-incoming-test.js b/test/lib-http-proxy-passes-web-incoming-test.js index cffe1af1e..37f74204b 100644 --- a/test/lib-http-proxy-passes-web-incoming-test.js +++ b/test/lib-http-proxy-passes-web-incoming-test.js @@ -1,6 +1,8 @@ var webPasses = require('../lib/http-proxy/passes/web-incoming'), httpProxy = require('../lib/http-proxy'), expect = require('expect.js'), + concat = require('concat-stream'), + async = require('async'), url = require('url'), http = require('http'); @@ -316,6 +318,44 @@ describe('#createProxyServer.web() using own http server', function () { http.request('http://127.0.0.1:8086', function() {}).end(); }); + it('should proxy the request and provide and respond to manual user response when using modifyResponse', function(done) { + var proxy = httpProxy.createProxyServer({ + target: 'http://127.0.0.1:8080', + selfHandleResponse: true + }); + + function requestHandler(req, res) { + proxy.once('proxyRes', function (proxyRes, pReq, pRes) { + proxyRes.pipe(concat(function (body) { + expect(body.toString('utf8')).eql('Response'); + pRes.end(Buffer.from('my-custom-response')); + })) + }); + + proxy.web(req, res); + } + + var proxyServer = http.createServer(requestHandler); + + var source = http.createServer(function(req, res) { + res.end('Response'); + }); + + async.parallel([ + next => proxyServer.listen(8086, next), + next => source.listen(8080, next) + ], function (err) { + http.get('http://127.0.0.1:8086', function(res) { + res.pipe(concat(function(body) { + expect(body.toString('utf8')).eql('my-custom-response'); + source.close(); + proxyServer.close(); + done(); + })); + }).once('error', done); + }) + }); + it('should proxy the request and handle changeOrigin option', function (done) { var proxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:8080', From ca9d4ce5058d8ff537cedd78a4fe86110e16ca42 Mon Sep 17 00:00:00 2001 From: Jarrett Cruger Date: Fri, 20 Apr 2018 11:33:35 -0400 Subject: [PATCH 25/25] [dist] doc updates --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7bb26c9a1..ea73dca31 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ proxyServer.listen(8015); * `false` (default): disable cookie rewriting * String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. * Object: mapping of paths to new paths, use `"*"` to match all paths. - For example keep one path unchanged, rewrite one path and remove other paths: + For example, to keep one path unchanged, rewrite one path and remove other paths: ``` cookiePathRewrite: { "/unchanged.path/": "/unchanged.path/", @@ -376,7 +376,7 @@ proxyServer.listen(8015); * **proxyTimeout**: timeout (in millis) for outgoing proxy requests * **timeout**: timeout (in millis) for incoming requests * **followRedirects**: true/false, Default: false - specify whether you want to follow redirects -* **selfHandleRequest** true/false, if set to true, none of the webOutgoing passes are called and its your responsibility ro appropriately return the response by listening and acting on the `proxyRes` event +* **selfHandleResponse** true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the `proxyRes` event * **buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: ``` @@ -486,12 +486,15 @@ proxy.close(); ### Miscellaneous -If you want to handle your own response after receiving the proxyRes, you can do -so with `selfHandleResponse` +If you want to handle your own response after receiving the `proxyRes`, you can do +so with `selfHandleResponse`. As you can see below, if you use this option, you +are able to intercept and read the `proxyRes` but you must also make sure to +reply to the `res` itself otherwise the original client will never receive any +data. ### Modify response -``` +```js var option = { target: target,