Update Iot.js
[platform/upstream/iotjs.git] / src / js / http_common.js
1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 var EventEmitter = require('events');
17 var util = require('util');
18 var HTTPParser = process.binding(process.binding.httpparser).HTTPParser;
19 var IncomingMessage = require('http_incoming').IncomingMessage;
20 var OutgoingMessage = require('http_outgoing').OutgoingMessage;
21 var Buffer = require('buffer');
22
23
24
25 var createHTTPParser = function() {
26   // REQUEST is the default type.
27   // For RESPONSE, use HTTPParser.reinitialize(HTTPParser.RESPONSE)
28   var parser = new HTTPParser(HTTPParser.REQUEST);
29   // cb during  http parsing from C side(http_parser)
30   parser.OnHeaders = parserOnHeaders;
31   parser.OnHeadersComplete = parserOnHeadersComplete;
32   parser.OnBody = parserOnBody;
33   parser.OnMessageComplete = parserOnMessageComplete;
34   return parser;
35 };
36
37 exports.createHTTPParser = createHTTPParser;
38
39
40 // This is called when parsing of incoming http msg done
41 function parserOnMessageComplete() {
42
43   var parser = this;
44   var stream = parser.incoming;
45
46   if (stream) {
47     stream.complete = true;
48     // no more data from incoming, stream will emit 'end' event
49     stream.push(null);
50   }
51
52   stream.socket.resume();
53 }
54
55
56 // This is called when header part in http msg is parsed.
57 function parserOnHeadersComplete(info) {
58
59   var parser = this;
60   var headers = info.headers;
61   var url = info.url;
62
63   if (!url) {
64     url = parser._url;
65     parser.url = "";
66   }
67
68   if (!headers) {
69     headers = parser._headers;
70     // FIXME: This should be impl. with Array
71     parser._headers = {};
72   }
73
74
75   parser.incoming = new IncomingMessage(parser.socket);
76   parser.incoming.url = url;
77
78   // add header fields of headers to incoming.headers
79   parser.incoming.addHeaders(headers);
80
81   if (util.isNumber(info.method)) {
82     // for server
83     parser.incoming.method = HTTPParser.methods[info.method];
84   } else {
85     // for client
86     parser.incoming.statusCode = info.status;
87     parser.incoming.statusMessage = info.status_msg;
88   }
89
90   // For client side, if response to 'HEAD' request, we will skip parsing body
91   var skipBody = parser.onIncoming(parser.incoming, info.shouldkeepalive);
92
93   return skipBody;
94 }
95
96
97 // parserOnBody is called when HTTPParser parses http msg(incoming) and
98 // get body part(buf from start at length of len)
99 function parserOnBody(buf, start, len) {
100
101   var parser = this;
102   var stream = parser.incoming;
103
104   if (!stream) {
105     return;
106   }
107
108   // Push body part into incoming stream, which will emit 'data' event
109   var body = buf.slice(start, start+len);
110   stream.push(body);
111 }
112
113
114 function AddHeader(dest, src) {
115   if (!dest.length) {
116     dest.length = 0;
117   }
118
119   for (var i=0;i<src.length;i++) {
120     dest[dest.length+i] = src[i];
121   }
122   dest.length = dest.length + src.length;
123 }
124
125
126 // This is called when http header is fragmented and
127 // HTTPParser sends it to JS in separate pieces.
128 function parserOnHeaders(headers, url) {
129   // FIXME: This should be impl. with Array.concat
130   AddHeader(this._headers, headers);
131   if (url) {
132     this._url += url;
133   }
134 }