1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
19 | exports.CompressionFilterFactory = exports.CompressionFilter = void 0;
|
20 | const zlib = require("zlib");
|
21 | const filter_1 = require("./filter");
|
22 | class CompressionHandler {
|
23 | |
24 |
|
25 |
|
26 |
|
27 |
|
28 | async writeMessage(message, compress) {
|
29 | let messageBuffer = message;
|
30 | if (compress) {
|
31 | messageBuffer = await this.compressMessage(messageBuffer);
|
32 | }
|
33 | const output = Buffer.allocUnsafe(messageBuffer.length + 5);
|
34 | output.writeUInt8(compress ? 1 : 0, 0);
|
35 | output.writeUInt32BE(messageBuffer.length, 1);
|
36 | messageBuffer.copy(output, 5);
|
37 | return output;
|
38 | }
|
39 | |
40 |
|
41 |
|
42 |
|
43 | async readMessage(data) {
|
44 | const compressed = data.readUInt8(0) === 1;
|
45 | let messageBuffer = data.slice(5);
|
46 | if (compressed) {
|
47 | messageBuffer = await this.decompressMessage(messageBuffer);
|
48 | }
|
49 | return messageBuffer;
|
50 | }
|
51 | }
|
52 | class IdentityHandler extends CompressionHandler {
|
53 | async compressMessage(message) {
|
54 | return message;
|
55 | }
|
56 | async writeMessage(message, compress) {
|
57 | const output = Buffer.allocUnsafe(message.length + 5);
|
58 | |
59 |
|
60 | output.writeUInt8(0, 0);
|
61 | output.writeUInt32BE(message.length, 1);
|
62 | message.copy(output, 5);
|
63 | return output;
|
64 | }
|
65 | decompressMessage(message) {
|
66 | return Promise.reject(new Error('Received compressed message but "grpc-encoding" header was identity'));
|
67 | }
|
68 | }
|
69 | class DeflateHandler extends CompressionHandler {
|
70 | compressMessage(message) {
|
71 | return new Promise((resolve, reject) => {
|
72 | zlib.deflate(message, (err, output) => {
|
73 | if (err) {
|
74 | reject(err);
|
75 | }
|
76 | else {
|
77 | resolve(output);
|
78 | }
|
79 | });
|
80 | });
|
81 | }
|
82 | decompressMessage(message) {
|
83 | return new Promise((resolve, reject) => {
|
84 | zlib.inflate(message, (err, output) => {
|
85 | if (err) {
|
86 | reject(err);
|
87 | }
|
88 | else {
|
89 | resolve(output);
|
90 | }
|
91 | });
|
92 | });
|
93 | }
|
94 | }
|
95 | class GzipHandler extends CompressionHandler {
|
96 | compressMessage(message) {
|
97 | return new Promise((resolve, reject) => {
|
98 | zlib.gzip(message, (err, output) => {
|
99 | if (err) {
|
100 | reject(err);
|
101 | }
|
102 | else {
|
103 | resolve(output);
|
104 | }
|
105 | });
|
106 | });
|
107 | }
|
108 | decompressMessage(message) {
|
109 | return new Promise((resolve, reject) => {
|
110 | zlib.unzip(message, (err, output) => {
|
111 | if (err) {
|
112 | reject(err);
|
113 | }
|
114 | else {
|
115 | resolve(output);
|
116 | }
|
117 | });
|
118 | });
|
119 | }
|
120 | }
|
121 | class UnknownHandler extends CompressionHandler {
|
122 | constructor(compressionName) {
|
123 | super();
|
124 | this.compressionName = compressionName;
|
125 | }
|
126 | compressMessage(message) {
|
127 | return Promise.reject(new Error(`Received message compressed with unsupported compression method ${this.compressionName}`));
|
128 | }
|
129 | decompressMessage(message) {
|
130 |
|
131 | return Promise.reject(new Error(`Compression method not supported: ${this.compressionName}`));
|
132 | }
|
133 | }
|
134 | function getCompressionHandler(compressionName) {
|
135 | switch (compressionName) {
|
136 | case 'identity':
|
137 | return new IdentityHandler();
|
138 | case 'deflate':
|
139 | return new DeflateHandler();
|
140 | case 'gzip':
|
141 | return new GzipHandler();
|
142 | default:
|
143 | return new UnknownHandler(compressionName);
|
144 | }
|
145 | }
|
146 | class CompressionFilter extends filter_1.BaseFilter {
|
147 | constructor() {
|
148 | super(...arguments);
|
149 | this.sendCompression = new IdentityHandler();
|
150 | this.receiveCompression = new IdentityHandler();
|
151 | }
|
152 | async sendMetadata(metadata) {
|
153 | const headers = await metadata;
|
154 | headers.set('grpc-accept-encoding', 'identity,deflate,gzip');
|
155 | headers.set('accept-encoding', 'identity');
|
156 | return headers;
|
157 | }
|
158 | receiveMetadata(metadata) {
|
159 | const receiveEncoding = metadata.get('grpc-encoding');
|
160 | if (receiveEncoding.length > 0) {
|
161 | const encoding = receiveEncoding[0];
|
162 | if (typeof encoding === 'string') {
|
163 | this.receiveCompression = getCompressionHandler(encoding);
|
164 | }
|
165 | }
|
166 | metadata.remove('grpc-encoding');
|
167 | metadata.remove('grpc-accept-encoding');
|
168 | return metadata;
|
169 | }
|
170 | async sendMessage(message) {
|
171 | |
172 |
|
173 |
|
174 | const resolvedMessage = await message;
|
175 | const compress = resolvedMessage.flags === undefined
|
176 | ? false
|
177 | : (resolvedMessage.flags & 2 ) === 0;
|
178 | return {
|
179 | message: await this.sendCompression.writeMessage(resolvedMessage.message, compress),
|
180 | flags: resolvedMessage.flags,
|
181 | };
|
182 | }
|
183 | async receiveMessage(message) {
|
184 | |
185 |
|
186 |
|
187 |
|
188 | return this.receiveCompression.readMessage(await message);
|
189 | }
|
190 | }
|
191 | exports.CompressionFilter = CompressionFilter;
|
192 | class CompressionFilterFactory {
|
193 | constructor(channel) {
|
194 | this.channel = channel;
|
195 | }
|
196 | createFilter(callStream) {
|
197 | return new CompressionFilter();
|
198 | }
|
199 | }
|
200 | exports.CompressionFilterFactory = CompressionFilterFactory;
|
201 |
|
\ | No newline at end of file |