UNPKG

2.46 kBJavaScriptView Raw
1var zlib = require('zlib')
2var Stream = require('stream')
3var bytes = require('bytes')
4var Negotiator = require('negotiator')
5
6var encodingMethods = {
7 gzip: zlib.createGzip,
8 deflate: zlib.createDeflate
9}
10
11module.exports = function compress(options) {
12 options = options || {}
13
14 var filter = options.filter
15 || /json|text|javascript|dart/i
16
17 var threshold = !options.threshold ? 1024
18 : typeof options.threshold === 'number' ? options.threshold
19 : typeof options.threshold === 'string' ? bytes(options.threshold)
20 : 1024
21
22 return function (next) {
23 return function *() {
24 yield next
25
26 this.vary('Accept-Encoding')
27
28 var body = this.body
29
30 if (this.compress === false
31 || this.method === 'HEAD'
32 || this.status === 204
33 || this.status === 304
34 // Assumes you either always set a body or always don't
35 || body == null
36 ) return
37
38 var length
39 if (Buffer.isBuffer(body)) {
40 if (!this.responseHeader['content-type'])
41 this.set('Content-Type', 'application/octet-stream')
42
43 length = body.length
44 } else if (typeof body === 'string') {
45 if (!this.responseHeader['content-type'])
46 this.set('Content-Type', 'text/plain; charset=utf-8')
47
48 length = Buffer.byteLength(body)
49 } else if (body instanceof Stream) {
50 if (!this.responseHeader['content-type'])
51 this.set('Content-Type', 'application/octet-stream')
52 } else {
53 // JSON
54 body = JSON.stringify(body, null, this.app.jsonSpaces)
55 length = Buffer.byteLength(body)
56 this.set('Content-Type', 'application/json')
57 }
58
59 var contentType = this.responseHeader['content-type']
60 if (!(this.compress === true || filter.test(contentType)))
61 return
62
63 var encodings = new Negotiator(this.req)
64 .preferredEncodings(['gzip', 'deflate', 'identity'])
65 var encoding = encodings[0] || 'identity'
66 if (encoding === 'identity')
67 return
68
69 if (threshold
70 && (typeof body === 'string' || Buffer.isBuffer(body))
71 && length < threshold
72 ) return
73
74 this.set('Content-Encoding', encoding)
75 this.res.removeHeader('Content-Length')
76
77 var stream = encodingMethods[encoding](options)
78 .on('error', this.error.bind(this))
79
80 if (body instanceof Stream)
81 body.pipe(stream)
82 else
83 stream.end(body)
84
85 this.body = stream
86 }
87 }
88}
\No newline at end of file