Projekt

Obecné

Profil

Stáhnout (6.56 KB) Statistiky
| Větev: | Revize:
1
var assert = require('assert');
2
var util = require('util');
3

    
4
var Buffer = require('buffer').Buffer;
5

    
6
// Node.js version
7
var mode = /^v0\.8\./.test(process.version) ? 'rusty' :
8
           /^v0\.(9|10)\./.test(process.version) ? 'old' :
9
           /^v0\.12\./.test(process.version) ? 'normal' :
10
           'modern';
11

    
12
var HTTPParser;
13

    
14
var methods;
15
var reverseMethods;
16

    
17
var kOnHeaders;
18
var kOnHeadersComplete;
19
var kOnMessageComplete;
20
var kOnBody;
21
if (mode === 'normal' || mode === 'modern') {
22
  HTTPParser = process.binding('http_parser').HTTPParser;
23
  methods = HTTPParser.methods;
24

    
25
  // v6
26
  if (!methods)
27
    methods = process.binding('http_parser').methods;
28

    
29
  reverseMethods = {};
30

    
31
  methods.forEach(function(method, index) {
32
    reverseMethods[method] = index;
33
  });
34

    
35
  kOnHeaders = HTTPParser.kOnHeaders | 0;
36
  kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
37
  kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
38
  kOnBody = HTTPParser.kOnBody | 0;
39
} else {
40
  kOnHeaders = 'onHeaders';
41
  kOnHeadersComplete = 'onHeadersComplete';
42
  kOnMessageComplete = 'onMessageComplete';
43
  kOnBody = 'onBody';
44
}
45

    
46
function Deceiver(socket, options) {
47
  this.socket = socket;
48
  this.options = options || {};
49
  this.isClient = this.options.isClient;
50
}
51
module.exports = Deceiver;
52

    
53
Deceiver.create = function create(stream, options) {
54
  return new Deceiver(stream, options);
55
};
56

    
57
Deceiver.prototype._toHeaderList = function _toHeaderList(object) {
58
  var out = [];
59
  var keys = Object.keys(object);
60

    
61
  for (var i = 0; i < keys.length; i++)
62
    out.push(keys[i], object[keys[i]]);
63

    
64
  return out;
65
};
66

    
67
Deceiver.prototype._isUpgrade = function _isUpgrade(request) {
68
  return request.method === 'CONNECT' ||
69
         request.headers.upgrade ||
70
         request.headers.connection &&
71
            /(^|\W)upgrade(\W|$)/i.test(request.headers.connection);
72
};
73

    
74
// TODO(indutny): support CONNECT
75
if (mode === 'modern') {
76
  /*
77
  function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
78
                                   url, statusCode, statusMessage, upgrade,
79
                                   shouldKeepAlive) {
80
   */
81
  Deceiver.prototype.emitRequest = function emitRequest(request) {
82
    var parser = this.socket.parser;
83
    assert(parser, 'No parser present');
84

    
85
    parser.execute = null;
86

    
87
    var self = this;
88
    var method = reverseMethods[request.method];
89
    parser.execute = function execute() {
90
      self._skipExecute(this);
91
      this[kOnHeadersComplete](1,
92
                               1,
93
                               self._toHeaderList(request.headers),
94
                               method,
95
                               request.path,
96
                               0,
97
                               '',
98
                               self._isUpgrade(request),
99
                               true);
100
      return 0;
101
    };
102

    
103
    this._emitEmpty();
104
  };
105

    
106
  Deceiver.prototype.emitResponse = function emitResponse(response) {
107
    var parser = this.socket.parser;
108
    assert(parser, 'No parser present');
109

    
110
    parser.execute = null;
111

    
112
    var self = this;
113
    parser.execute = function execute() {
114
      self._skipExecute(this);
115
      this[kOnHeadersComplete](1,
116
                               1,
117
                               self._toHeaderList(response.headers),
118
                               response.path,
119
                               response.code,
120
                               response.status,
121
                               response.reason || '',
122
                               self._isUpgrade(response),
123
                               true);
124
      return 0;
125
    };
126

    
127
    this._emitEmpty();
128
  };
129
} else {
130
  /*
131
    `function parserOnHeadersComplete(info) {`
132

    
133
    info = { .versionMajor, .versionMinor, .url, .headers, .method,
134
             .statusCode, .statusMessage, .upgrade, .shouldKeepAlive }
135
   */
136
  Deceiver.prototype.emitRequest = function emitRequest(request) {
137
    var parser = this.socket.parser;
138
    assert(parser, 'No parser present');
139

    
140
    var method = request.method;
141
    if (reverseMethods)
142
      method = reverseMethods[method];
143

    
144
    var info = {
145
      versionMajor: 1,
146
      versionMinor: 1,
147
      url: request.path,
148
      headers: this._toHeaderList(request.headers),
149
      method: method,
150
      statusCode: 0,
151
      statusMessage: '',
152
      upgrade: this._isUpgrade(request),
153
      shouldKeepAlive: true
154
    };
155

    
156
    var self = this;
157
    parser.execute = function execute() {
158
      self._skipExecute(this);
159
      this[kOnHeadersComplete](info);
160
      return 0;
161
    };
162

    
163
    this._emitEmpty();
164
  };
165

    
166
  Deceiver.prototype.emitResponse = function emitResponse(response) {
167
    var parser = this.socket.parser;
168
    assert(parser, 'No parser present');
169

    
170
    var info = {
171
      versionMajor: 1,
172
      versionMinor: 1,
173
      url: response.path,
174
      headers: this._toHeaderList(response.headers),
175
      method: false,
176
      statusCode: response.status,
177
      statusMessage: response.reason || '',
178
      upgrade: this._isUpgrade(response),
179
      shouldKeepAlive: true
180
    };
181

    
182
    var self = this;
183
    parser.execute = function execute() {
184
      self._skipExecute(this);
185
      this[kOnHeadersComplete](info);
186
      return 0;
187
    };
188

    
189
    this._emitEmpty();
190
  };
191
}
192

    
193
Deceiver.prototype._skipExecute = function _skipExecute(parser) {
194
  var self = this;
195
  var oldExecute = parser.constructor.prototype.execute;
196
  var oldFinish = parser.constructor.prototype.finish;
197

    
198
  parser.execute = null;
199
  parser.finish = null;
200

    
201
  parser.execute = function execute(buffer, start, len) {
202
    // Parser reuse
203
    if (this.socket !== self.socket) {
204
      this.execute = oldExecute;
205
      this.finish = oldFinish;
206
      return this.execute(buffer, start, len);
207
    }
208

    
209
    if (start !== undefined)
210
      buffer = buffer.slice(start, start + len);
211
    self.emitBody(buffer);
212
    return len;
213
  };
214

    
215
  parser.finish = function finish() {
216
    // Parser reuse
217
    if (this.socket !== self.socket) {
218
      this.execute = oldExecute;
219
      this.finish = oldFinish;
220
      return this.finish();
221
    }
222

    
223
    this.execute = oldExecute;
224
    this.finish = oldFinish;
225
    self.emitMessageComplete();
226
  };
227
};
228

    
229
Deceiver.prototype.emitBody = function emitBody(buffer) {
230
  var parser = this.socket.parser;
231
  assert(parser, 'No parser present');
232

    
233
  parser[kOnBody](buffer, 0, buffer.length);
234
};
235

    
236
Deceiver.prototype._emitEmpty = function _emitEmpty() {
237
  // Emit data to force out handling of UPGRADE
238
  var empty = new Buffer(0);
239
  if (this.socket.ondata)
240
    this.socket.ondata(empty, 0, 0);
241
  else
242
    this.socket.emit('data', empty);
243
};
244

    
245
Deceiver.prototype.emitMessageComplete = function emitMessageComplete() {
246
  var parser = this.socket.parser;
247
  assert(parser, 'No parser present');
248

    
249
  parser[kOnMessageComplete]();
250
};
    (1-1/1)