├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── deflate.js ├── gzip.js └── uncompressed.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | * 3 | 4 | # But not these files... 5 | !package.json 6 | !index.js 7 | !LICENSE 8 | !README.md -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 5.6.0 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Sashe Klechkovski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # http-proxy-response-rewrite [![Build Status](https://travis-ci.org/saskodh/http-proxy-response-rewrite.svg?branch=master)](https://travis-ci.org/saskodh/http-proxy-response-rewrite) 2 | Rewrite the response body from [http-proxy](https://github.com/nodejitsu/node-http-proxy). 3 | 4 | ## Installation 5 | 6 | ``` 7 | npm install http-proxy-response-rewrite 8 | ``` 9 | 10 | ## Motivation 11 | When using [http-proxy](https://github.com/nodejitsu/node-http-proxy) sometimes you will need to modify the response body. While the response object is available and can be easily modified, the response body will usually be compressed. This library will take care of the necessary (de)compressing and leave to you only the modification concerns. 12 | So before using this repository, confirm your server compression format, currently only supports **gzip**、**deflate** and **uncompressed**. 13 | If you need other compression formats, please create a new Issue, and I will try to achieve it as much as possible. 14 | 15 | ## Use Cases 16 | 17 | #### Simulation server using gzip compression 18 | 19 | ``` 20 | var zlib = require('zlib'); 21 | var http = require('http'); 22 | var httpProxy = require('http-proxy'); 23 | var modifyResponse = require('../'); 24 | 25 | // Create a proxy server 26 | var proxy = httpProxy.createProxyServer({ 27 | target: 'http://localhost:5001' 28 | }); 29 | 30 | // Listen for the `proxyRes` event on `proxy`. 31 | proxy.on('proxyRes', function (proxyRes, req, res) { 32 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 33 | if (body) { 34 | // modify some information 35 | var modifiedBody = JSON.parse(body); 36 | modifiedBody.age = 2; 37 | delete modifiedBody.version; 38 | return JSON.stringify(modifiedBody); 39 | } 40 | return body; 41 | }); 42 | }); 43 | 44 | // Create your server and then proxies the request 45 | var server = http.createServer(function (req, res) { 46 | proxy.web(req, res); 47 | }).listen(5000); 48 | 49 | // Create your target server 50 | var targetServer = http.createServer(function (req, res) { 51 | 52 | // Create gzipped content 53 | var gzip = zlib.Gzip(); 54 | var _write = res.write; 55 | var _end = res.end; 56 | 57 | gzip.on('data', function (buf) { 58 | _write.call(res, buf); 59 | }); 60 | gzip.on('end', function () { 61 | _end.call(res); 62 | }); 63 | 64 | res.write = function (data) { 65 | gzip.write(data); 66 | }; 67 | res.end = function () { 68 | gzip.end(); 69 | }; 70 | 71 | res.writeHead(200, {'Content-Type': 'application/json', 'Content-Encoding': 'gzip'}); 72 | res.write(JSON.stringify({name: 'http-proxy-json', age: 1, version: '1.0.0'})); 73 | res.end(); 74 | }).listen(5001); 75 | ``` 76 | 77 | #### Simulation server using deflate compression 78 | 79 | ``` 80 | var zlib = require('zlib'); 81 | var http = require('http'); 82 | var httpProxy = require('http-proxy'); 83 | var modifyResponse = require('../'); 84 | 85 | // Create a proxy server 86 | var proxy = httpProxy.createProxyServer({ 87 | target: 'http://localhost:5001' 88 | }); 89 | 90 | // Listen for the `proxyRes` event on `proxy`. 91 | proxy.on('proxyRes', function (proxyRes, req, res) { 92 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 93 | if (body) { 94 | // modify some information 95 | var modifiedBody = JSON.parse(body); 96 | modifiedBody.age = 2; 97 | delete modifiedBody.version; 98 | return JSON.stringify(modifiedBody); 99 | } 100 | return body; 101 | }); 102 | }); 103 | 104 | // Create your server and then proxies the request 105 | var server = http.createServer(function (req, res) { 106 | proxy.web(req, res); 107 | }).listen(5000); 108 | 109 | // Create your target server 110 | var targetServer = http.createServer(function (req, res) { 111 | 112 | // Create deflated content 113 | var deflate = zlib.Deflate(); 114 | var _write = res.write; 115 | var _end = res.end; 116 | 117 | deflate.on('data', function (buf) { 118 | _write.call(res, buf); 119 | }); 120 | deflate.on('end', function () { 121 | _end.call(res); 122 | }); 123 | 124 | res.write = function (data) { 125 | deflate.write(data); 126 | }; 127 | res.end = function () { 128 | deflate.end(); 129 | }; 130 | 131 | res.writeHead(200, {'Content-Type': 'application/json', 'Content-Encoding': 'deflate'}); 132 | res.write(JSON.stringify({name: 'http-proxy-json', age: 1, version: '1.0.0'})); 133 | res.end(); 134 | }).listen(5001); 135 | ``` 136 | 137 | #### Server does not enable compression 138 | 139 | ``` 140 | var http = require('http'); 141 | var httpProxy = require('http-proxy'); 142 | var modifyResponse = require('../'); 143 | 144 | // Create a proxy server 145 | var proxy = httpProxy.createProxyServer({ 146 | target: 'http://localhost:5001' 147 | }); 148 | 149 | // Listen for the `proxyRes` event on `proxy`. 150 | proxy.on('proxyRes', function (proxyRes, req, res) { 151 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 152 | if (body) { 153 | // modify some information 154 | var modifiedBody = JSON.parse(body); 155 | modifiedBody.age = 2; 156 | delete modifiedBody.version; 157 | return JSON.stringify(modifiedBody); 158 | } 159 | return body; 160 | }); 161 | }); 162 | 163 | // Create your server and then proxies the request 164 | var server = http.createServer(function (req, res) { 165 | proxy.web(req, res); 166 | }).listen(5000); 167 | 168 | // Create your target server 169 | var targetServer = http.createServer(function (req, res) { 170 | res.writeHead(200, {'Content-Type': 'application/json', 'Content-Encoding': 'deflate'}); 171 | res.write(JSON.stringify({name: 'http-proxy-json', age: 1, version: '1.0.0'})); 172 | res.end(); 173 | }).listen(5001); 174 | ``` 175 | 176 | ## Tests 177 | 178 | To run the test suite, first install the dependencies, then run `npm test`: 179 | 180 | ```bash 181 | $ npm install 182 | $ npm test 183 | ``` 184 | 185 | ## License 186 | 187 | [MIT](http://opensource.org/licenses/MIT) -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var zlib = require('zlib'); 2 | var concatStream = require('concat-stream'); 3 | var BufferHelper = require('bufferhelper'); 4 | 5 | /** 6 | * Modify the response 7 | * @param res {Object} The http response 8 | * @param contentEncoding {String} The http header content-encoding: gzip/deflate 9 | * @param callback {Function} Custom modified logic 10 | */ 11 | module.exports = function modifyResponse(res, contentEncoding, callback) { 12 | var unzip, zip; 13 | // Now only deal with the gzip/deflate/undefined content-encoding. 14 | switch (contentEncoding) { 15 | case 'gzip': 16 | unzip = zlib.Gunzip(); 17 | zip = zlib.Gzip(); 18 | break; 19 | case 'deflate': 20 | unzip = zlib.Inflate(); 21 | zip = zlib.Deflate(); 22 | break; 23 | } 24 | 25 | // The cache response method can be called after the modification. 26 | var _write = res.write; 27 | var _end = res.end; 28 | 29 | if (unzip) { 30 | unzip.on('error', function (e) { 31 | console.log('Unzip error: ', e); 32 | _end.call(res); 33 | }); 34 | handleCompressed(res, _write, _end, unzip, zip, callback); 35 | } else if (!contentEncoding) { 36 | handleUncompressed(res, _write, _end, callback); 37 | } else { 38 | console.log('Not supported content-encoding: ' + contentEncoding); 39 | } 40 | }; 41 | 42 | /** 43 | * handle compressed 44 | */ 45 | function handleCompressed(res, _write, _end, unzip, zip, callback) { 46 | // The rewrite response method is replaced by unzip stream. 47 | res.write = function (data) { 48 | unzip.write(data); 49 | }; 50 | 51 | res.end = function () { 52 | unzip.end(); 53 | }; 54 | 55 | // Concat the unzip stream. 56 | var concatWrite = concatStream(function (data) { 57 | var body = data.toString(); 58 | 59 | // Custom modified logic 60 | if (typeof callback === 'function') { 61 | body = callback(body); 62 | } 63 | 64 | body = new Buffer(body); 65 | 66 | // Call the response method and recover the content-encoding. 67 | zip.on('data', function (chunk) { 68 | _write.call(res, chunk); 69 | }); 70 | zip.on('end', function () { 71 | _end.call(res); 72 | }); 73 | 74 | zip.write(body); 75 | zip.end(); 76 | }); 77 | 78 | unzip.pipe(concatWrite); 79 | } 80 | 81 | /** 82 | * handle Uncompressed 83 | */ 84 | function handleUncompressed(res, _write, _end, callback) { 85 | var buffer = new BufferHelper(); 86 | // Rewrite response method and get the content. 87 | res.write = function (data) { 88 | buffer.concat(data); 89 | }; 90 | 91 | res.end = function () { 92 | var body = buffer.toBuffer().toString(); 93 | 94 | // Custom modified logic 95 | if (typeof callback === 'function') { 96 | body = callback(body); 97 | } 98 | 99 | body = new Buffer(body); 100 | 101 | // Call the response method 102 | _write.call(res, body); 103 | _end.call(res); 104 | }; 105 | } 106 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-http-proxy-json", 3 | "version": "0.1.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "assertion-error": { 8 | "version": "1.0.2", 9 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", 10 | "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", 11 | "dev": true 12 | }, 13 | "bufferhelper": { 14 | "version": "0.2.1", 15 | "resolved": "https://registry.npmjs.org/bufferhelper/-/bufferhelper-0.2.1.tgz", 16 | "integrity": "sha1-+nSjhXJKWOJC8ErWZGwjZvg7kT4=" 17 | }, 18 | "chai": { 19 | "version": "3.5.0", 20 | "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", 21 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 22 | "dev": true, 23 | "requires": { 24 | "assertion-error": "1.0.2", 25 | "deep-eql": "0.1.3", 26 | "type-detect": "1.0.0" 27 | } 28 | }, 29 | "commander": { 30 | "version": "2.3.0", 31 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", 32 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", 33 | "dev": true 34 | }, 35 | "concat-stream": { 36 | "version": "1.6.0", 37 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", 38 | "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", 39 | "requires": { 40 | "inherits": "2.0.3", 41 | "readable-stream": "2.3.3", 42 | "typedarray": "0.0.6" 43 | } 44 | }, 45 | "core-util-is": { 46 | "version": "1.0.2", 47 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 48 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 49 | }, 50 | "debug": { 51 | "version": "2.2.0", 52 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 53 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 54 | "dev": true, 55 | "requires": { 56 | "ms": "0.7.1" 57 | } 58 | }, 59 | "deep-eql": { 60 | "version": "0.1.3", 61 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 62 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 63 | "dev": true, 64 | "requires": { 65 | "type-detect": "0.1.1" 66 | }, 67 | "dependencies": { 68 | "type-detect": { 69 | "version": "0.1.1", 70 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", 71 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 72 | "dev": true 73 | } 74 | } 75 | }, 76 | "diff": { 77 | "version": "1.4.0", 78 | "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 79 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", 80 | "dev": true 81 | }, 82 | "escape-string-regexp": { 83 | "version": "1.0.2", 84 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", 85 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", 86 | "dev": true 87 | }, 88 | "eventemitter3": { 89 | "version": "1.2.0", 90 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", 91 | "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", 92 | "dev": true 93 | }, 94 | "glob": { 95 | "version": "3.2.11", 96 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", 97 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 98 | "dev": true, 99 | "requires": { 100 | "inherits": "2.0.3", 101 | "minimatch": "0.3.0" 102 | } 103 | }, 104 | "growl": { 105 | "version": "1.9.2", 106 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 107 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 108 | "dev": true 109 | }, 110 | "http-proxy": { 111 | "version": "1.16.2", 112 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", 113 | "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", 114 | "dev": true, 115 | "requires": { 116 | "eventemitter3": "1.2.0", 117 | "requires-port": "1.0.0" 118 | } 119 | }, 120 | "inherits": { 121 | "version": "2.0.3", 122 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 123 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 124 | }, 125 | "isarray": { 126 | "version": "1.0.0", 127 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 128 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 129 | }, 130 | "jade": { 131 | "version": "0.26.3", 132 | "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", 133 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", 134 | "dev": true, 135 | "requires": { 136 | "commander": "0.6.1", 137 | "mkdirp": "0.3.0" 138 | }, 139 | "dependencies": { 140 | "commander": { 141 | "version": "0.6.1", 142 | "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", 143 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", 144 | "dev": true 145 | }, 146 | "mkdirp": { 147 | "version": "0.3.0", 148 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", 149 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", 150 | "dev": true 151 | } 152 | } 153 | }, 154 | "lru-cache": { 155 | "version": "2.7.3", 156 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 157 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", 158 | "dev": true 159 | }, 160 | "minimatch": { 161 | "version": "0.3.0", 162 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", 163 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 164 | "dev": true, 165 | "requires": { 166 | "lru-cache": "2.7.3", 167 | "sigmund": "1.0.1" 168 | } 169 | }, 170 | "minimist": { 171 | "version": "0.0.8", 172 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 173 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 174 | "dev": true 175 | }, 176 | "mkdirp": { 177 | "version": "0.5.1", 178 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 179 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 180 | "dev": true, 181 | "requires": { 182 | "minimist": "0.0.8" 183 | } 184 | }, 185 | "mocha": { 186 | "version": "2.5.3", 187 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", 188 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", 189 | "dev": true, 190 | "requires": { 191 | "commander": "2.3.0", 192 | "debug": "2.2.0", 193 | "diff": "1.4.0", 194 | "escape-string-regexp": "1.0.2", 195 | "glob": "3.2.11", 196 | "growl": "1.9.2", 197 | "jade": "0.26.3", 198 | "mkdirp": "0.5.1", 199 | "supports-color": "1.2.0", 200 | "to-iso-string": "0.0.2" 201 | } 202 | }, 203 | "ms": { 204 | "version": "0.7.1", 205 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 206 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 207 | "dev": true 208 | }, 209 | "process-nextick-args": { 210 | "version": "1.0.7", 211 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 212 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 213 | }, 214 | "readable-stream": { 215 | "version": "2.3.3", 216 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 217 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 218 | "requires": { 219 | "core-util-is": "1.0.2", 220 | "inherits": "2.0.3", 221 | "isarray": "1.0.0", 222 | "process-nextick-args": "1.0.7", 223 | "safe-buffer": "5.1.1", 224 | "string_decoder": "1.0.3", 225 | "util-deprecate": "1.0.2" 226 | } 227 | }, 228 | "requires-port": { 229 | "version": "1.0.0", 230 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 231 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 232 | "dev": true 233 | }, 234 | "safe-buffer": { 235 | "version": "5.1.1", 236 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 237 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 238 | }, 239 | "sigmund": { 240 | "version": "1.0.1", 241 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 242 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", 243 | "dev": true 244 | }, 245 | "string_decoder": { 246 | "version": "1.0.3", 247 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 248 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 249 | "requires": { 250 | "safe-buffer": "5.1.1" 251 | } 252 | }, 253 | "supports-color": { 254 | "version": "1.2.0", 255 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", 256 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", 257 | "dev": true 258 | }, 259 | "to-iso-string": { 260 | "version": "0.0.2", 261 | "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", 262 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", 263 | "dev": true 264 | }, 265 | "type-detect": { 266 | "version": "1.0.0", 267 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", 268 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 269 | "dev": true 270 | }, 271 | "typedarray": { 272 | "version": "0.0.6", 273 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 274 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" 275 | }, 276 | "util-deprecate": { 277 | "version": "1.0.2", 278 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 279 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "http-proxy-response-rewrite", 3 | "version": "0.0.1", 4 | "description": "Rewrite the response body from http-proxy.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "./node_modules/.bin/mocha -R spec ./test/*.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/saskodh/http-proxy-response-rewrite.git" 12 | }, 13 | "keywords": [ 14 | "http-proxy", 15 | "streaming", 16 | "json" 17 | ], 18 | "authors": [ 19 | "Sashe Klechkovski ", 20 | "XianFa Lang " 21 | ], 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/saskodh/http-proxy-response-rewrite/issues" 25 | }, 26 | "homepage": "https://github.com/saskodh/http-proxy-response-rewrite#readme", 27 | "dependencies": { 28 | "bufferhelper": "^0.2.1", 29 | "concat-stream": "^1.5.1" 30 | }, 31 | "devDependencies": { 32 | "chai": "^3.5.0", 33 | "http-proxy": "^1.13.3", 34 | "mocha": "^2.5.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/deflate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test content-encoding for deflate 3 | */ 4 | 5 | var assert = require('chai').assert; 6 | 7 | var zlib = require('zlib'); 8 | var http = require('http'); 9 | var httpProxy = require('http-proxy'); 10 | var modifyResponse = require('../'); 11 | 12 | var SERVER_PORT = 5002; 13 | var TARGET_SERVER_PORT = 5003; 14 | 15 | // Create a proxy server 16 | var proxy = httpProxy.createProxyServer({ 17 | target: 'http://localhost:' + TARGET_SERVER_PORT 18 | }); 19 | 20 | // Listen for the `proxyRes` event on `proxy`. 21 | proxy.on('proxyRes', function (proxyRes, req, res) { 22 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 23 | if (body) { 24 | body = JSON.parse(body); 25 | // modify some information 26 | body.age = 2; 27 | delete body.version; 28 | } 29 | return JSON.stringify(body); 30 | }); 31 | }); 32 | 33 | // Create your server and then proxies the request 34 | var server = http.createServer(function (req, res) { 35 | proxy.web(req, res); 36 | }).listen(SERVER_PORT); 37 | 38 | // Create your target server 39 | var targetServer = http.createServer(function (req, res) { 40 | 41 | // Create deflated content 42 | var deflate = zlib.Deflate(); 43 | var _write = res.write; 44 | var _end = res.end; 45 | 46 | deflate.on('data', function (buf) { 47 | _write.call(res, buf); 48 | }); 49 | deflate.on('end', function () { 50 | _end.call(res); 51 | }); 52 | 53 | res.write = function (data) { 54 | deflate.write(data); 55 | }; 56 | res.end = function () { 57 | deflate.end(); 58 | }; 59 | 60 | res.writeHead(200, {'Content-Type': 'application/json', 'Content-Encoding': 'deflate'}); 61 | res.write(JSON.stringify({name: 'node-http-proxy-json', age: 1, version: '1.0.0'})); 62 | res.end(); 63 | }).listen(TARGET_SERVER_PORT); 64 | 65 | describe("modifyResponse--deflate", function () { 66 | it('deflate: modify response json successfully', function (done) { 67 | // Test server 68 | http.get('http://localhost:' + SERVER_PORT, function (res) { 69 | var body = ''; 70 | var inflate = zlib.Inflate(); 71 | res.pipe(inflate); 72 | 73 | inflate.on('data', function (chunk) { 74 | body += chunk; 75 | }).on('end', function () { 76 | assert.equal(JSON.stringify({name: 'node-http-proxy-json', age: 2}), body); 77 | 78 | proxy.close(); 79 | server.close(); 80 | targetServer.close(); 81 | 82 | done(); 83 | }); 84 | }); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /test/gzip.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test content-encoding for gzip 3 | */ 4 | 5 | var assert = require('chai').assert; 6 | 7 | var zlib = require('zlib'); 8 | var http = require('http'); 9 | var httpProxy = require('http-proxy'); 10 | var modifyResponse = require('../'); 11 | 12 | var SERVER_PORT = 5000; 13 | var TARGET_SERVER_PORT = 5001; 14 | 15 | // Create a proxy server 16 | var proxy = httpProxy.createProxyServer({ 17 | target: 'http://localhost:' + TARGET_SERVER_PORT 18 | }); 19 | 20 | // Listen for the `proxyRes` event on `proxy`. 21 | proxy.on('proxyRes', function (proxyRes, req, res) { 22 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 23 | if (body) { 24 | body = JSON.parse(body); 25 | // modify some information 26 | body.age = 2; 27 | delete body.version; 28 | } 29 | return JSON.stringify(body); 30 | }); 31 | }); 32 | 33 | // Create your server and then proxies the request 34 | var server = http.createServer(function (req, res) { 35 | proxy.web(req, res); 36 | }).listen(SERVER_PORT); 37 | 38 | // Create your target server 39 | var targetServer = http.createServer(function (req, res) { 40 | 41 | // Create gzipped content 42 | var gzip = zlib.Gzip(); 43 | var _write = res.write; 44 | var _end = res.end; 45 | 46 | gzip.on('data', function (buf) { 47 | _write.call(res, buf); 48 | }); 49 | gzip.on('end', function () { 50 | _end.call(res); 51 | }); 52 | 53 | res.write = function (data) { 54 | gzip.write(data); 55 | }; 56 | res.end = function () { 57 | gzip.end(); 58 | }; 59 | 60 | res.writeHead(200, {'Content-Type': 'application/json', 'Content-Encoding': 'gzip'}); 61 | res.write(JSON.stringify({name: 'node-http-proxy-json', age: 1, version: '1.0.0'})); 62 | res.end(); 63 | }).listen(TARGET_SERVER_PORT); 64 | 65 | describe("modifyResponse--gzip", function () { 66 | it('gzip: modify response json successfully', function (done) { 67 | // Test server 68 | http.get('http://localhost:' + SERVER_PORT, function (res) { 69 | var body = ''; 70 | var gunzip = zlib.Gunzip(); 71 | res.pipe(gunzip); 72 | 73 | gunzip.on('data', function (chunk) { 74 | body += chunk; 75 | }).on('end', function () { 76 | assert.equal(JSON.stringify({name: 'node-http-proxy-json', age: 2}), body); 77 | 78 | proxy.close(); 79 | server.close(); 80 | targetServer.close(); 81 | 82 | done(); 83 | }); 84 | }); 85 | }); 86 | }); 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /test/uncompressed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test content-encoding for uncompressed 3 | */ 4 | 5 | var assert = require('chai').assert; 6 | 7 | var http = require('http'); 8 | var httpProxy = require('http-proxy'); 9 | var modifyResponse = require('../'); 10 | 11 | var SERVER_PORT = 5004; 12 | var TARGET_SERVER_PORT = 5005; 13 | 14 | // Create a proxy server 15 | var proxy = httpProxy.createProxyServer({ 16 | target: 'http://localhost:' + TARGET_SERVER_PORT 17 | }); 18 | 19 | // Listen for the `proxyRes` event on `proxy`. 20 | proxy.on('proxyRes', function (proxyRes, req, res) { 21 | modifyResponse(res, proxyRes.headers['content-encoding'], function (body) { 22 | if (body) { 23 | body = JSON.parse(body); 24 | // modify some information 25 | body.age = 2; 26 | delete body.version; 27 | } 28 | return JSON.stringify(body); 29 | }); 30 | }); 31 | 32 | // Create your server and then proxies the request 33 | var server = http.createServer(function (req, res) { 34 | proxy.web(req, res); 35 | }).listen(SERVER_PORT); 36 | 37 | // Create your target server 38 | var targetServer = http.createServer(function (req, res) { 39 | res.writeHead(200, {'Content-Type': 'application/json'}); 40 | res.write(JSON.stringify({name: 'node-http-proxy-json', age: 1, version: '1.0.0'})); 41 | res.end(); 42 | }).listen(TARGET_SERVER_PORT); 43 | 44 | describe("modifyResponse--uncompressed", function () { 45 | it('uncompressed: modify response json successfully', function (done) { 46 | // Test server 47 | http.get('http://localhost:' + SERVER_PORT, function (res) { 48 | var body = ''; 49 | res.on('data', function (chunk) { 50 | body += chunk; 51 | }).on('end', function () { 52 | assert.equal(JSON.stringify({name: 'node-http-proxy-json', age: 2}), body); 53 | 54 | proxy.close(); 55 | server.close(); 56 | targetServer.close(); 57 | 58 | done(); 59 | }); 60 | }); 61 | }); 62 | }); 63 | 64 | --------------------------------------------------------------------------------