-
Notifications
You must be signed in to change notification settings - Fork 12
/
gzip.js
111 lines (92 loc) · 2.91 KB
/
gzip.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
/*!
* Ext JS Connect
* Copyright(c) 2010 Sencha Inc.
* MIT Licensed
*/
var spawn = require('child_process').spawn,
sys = require('sys');
/**
* Connect middleware providing gzip compression on the fly. By default, it
* compresses requests with mime types that match the expression
* /text|javascript|json/.
*
* Options:
*
* - `matchType` Regular expression matching mime types to be compressed
* - `flags` String of flags passed to the binary. Nothing by default
* - `bin` Binary executable defaulting to "gzip"
*
* @param {Object} options
* @api public
*/
exports = module.exports = function gzip(options) {
var options = options || {},
matchType = options.matchType || /text|javascript|json/,
bin = options.bin || 'gzip',
flags = options.flags || '';
if (!matchType.test) throw new Error('option matchType must be a regular expression');
flags = (flags) ? '-c ' + flags : '-c';
flags = flags.split(' ');
return function gzip(req, res, next) {
var writeHead = res.writeHead,
defaults = {};
['write', 'end'].forEach(function(name) {
defaults[name] = res[name];
res[name] = function() {
// Make sure headers are setup if they haven't been called yet
if (res.writeHead !== writeHead) {
res.writeHead(res.statusCode);
}
res[name].apply(this, arguments);
}
});
res.writeHead = function(code) {
var args = Array.prototype.slice.call(arguments, 0),
write = defaults.write,
end = defaults.end,
headers, key, accept, type, encoding, gzip;
if (args.length > 1) {
headers = args.pop();
for (key in headers) {
res.setHeader(key, headers[key])
}
}
accept = req.headers['accept-encoding'] || '';
type = res.getHeader('content-type') || '';
encoding = res.getHeader('content-encoding');
if (code !== 200 || !~accept.indexOf('gzip') ||
!matchType.test(type) || encoding) {
res.write = write;
res.end = end;
return finish();
}
res.setHeader('Content-Encoding', 'gzip');
res.setHeader('Vary', 'Accept-Encoding');
res.removeHeader('Content-Length');
gzip = spawn(bin, flags);
res.write = function(chunk, encoding) {
gzip.stdin.write(chunk, encoding);
};
res.end = function(chunk, encoding) {
if (chunk) {
res.write(chunk, encoding);
}
gzip.stdin.end();
};
gzip.stdout.addListener('data', function(chunk) {
write.call(res, chunk);
});
gzip.addListener('exit', function(code) {
res.write = write;
res.end = end;
res.end();
});
finish();
function finish() {
res.writeHead = writeHead;
res.writeHead.apply(res, args);
}
};
next();
};
};