87 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.responseInterceptor = void 0;
 | |
| const zlib = require("zlib");
 | |
| /**
 | |
|  * Intercept responses from upstream.
 | |
|  * Automatically decompress (deflate, gzip, brotli).
 | |
|  * Give developer the opportunity to modify intercepted Buffer and http.ServerResponse
 | |
|  *
 | |
|  * NOTE: must set options.selfHandleResponse=true (prevent automatic call of res.end())
 | |
|  */
 | |
| function responseInterceptor(interceptor) {
 | |
|     return async function proxyRes(proxyRes, req, res) {
 | |
|         const originalProxyRes = proxyRes;
 | |
|         let buffer = Buffer.from('', 'utf8');
 | |
|         // decompress proxy response
 | |
|         const _proxyRes = decompress(proxyRes, proxyRes.headers['content-encoding']);
 | |
|         // concat data stream
 | |
|         _proxyRes.on('data', (chunk) => (buffer = Buffer.concat([buffer, chunk])));
 | |
|         _proxyRes.on('end', async () => {
 | |
|             // copy original headers
 | |
|             copyHeaders(proxyRes, res);
 | |
|             // call interceptor with intercepted response (buffer)
 | |
|             const interceptedBuffer = Buffer.from(await interceptor(buffer, originalProxyRes, req, res));
 | |
|             // set correct content-length (with double byte character support)
 | |
|             res.setHeader('content-length', Buffer.byteLength(interceptedBuffer, 'utf8'));
 | |
|             res.write(interceptedBuffer);
 | |
|             res.end();
 | |
|         });
 | |
|         _proxyRes.on('error', (error) => {
 | |
|             res.end(`Error fetching proxied request: ${error.message}`);
 | |
|         });
 | |
|     };
 | |
| }
 | |
| exports.responseInterceptor = responseInterceptor;
 | |
| /**
 | |
|  * Streaming decompression of proxy response
 | |
|  * source: https://github.com/apache/superset/blob/9773aba522e957ed9423045ca153219638a85d2f/superset-frontend/webpack.proxy-config.js#L116
 | |
|  */
 | |
| function decompress(proxyRes, contentEncoding) {
 | |
|     let _proxyRes = proxyRes;
 | |
|     let decompress;
 | |
|     switch (contentEncoding) {
 | |
|         case 'gzip':
 | |
|             decompress = zlib.createGunzip();
 | |
|             break;
 | |
|         case 'br':
 | |
|             decompress = zlib.createBrotliDecompress();
 | |
|             break;
 | |
|         case 'deflate':
 | |
|             decompress = zlib.createInflate();
 | |
|             break;
 | |
|         default:
 | |
|             break;
 | |
|     }
 | |
|     if (decompress) {
 | |
|         _proxyRes.pipe(decompress);
 | |
|         _proxyRes = decompress;
 | |
|     }
 | |
|     return _proxyRes;
 | |
| }
 | |
| /**
 | |
|  * Copy original headers
 | |
|  * https://github.com/apache/superset/blob/9773aba522e957ed9423045ca153219638a85d2f/superset-frontend/webpack.proxy-config.js#L78
 | |
|  */
 | |
| function copyHeaders(originalResponse, response) {
 | |
|     response.statusCode = originalResponse.statusCode;
 | |
|     response.statusMessage = originalResponse.statusMessage;
 | |
|     if (response.setHeader) {
 | |
|         let keys = Object.keys(originalResponse.headers);
 | |
|         // ignore chunked, brotli, gzip, deflate headers
 | |
|         keys = keys.filter((key) => !['content-encoding', 'transfer-encoding'].includes(key));
 | |
|         keys.forEach((key) => {
 | |
|             let value = originalResponse.headers[key];
 | |
|             if (key === 'set-cookie') {
 | |
|                 // remove cookie domain
 | |
|                 value = Array.isArray(value) ? value : [value];
 | |
|                 value = value.map((x) => x.replace(/Domain=[^;]+?/i, ''));
 | |
|             }
 | |
|             response.setHeader(key, value);
 | |
|         });
 | |
|     }
 | |
|     else {
 | |
|         response.headers = originalResponse.headers;
 | |
|     }
 | |
| }
 |