|
| 1 | +# Response Interceptor |
| 2 | + |
| 3 | +Intercept responses from upstream with `responseInterceptor`. (Make sure to set `selfHandleResponse: true`) |
| 4 | + |
| 5 | +Responses which are compressed with `brotli`, `gzip` and `deflate` will be decompressed automatically. Response will be made available as [`buffer`](https://nodejs.org/api/buffer.html) which you can manipulate. |
| 6 | + |
| 7 | +## Replace text and change http status code |
| 8 | + |
| 9 | +```js |
| 10 | +const { createProxyMiddleware, responseInterceptor } = require('http-proxy-middleware'); |
| 11 | + |
| 12 | +const proxy = createProxyMiddleware({ |
| 13 | + target: 'http://www.example.com', |
| 14 | + changeOrigin: true, // for vhosted sites |
| 15 | + |
| 16 | + /** |
| 17 | + * IMPORTANT: avoid res.end being called automatically |
| 18 | + **/ |
| 19 | + selfHandleResponse: true, // res.end() will be called internally by responseInterceptor() |
| 20 | + |
| 21 | + /** |
| 22 | + * Intercept response and replace 'Hello' with 'Teapot' with 418 http response status code |
| 23 | + **/ |
| 24 | + onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => { |
| 25 | + res.statusCode = 418; // set different response status code |
| 26 | + |
| 27 | + const response = responseBuffer.toString('utf-8'); |
| 28 | + return response.replace('Hello', 'Teapot'); |
| 29 | + }), |
| 30 | +}); |
| 31 | +``` |
| 32 | + |
| 33 | +## Log request and response |
| 34 | + |
| 35 | +```javascript |
| 36 | +const proxy = createProxyMiddleware({ |
| 37 | + target: 'http://www.example.com', |
| 38 | + changeOrigin: true, // for vhosted sites |
| 39 | + |
| 40 | + selfHandleResponse: true, // res.end() will be called internally by responseInterceptor() |
| 41 | + |
| 42 | + onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => { |
| 43 | + // log original request and proxied request info |
| 44 | + const exchange = `[DEBUG] ${req.method} ${req.path} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path} [${proxyRes.statusCode}]`; |
| 45 | + console.log(exchange); // [DEBUG] GET / -> http://www.example.com [200] |
| 46 | + |
| 47 | + // log complete response |
| 48 | + const response = responseBuffer.toString('utf-8'); |
| 49 | + console.log(response); // log response body |
| 50 | + |
| 51 | + return responseBuffer; |
| 52 | + }), |
| 53 | +}); |
| 54 | +``` |
| 55 | + |
| 56 | +## Manipulate JSON responses (application/json) |
| 57 | + |
| 58 | +```javascript |
| 59 | +const proxy = createProxyMiddleware({ |
| 60 | + target: 'http://jsonplaceholder.typicode.com', |
| 61 | + changeOrigin: true, // for vhosted sites |
| 62 | + |
| 63 | + selfHandleResponse: true, // res.end() will be called internally by responseInterceptor() |
| 64 | + |
| 65 | + onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => { |
| 66 | + // detect json responses |
| 67 | + if (proxyRes.headers['content-type'] === 'application/json') { |
| 68 | + let data = JSON.parse(responseBuffer.toString('utf-8')); |
| 69 | + |
| 70 | + // manipulate JSON data here |
| 71 | + data = Object.assign({}, data, { extra: 'foo bar' }); |
| 72 | + |
| 73 | + // return manipulated JSON |
| 74 | + return JSON.stringify(data); |
| 75 | + } |
| 76 | + |
| 77 | + // return other content-types as-is |
| 78 | + return responseBuffer; |
| 79 | + }), |
| 80 | +}); |
| 81 | +``` |
| 82 | + |
| 83 | +## Manipulate image response |
| 84 | + |
| 85 | +Example [Lenna](https://en.wikipedia.org/wiki/Lenna) image: <https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png> |
| 86 | + |
| 87 | +Proxy and manipulate image (flip, sepia, pixelate). |
| 88 | + |
| 89 | +[](https://codesandbox.io/s/trusting-engelbart-03rjl) |
| 90 | + |
| 91 | +Check [source code](https://codesandbox.io/s/trusting-engelbart-03rjl) on codesandbox. |
| 92 | + |
| 93 | +Some working examples on <https://03rjl.sse.codesandbox.io>/[relative wikimedia image path]: |
| 94 | + |
| 95 | +- Lenna - ([manipulated](https://03rjl.sse.codesandbox.io/wikipedia/en/7/7d/Lenna_%28test_image%29.png)) ([original](https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png)). |
| 96 | +- Starry Night - ([manipulated](https://03rjl.sse.codesandbox.io/wikipedia/commons/thumb/e/ea/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg/1024px-Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg)) ([original](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg/1024px-Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg)). |
| 97 | +- Mona Lisa - ([manipulated](https://03rjl.sse.codesandbox.io/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/800px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg)) ([original](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/800px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg)). |
| 98 | + |
| 99 | +_You can just use any relative image path from <https://upload.wikimedia.org> and use the relative image path on <https://03rjl.sse.codesandbox.io> to see the manipulated image._ |
| 100 | + |
| 101 | +```javascript |
| 102 | +const Jimp = require('jimp'); // use jimp libray for image manipulation |
| 103 | + |
| 104 | +const proxy = createProxyMiddleware({ |
| 105 | + target: 'https://upload.wikimedia.org', |
| 106 | + changeOrigin: true, // for vhosted sites |
| 107 | + |
| 108 | + selfHandleResponse: true, // res.end() will be called internally by responseInterceptor() |
| 109 | + |
| 110 | + onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => { |
| 111 | + const imageTypes = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif']; |
| 112 | + |
| 113 | + // detect image responses |
| 114 | + if (imageTypes.includes(proxyRes.headers['content-type'])) { |
| 115 | + try { |
| 116 | + const image = await Jimp.read(responseBuffer); |
| 117 | + image.flip(true, false).sepia().pixelate(5); |
| 118 | + return image.getBufferAsync(Jimp.AUTO); |
| 119 | + } catch (err) { |
| 120 | + console.log('image processing error: ', err); |
| 121 | + return responseBuffer; |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + return responseBuffer; // return other content-types as-is |
| 126 | + }), |
| 127 | +}); |
| 128 | + |
| 129 | +// http://localhost:3000/wikipedia/en/7/7d/Lenna\_%28test_image%29.png |
| 130 | +``` |
0 commit comments