-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathcompression.js
executable file
·119 lines (86 loc) · 3.17 KB
/
compression.js
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
'use strict';
const Zlib = require('zlib');
const Accept = require('@hapi/accept');
const Bounce = require('@hapi/bounce');
const Hoek = require('@hapi/hoek');
const internals = {
common: ['gzip, deflate', 'deflate, gzip', 'gzip', 'deflate', 'gzip, deflate, br']
};
exports = module.exports = internals.Compression = class {
decoders = {
gzip: (options) => Zlib.createGunzip(options),
deflate: (options) => Zlib.createInflate(options)
};
encodings = ['identity', 'gzip', 'deflate'];
encoders = {
identity: null,
gzip: (options) => Zlib.createGzip(options),
deflate: (options) => Zlib.createDeflate(options)
};
#common = null;
constructor() {
this._updateCommons();
}
_updateCommons() {
this.#common = new Map();
for (const header of internals.common) {
this.#common.set(header, Accept.encoding(header, this.encodings));
}
}
addEncoder(encoding, encoder) {
Hoek.assert(this.encoders[encoding] === undefined, `Cannot override existing encoder for ${encoding}`);
Hoek.assert(typeof encoder === 'function', `Invalid encoder function for ${encoding}`);
this.encoders[encoding] = encoder;
this.encodings.unshift(encoding);
this._updateCommons();
}
addDecoder(encoding, decoder) {
Hoek.assert(this.decoders[encoding] === undefined, `Cannot override existing decoder for ${encoding}`);
Hoek.assert(typeof decoder === 'function', `Invalid decoder function for ${encoding}`);
this.decoders[encoding] = decoder;
}
accept(request) {
const header = request.headers['accept-encoding'];
if (!header) {
return 'identity';
}
const common = this.#common.get(header);
if (common) {
return common;
}
try {
return Accept.encoding(header, this.encodings);
}
catch (err) {
Bounce.rethrow(err, 'system');
err.header = header;
request._log(['accept-encoding', 'error'], err);
return 'identity';
}
}
encoding(response, length) {
if (response.settings.compressed) {
response.headers['content-encoding'] = response.settings.compressed;
return null;
}
const request = response.request;
if (!request._core.settings.compression ||
length !== null && length < request._core.settings.compression.minBytes) {
return null;
}
const mime = request._core.mime.type(response.headers['content-type'] || 'application/octet-stream');
if (!mime.compressible) {
return null;
}
response.vary('accept-encoding');
if (response.headers['content-encoding']) {
return null;
}
return request.info.acceptEncoding === 'identity' ? null : request.info.acceptEncoding;
}
encoder(request, encoding) {
const encoder = this.encoders[encoding];
Hoek.assert(encoder !== undefined, `Unknown encoding ${encoding}`);
return encoder(request._route.settings.compression[encoding]);
}
};