UNPKG

2.46 kBJavaScriptView Raw
1'use strict';
2
3/**
4 * Compression plugin.
5 * Provides gzip and deflate on the fly compression for response
6 * @module Crixalis
7 * @submodule compression
8 * @for Controller
9 */
10
11var define = require('../controller').define,
12 zlib = require('zlib');
13
14module.exports = function () {
15 /**
16 * Default compression method. Supported values are __gzip__ and __deflate__.
17 * @property defaultCompression
18 * @type String
19 * @default gzip
20 */
21 define('property', 'defaultCompression', 'gzip');
22
23 /**
24 * Detect best supported by client compression format
25 * @method compression
26 * @return {String}
27 */
28 define('method', 'compression', function () {
29 var codings = this.codings,
30 i, l;
31
32 /* Select compression type */
33 for (i = 0, l = codings.length; i < l; i++) {
34 switch (codings[i]) {
35 case '*':
36 return this.defaultCompression;
37
38 case 'gzip':
39 return 'gzip';
40
41 case 'deflate':
42 return 'deflate';
43 }
44 }
45
46 /* Nothing selected */
47 return undefined;
48 });
49
50 /**
51 * Apply compression to response body
52 * @event compression
53 */
54 define('handler', 'compression', function () {
55 var that = this,
56 type = this.compression(),
57 length = 0,
58 buffers = [],
59 compressor;
60
61 switch (type) {
62 case 'gzip':
63 compressor = zlib.createGzip();
64 break;
65
66 case 'deflate':
67 compressor = zlib.createDeflate();
68 break;
69
70 default:
71 /* Compression not supported by client or disabled for this request */
72 process.nextTick(function () {
73 that._response();
74 });
75 return;
76 }
77
78 compressor.on('error', function (error) {
79 that.error(error, true);
80 });
81
82 compressor.on('data', function (chunk) {
83 length += chunk.length;
84 buffers.push(chunk);
85 });
86
87 compressor.on('end', function () {
88 var output, b, i, j, l, k;
89
90 compressor.removeAllListeners();
91
92 switch (buffers.length) {
93 case 0:
94 output = new Buffer(0);
95 break;
96
97 case 1:
98 output = buffers[0];
99 break;
100
101 default:
102 output = new Buffer(length);
103
104 for (i = 0, j = 0, l = buffers.length; i < l; i++) {
105 b = buffers[i];
106 k = b.length;
107 b.copy(output, j, 0, k);
108 j += k;
109 }
110 }
111
112 /* Set headers */
113 that.headers['Content-Length'] = length;
114 that.headers['Content-Encoding'] = type;
115 that.headers['Vary'] = 'Accept-Encoding';
116
117 that.body = output;
118
119 /* Respond to client */
120 that._response();
121 });
122
123 compressor.write(this.body);
124 compressor.end();
125 });
126};