-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathindex.js
More file actions
150 lines (130 loc) · 3.79 KB
/
index.js
File metadata and controls
150 lines (130 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
'use strict';
const zlib = require('zlib');
const concatStream = require('concat-stream');
const BufferHelper = require('bufferhelper');
const isString = function (obj) {
return Object.prototype.toString.call(obj) === '[object String]';
}
/**
* Modify the response of json
* @param res {Response} The http response
* @param proxyRes {proxyRes|String} String: The http header content-encoding: gzip/deflate
* @param callback {Function} Custom modified logic
*/
module.exports = function modifyResponse(res, proxyRes, callback) {
let contentEncoding = proxyRes;
if (proxyRes && proxyRes.headers) {
contentEncoding = proxyRes.headers['content-encoding'];
// Delete the content-length if it exists. Otherwise, an exception will occur
// @see: https://github.com/langjt/node-http-proxy-json/issues/10
if ('content-length' in proxyRes.headers) {
delete proxyRes.headers['content-length'];
}
}
let unzip, zip;
// Now only deal with the gzip/deflate/brotli/undefined content-encoding.
switch (contentEncoding) {
case 'gzip':
unzip = zlib.Gunzip();
zip = zlib.Gzip();
break;
case 'deflate':
unzip = zlib.Inflate();
zip = zlib.Deflate();
break;
case 'br':
unzip = zlib.BrotliDecompress && zlib.BrotliDecompress();
zip = zlib.BrotliCompress && zlib.BrotliCompress();
break;
}
// The cache response method can be called after the modification.
let _write = res.write;
let _end = res.end;
if (unzip) {
unzip.on('error', function (e) {
console.log('Unzip error: ', e);
_end.call(res);
});
handleCompressed(res, _write, _end, unzip, zip, callback);
} else if (!contentEncoding) {
handleUncompressed(res, _write, _end, callback);
} else {
console.log('Not supported content-encoding: ' + contentEncoding);
}
};
/**
* handle compressed
*/
function handleCompressed(res, _write, _end, unzip, zip, callback) {
// The rewrite response method is replaced by unzip stream.
res.write = data => { unzip.write(data) };
res.end = () => unzip.end();
// Concat the unzip stream.
let concatWrite = concatStream(data => {
let body;
try {
body = JSON.parse(data.toString());
} catch (e) {
body = data.toString();
}
// Custom modified logic
if (typeof callback === 'function') {
body = callback(body);
}
let finish = _body => {
// empty response body
if (!_body) {
_body = '';
}
// Converts the JSON to buffer.
let body = new Buffer(isString(_body) ? _body : JSON.stringify(_body));
// Call the response method and recover the content-encoding.
zip.on('data', chunk => _write.call(res, chunk));
zip.on('end', () => _end.call(res));
zip.write(body);
zip.end();
};
if (body && body.then) {
body.then(finish);
} else {
finish(body);
}
});
unzip.pipe(concatWrite);
}
/**
* handle Uncompressed
*/
function handleUncompressed(res, _write, _end, callback) {
let buffer = new BufferHelper();
// Rewrite response method and get the content.
res.write = data => buffer.concat(data);
res.end = () => {
let body;
try {
body = JSON.parse(buffer.toBuffer().toString());
} catch (e) {
body = buffer.toBuffer().toString();
}
// Custom modified logic
if (typeof callback === 'function') {
body = callback(body);
}
let finish = _body => {
// empty response body
if (!_body) {
_body = '';
}
// Converts the JSON to buffer.
let body = new Buffer(isString(_body) ? _body : JSON.stringify(_body));
// Call the response method
_write.call(res, body);
_end.call(res);
};
if (body && body.then) {
body.then(finish);
} else {
finish(body);
}
};
}