fluent-plugin-websocket 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.rdoc +30 -19
- data/examples/msgpack.js +646 -0
- data/examples/websocket.html +81 -0
- data/fluent-plugin-websocket.gemspec +2 -2
- data/lib/fluent/plugin/out_websocket.rb +46 -11
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bed9989f3203afca2a0ecac1ecd6d0155aa6b061
|
4
|
+
data.tar.gz: 9fe57af129239dd41520445f6f3d5b0e5f90b71b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49300703aa75c86e1a571a5e1bc527bacf735916e8d3c85718e0f400756b920071657528263152248a2b678b546e9c1cd260f062ef2bda49afbbd09cbf49f687
|
7
|
+
data.tar.gz: 1446c1902d16db79f4c499c0d68afb5c9e86b0ad418d87073c0acc302652a51c16287cbe29bfe506547c28bbe3fd1c275f629c012c196c8a93701dfbdcfb16a8
|
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
=
|
1
|
+
= fluent-plugin-websocket
|
2
|
+
{https://badge.fury.io/rb/fluent-plugin-websocket.svg}[https://badge.fury.io/rb/fluent-plugin-websocket]
|
2
3
|
|
3
4
|
Fluentd websocket output plugin.
|
4
5
|
|
@@ -10,17 +11,16 @@ In the current version, emitted data will be broadcasted to the all connected cl
|
|
10
11
|
|
11
12
|
gem install fluent-plugin-websocket
|
12
13
|
|
13
|
-
This plugin depends on {*em-websocket*}[https://github.com/igrigorik/em-websocket].
|
14
|
-
|
15
14
|
== Configuration
|
16
15
|
<match foo.**>
|
17
16
|
type websocket
|
18
|
-
host 192.168.1.1
|
19
|
-
port 8080
|
20
|
-
use_msgpack false
|
21
|
-
add_time false
|
22
|
-
add_tag true
|
17
|
+
host 192.168.1.1 # default: 0.0.0.0 (ANY)
|
18
|
+
port 8080 # default: 8080
|
19
|
+
use_msgpack false # default: false
|
20
|
+
add_time false # default: false
|
21
|
+
add_tag true # default: true
|
23
22
|
buffered_messages 100 # default: 0
|
23
|
+
token SomeToken # default: nil
|
24
24
|
</match>
|
25
25
|
|
26
26
|
* *host*: WebSocket server IP address.
|
@@ -29,6 +29,7 @@ This plugin depends on {*em-websocket*}[https://github.com/igrigorik/em-websocke
|
|
29
29
|
* <b>add_time</b>: Add timestamp to the data.
|
30
30
|
* <b>add_tag</b>: Add fluentd tag to the data.
|
31
31
|
* <b>buffered_messages</b>: The number of messages to be buffered. The new connection receives them.
|
32
|
+
* <b>token</b>: Authentication token. Passed as get param. If set to nil, authentication is disabled.
|
32
33
|
|
33
34
|
If there are no websocket connections, this plugin silently discards data. You may use <em>out_copy</em> plugin like this:
|
34
35
|
|
@@ -74,23 +75,33 @@ Extract data by {msgpack.js}[https://github.com/msgpack/msgpack-javascript].
|
|
74
75
|
...
|
75
76
|
}
|
76
77
|
|
77
|
-
|
78
|
+
=== Authentication and filtering
|
79
|
+
|
80
|
+
curl --include \
|
81
|
+
--no-buffer \
|
82
|
+
--header "Connection: Upgrade" \
|
83
|
+
--header "Upgrade: websocket" \
|
84
|
+
--header "Host: 127.0.0.1:8080" \
|
85
|
+
--header "Origin: http://127.0.0.1:8080" \
|
86
|
+
--header "Sec-WebSocket-Key: SGVabG8sIHOvcmxDIQ==" \
|
87
|
+
--header "Sec-WebSocket-Version: 13" \
|
88
|
+
"http://127.0.0.1:8888/?foo=bar&token=MyT0ken"
|
78
89
|
|
79
|
-
|
80
|
-
|
81
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
82
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
83
|
-
5. Create new Pull Request
|
90
|
+
* If token setting in config file is not nil, websocket server checks _token_ parameter
|
91
|
+
* Client will receive data which include \{"foo": "bar"\}
|
84
92
|
|
85
|
-
==
|
86
|
-
* 0.1.
|
93
|
+
== Changelogs
|
94
|
+
* 0.1.8 Add authentication and filtering
|
95
|
+
* 0.1.7 Add message buffering.
|
87
96
|
* 0.1.6 Added license to gemspec.
|
88
|
-
* 0.1.5 Fixed dependencies.
|
89
|
-
* 0.1.4 Changed json parser to yajl.
|
97
|
+
* 0.1.5 Fixed dependencies.
|
98
|
+
* 0.1.4 Changed json parser to yajl.
|
90
99
|
* 0.1.3 Bug fix.
|
91
100
|
* 0.1.2 Released gem.
|
92
101
|
|
102
|
+
See commit logs about contributors.
|
103
|
+
|
93
104
|
== Copyright
|
94
105
|
|
95
|
-
Copyright:: Copyright (c) 2013
|
106
|
+
Copyright:: Copyright (c) 2013 Tetsu Izawa (@moccos)
|
96
107
|
License:: Apache License, Version 2.0
|
data/examples/msgpack.js
ADDED
@@ -0,0 +1,646 @@
|
|
1
|
+
/* jshint browser: true */
|
2
|
+
/* global define, module */
|
3
|
+
( // Module boilerplate to support browser globals and browserify and AMD.
|
4
|
+
typeof define === "function" ? function (m) { define("msgpack-js", m); } :
|
5
|
+
typeof exports === "object" ? function (m) { module.exports = m(); } :
|
6
|
+
function(m){ this.msgpack = m(); }
|
7
|
+
)(function () {
|
8
|
+
"use strict";
|
9
|
+
|
10
|
+
var exports = {};
|
11
|
+
|
12
|
+
exports.inspect = inspect;
|
13
|
+
function inspect(buffer) {
|
14
|
+
if (buffer === undefined) return "undefined";
|
15
|
+
var view;
|
16
|
+
var type;
|
17
|
+
if (buffer instanceof ArrayBuffer) {
|
18
|
+
type = "ArrayBuffer";
|
19
|
+
view = new DataView(buffer);
|
20
|
+
}
|
21
|
+
else if (buffer instanceof DataView) {
|
22
|
+
type = "DataView";
|
23
|
+
view = buffer;
|
24
|
+
}
|
25
|
+
if (!view) return JSON.stringify(buffer);
|
26
|
+
var bytes = [];
|
27
|
+
for (var i = 0; i < buffer.byteLength; i++) {
|
28
|
+
if (i > 20) {
|
29
|
+
bytes.push("...");
|
30
|
+
break;
|
31
|
+
}
|
32
|
+
var byte = view.getUint8(i).toString(16);
|
33
|
+
if (byte.length === 1) byte = "0" + byte;
|
34
|
+
bytes.push(byte);
|
35
|
+
}
|
36
|
+
return "<" + type + " " + bytes.join(" ") + ">";
|
37
|
+
}
|
38
|
+
|
39
|
+
// Encode string as utf8 into dataview at offset
|
40
|
+
exports.utf8Write = utf8Write;
|
41
|
+
function utf8Write(view, offset, string) {
|
42
|
+
var byteLength = view.byteLength;
|
43
|
+
for(var i = 0, l = string.length; i < l; i++) {
|
44
|
+
var codePoint = string.charCodeAt(i);
|
45
|
+
|
46
|
+
// One byte of UTF-8
|
47
|
+
if (codePoint < 0x80) {
|
48
|
+
view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
|
49
|
+
continue;
|
50
|
+
}
|
51
|
+
|
52
|
+
// Two bytes of UTF-8
|
53
|
+
if (codePoint < 0x800) {
|
54
|
+
view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
|
55
|
+
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
56
|
+
continue;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Three bytes of UTF-8.
|
60
|
+
if (codePoint < 0x10000) {
|
61
|
+
view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
|
62
|
+
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
|
63
|
+
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
64
|
+
continue;
|
65
|
+
}
|
66
|
+
|
67
|
+
// Four bytes of UTF-8
|
68
|
+
if (codePoint < 0x110000) {
|
69
|
+
view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
|
70
|
+
view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
|
71
|
+
view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
|
72
|
+
view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
|
73
|
+
continue;
|
74
|
+
}
|
75
|
+
throw new Error("bad codepoint " + codePoint);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
exports.utf8Read = utf8Read;
|
80
|
+
function utf8Read(view, offset, length) {
|
81
|
+
var string = "";
|
82
|
+
for (var i = offset, end = offset + length; i < end; i++) {
|
83
|
+
var byte = view.getUint8(i);
|
84
|
+
// One byte character
|
85
|
+
if ((byte & 0x80) === 0x00) {
|
86
|
+
string += String.fromCharCode(byte);
|
87
|
+
continue;
|
88
|
+
}
|
89
|
+
// Two byte character
|
90
|
+
if ((byte & 0xe0) === 0xc0) {
|
91
|
+
string += String.fromCharCode(
|
92
|
+
((byte & 0x1f) << 6) |
|
93
|
+
(view.getUint8(++i) & 0x3f)
|
94
|
+
);
|
95
|
+
continue;
|
96
|
+
}
|
97
|
+
// Three byte character
|
98
|
+
if ((byte & 0xf0) === 0xe0) {
|
99
|
+
string += String.fromCharCode(
|
100
|
+
((byte & 0x0f) << 12) |
|
101
|
+
((view.getUint8(++i) & 0x3f) << 6) |
|
102
|
+
((view.getUint8(++i) & 0x3f) << 0)
|
103
|
+
);
|
104
|
+
continue;
|
105
|
+
}
|
106
|
+
// Four byte character
|
107
|
+
if ((byte & 0xf8) === 0xf0) {
|
108
|
+
string += String.fromCharCode(
|
109
|
+
((byte & 0x07) << 18) |
|
110
|
+
((view.getUint8(++i) & 0x3f) << 12) |
|
111
|
+
((view.getUint8(++i) & 0x3f) << 6) |
|
112
|
+
((view.getUint8(++i) & 0x3f) << 0)
|
113
|
+
);
|
114
|
+
continue;
|
115
|
+
}
|
116
|
+
throw new Error("Invalid byte " + byte.toString(16));
|
117
|
+
}
|
118
|
+
return string;
|
119
|
+
}
|
120
|
+
|
121
|
+
exports.utf8ByteCount = utf8ByteCount;
|
122
|
+
function utf8ByteCount(string) {
|
123
|
+
var count = 0;
|
124
|
+
for(var i = 0, l = string.length; i < l; i++) {
|
125
|
+
var codePoint = string.charCodeAt(i);
|
126
|
+
if (codePoint < 0x80) {
|
127
|
+
count += 1;
|
128
|
+
continue;
|
129
|
+
}
|
130
|
+
if (codePoint < 0x800) {
|
131
|
+
count += 2;
|
132
|
+
continue;
|
133
|
+
}
|
134
|
+
if (codePoint < 0x10000) {
|
135
|
+
count += 3;
|
136
|
+
continue;
|
137
|
+
}
|
138
|
+
if (codePoint < 0x110000) {
|
139
|
+
count += 4;
|
140
|
+
continue;
|
141
|
+
}
|
142
|
+
throw new Error("bad codepoint " + codePoint);
|
143
|
+
}
|
144
|
+
return count;
|
145
|
+
}
|
146
|
+
|
147
|
+
exports.encode = function (value) {
|
148
|
+
var buffer = new ArrayBuffer(encodedSize(value));
|
149
|
+
var view = new DataView(buffer);
|
150
|
+
encode(value, view, 0);
|
151
|
+
return buffer;
|
152
|
+
};
|
153
|
+
|
154
|
+
exports.decode = decode;
|
155
|
+
|
156
|
+
// https://github.com/msgpack/msgpack/blob/master/spec.md
|
157
|
+
// we reserve extension type 0x00 to encode javascript 'undefined'
|
158
|
+
|
159
|
+
function Decoder(view, offset) {
|
160
|
+
this.offset = offset || 0;
|
161
|
+
this.view = view;
|
162
|
+
}
|
163
|
+
Decoder.prototype.map = function (length) {
|
164
|
+
var value = {};
|
165
|
+
for (var i = 0; i < length; i++) {
|
166
|
+
var key = this.parse();
|
167
|
+
value[key] = this.parse();
|
168
|
+
}
|
169
|
+
return value;
|
170
|
+
};
|
171
|
+
Decoder.prototype.bin = function (length) {
|
172
|
+
var value = new ArrayBuffer(length);
|
173
|
+
(new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
|
174
|
+
this.offset += length;
|
175
|
+
return value;
|
176
|
+
};
|
177
|
+
Decoder.prototype.str = function (length) {
|
178
|
+
var value = utf8Read(this.view, this.offset, length);
|
179
|
+
this.offset += length;
|
180
|
+
return value;
|
181
|
+
};
|
182
|
+
Decoder.prototype.array = function (length) {
|
183
|
+
var value = new Array(length);
|
184
|
+
for (var i = 0; i < length; i++) {
|
185
|
+
value[i] = this.parse();
|
186
|
+
}
|
187
|
+
return value;
|
188
|
+
};
|
189
|
+
Decoder.prototype.parse = function () {
|
190
|
+
var type = this.view.getUint8(this.offset);
|
191
|
+
var value, length;
|
192
|
+
// FixStr
|
193
|
+
if ((type & 0xe0) === 0xa0) {
|
194
|
+
length = type & 0x1f;
|
195
|
+
this.offset++;
|
196
|
+
return this.str(length);
|
197
|
+
}
|
198
|
+
// FixMap
|
199
|
+
if ((type & 0xf0) === 0x80) {
|
200
|
+
length = type & 0x0f;
|
201
|
+
this.offset++;
|
202
|
+
return this.map(length);
|
203
|
+
}
|
204
|
+
// FixArray
|
205
|
+
if ((type & 0xf0) === 0x90) {
|
206
|
+
length = type & 0x0f;
|
207
|
+
this.offset++;
|
208
|
+
return this.array(length);
|
209
|
+
}
|
210
|
+
// Positive FixNum
|
211
|
+
if ((type & 0x80) === 0x00) {
|
212
|
+
this.offset++;
|
213
|
+
return type;
|
214
|
+
}
|
215
|
+
// Negative Fixnum
|
216
|
+
if ((type & 0xe0) === 0xe0) {
|
217
|
+
value = this.view.getInt8(this.offset);
|
218
|
+
this.offset++;
|
219
|
+
return value;
|
220
|
+
}
|
221
|
+
// Undefined as FixExt1
|
222
|
+
if (type === 0xd4 && this.view.getUint8(this.offset + 1) === 0x00) {
|
223
|
+
this.offset += 3;
|
224
|
+
return undefined;
|
225
|
+
}
|
226
|
+
switch (type) {
|
227
|
+
// str 8
|
228
|
+
case 0xd9:
|
229
|
+
length = this.view.getUint8(this.offset + 1);
|
230
|
+
this.offset += 2;
|
231
|
+
return this.str(length);
|
232
|
+
// str 16
|
233
|
+
case 0xda:
|
234
|
+
length = this.view.getUint16(this.offset + 1);
|
235
|
+
this.offset += 3;
|
236
|
+
return this.str(length);
|
237
|
+
// str 32
|
238
|
+
case 0xdb:
|
239
|
+
length = this.view.getUint32(this.offset + 1);
|
240
|
+
this.offset += 5;
|
241
|
+
return this.str(length);
|
242
|
+
// bin 8
|
243
|
+
case 0xc4:
|
244
|
+
length = this.view.getUint8(this.offset + 1);
|
245
|
+
this.offset += 2;
|
246
|
+
return this.bin(length);
|
247
|
+
// bin 16
|
248
|
+
case 0xc5:
|
249
|
+
length = this.view.getUint16(this.offset + 1);
|
250
|
+
this.offset += 3;
|
251
|
+
return this.bin(length);
|
252
|
+
// bin 32
|
253
|
+
case 0xc6:
|
254
|
+
length = this.view.getUint32(this.offset + 1);
|
255
|
+
this.offset += 5;
|
256
|
+
return this.bin(length);
|
257
|
+
// nil
|
258
|
+
case 0xc0:
|
259
|
+
this.offset++;
|
260
|
+
return null;
|
261
|
+
// false
|
262
|
+
case 0xc2:
|
263
|
+
this.offset++;
|
264
|
+
return false;
|
265
|
+
// true
|
266
|
+
case 0xc3:
|
267
|
+
this.offset++;
|
268
|
+
return true;
|
269
|
+
// uint8
|
270
|
+
case 0xcc:
|
271
|
+
value = this.view.getUint8(this.offset + 1);
|
272
|
+
this.offset += 2;
|
273
|
+
return value;
|
274
|
+
// uint 16
|
275
|
+
case 0xcd:
|
276
|
+
value = this.view.getUint16(this.offset + 1);
|
277
|
+
this.offset += 3;
|
278
|
+
return value;
|
279
|
+
// uint 32
|
280
|
+
case 0xce:
|
281
|
+
value = this.view.getUint32(this.offset + 1);
|
282
|
+
this.offset += 5;
|
283
|
+
return value;
|
284
|
+
// uint 64
|
285
|
+
case 0xcf:
|
286
|
+
var high = this.view.getUint32(this.offset + 1);
|
287
|
+
var low = this.view.getUint32(this.offset + 5);
|
288
|
+
value = high*0x100000000 + low;
|
289
|
+
this.offset += 9;
|
290
|
+
return value;
|
291
|
+
// int 8
|
292
|
+
case 0xd0:
|
293
|
+
value = this.view.getInt8(this.offset + 1);
|
294
|
+
this.offset += 2;
|
295
|
+
return value;
|
296
|
+
// int 16
|
297
|
+
case 0xd1:
|
298
|
+
value = this.view.getInt16(this.offset + 1);
|
299
|
+
this.offset += 3;
|
300
|
+
return value;
|
301
|
+
// int 32
|
302
|
+
case 0xd2:
|
303
|
+
value = this.view.getInt32(this.offset + 1);
|
304
|
+
this.offset += 5;
|
305
|
+
return value;
|
306
|
+
// int 64
|
307
|
+
case 0xd3:
|
308
|
+
var high = this.view.getInt32(this.offset + 1);
|
309
|
+
var low = this.view.getUint32(this.offset + 5);
|
310
|
+
value = high*0x100000000 + low;
|
311
|
+
this.offset += 9;
|
312
|
+
return value;
|
313
|
+
// map 16
|
314
|
+
case 0xde:
|
315
|
+
length = this.view.getUint16(this.offset + 1);
|
316
|
+
this.offset += 3;
|
317
|
+
return this.map(length);
|
318
|
+
// map 32
|
319
|
+
case 0xdf:
|
320
|
+
length = this.view.getUint32(this.offset + 1);
|
321
|
+
this.offset += 5;
|
322
|
+
return this.map(length);
|
323
|
+
// array 16
|
324
|
+
case 0xdc:
|
325
|
+
length = this.view.getUint16(this.offset + 1);
|
326
|
+
this.offset += 3;
|
327
|
+
return this.array(length);
|
328
|
+
// array 32
|
329
|
+
case 0xdd:
|
330
|
+
length = this.view.getUint32(this.offset + 1);
|
331
|
+
this.offset += 5;
|
332
|
+
return this.array(length);
|
333
|
+
// float
|
334
|
+
case 0xca:
|
335
|
+
value = this.view.getFloat32(this.offset + 1);
|
336
|
+
this.offset += 5;
|
337
|
+
return value;
|
338
|
+
// double
|
339
|
+
case 0xcb:
|
340
|
+
value = this.view.getFloat64(this.offset + 1);
|
341
|
+
this.offset += 9;
|
342
|
+
return value;
|
343
|
+
}
|
344
|
+
throw new Error("Unknown type 0x" + type.toString(16));
|
345
|
+
};
|
346
|
+
function decode(buffer) {
|
347
|
+
var view = new DataView(buffer);
|
348
|
+
var decoder = new Decoder(view);
|
349
|
+
var value = decoder.parse();
|
350
|
+
if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
|
351
|
+
return value;
|
352
|
+
}
|
353
|
+
|
354
|
+
function encode(value, view, offset) {
|
355
|
+
var type = typeof value;
|
356
|
+
|
357
|
+
// Strings Bytes
|
358
|
+
if (type === "string") {
|
359
|
+
var length = utf8ByteCount(value);
|
360
|
+
// fix str
|
361
|
+
if (length < 0x20) {
|
362
|
+
view.setUint8(offset, length | 0xa0);
|
363
|
+
utf8Write(view, offset + 1, value);
|
364
|
+
return 1 + length;
|
365
|
+
}
|
366
|
+
// str 8
|
367
|
+
if (length < 0x100) {
|
368
|
+
view.setUint8(offset, 0xd9);
|
369
|
+
view.setUint8(offset + 1, length);
|
370
|
+
utf8Write(view, offset + 2, value);
|
371
|
+
return 2 + length;
|
372
|
+
}
|
373
|
+
// str 16
|
374
|
+
if (length < 0x10000) {
|
375
|
+
view.setUint8(offset, 0xda);
|
376
|
+
view.setUint16(offset + 1, length);
|
377
|
+
utf8Write(view, offset + 3, value);
|
378
|
+
return 3 + length;
|
379
|
+
}
|
380
|
+
// str 32
|
381
|
+
if (length < 0x100000000) {
|
382
|
+
view.setUint8(offset, 0xdb);
|
383
|
+
view.setUint32(offset + 1, length);
|
384
|
+
utf8Write(view, offset + 5, value);
|
385
|
+
return 5 + length;
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
389
|
+
if (value instanceof ArrayBuffer) {
|
390
|
+
var length = value.byteLength;
|
391
|
+
// bin 8
|
392
|
+
if (length < 0x100) {
|
393
|
+
view.setUint8(offset, 0xc4);
|
394
|
+
view.setUint8(offset + 1, length);
|
395
|
+
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 2);
|
396
|
+
return 2 + length;
|
397
|
+
}
|
398
|
+
// bin 16
|
399
|
+
if (length < 0x10000) {
|
400
|
+
view.setUint8(offset, 0xc5);
|
401
|
+
view.setUint16(offset + 1, length);
|
402
|
+
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
|
403
|
+
return 3 + length;
|
404
|
+
}
|
405
|
+
// bin 32
|
406
|
+
if (length < 0x100000000) {
|
407
|
+
view.setUint8(offset, 0xc6);
|
408
|
+
view.setUint32(offset + 1, length);
|
409
|
+
(new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
|
410
|
+
return 5 + length;
|
411
|
+
}
|
412
|
+
}
|
413
|
+
|
414
|
+
if (type === "number") {
|
415
|
+
// Floating Point
|
416
|
+
if ((value << 0) !== value) {
|
417
|
+
view.setUint8(offset, 0xcb);
|
418
|
+
view.setFloat64(offset + 1, value);
|
419
|
+
return 9;
|
420
|
+
}
|
421
|
+
|
422
|
+
// Integers
|
423
|
+
if (value >=0) {
|
424
|
+
// positive fixnum
|
425
|
+
if (value < 0x80) {
|
426
|
+
view.setUint8(offset, value);
|
427
|
+
return 1;
|
428
|
+
}
|
429
|
+
// uint 8
|
430
|
+
if (value < 0x100) {
|
431
|
+
view.setUint8(offset, 0xcc);
|
432
|
+
view.setUint8(offset + 1, value);
|
433
|
+
return 2;
|
434
|
+
}
|
435
|
+
// uint 16
|
436
|
+
if (value < 0x10000) {
|
437
|
+
view.setUint8(offset, 0xcd);
|
438
|
+
view.setUint16(offset + 1, value);
|
439
|
+
return 3;
|
440
|
+
}
|
441
|
+
// uint 32
|
442
|
+
if (value < 0x100000000) {
|
443
|
+
view.setUint8(offset, 0xce);
|
444
|
+
view.setUint32(offset + 1, value);
|
445
|
+
return 5;
|
446
|
+
}
|
447
|
+
throw new Error("Number too big 0x" + value.toString(16));
|
448
|
+
}
|
449
|
+
// negative fixnum
|
450
|
+
if (value >= -0x20) {
|
451
|
+
view.setInt8(offset, value);
|
452
|
+
return 1;
|
453
|
+
}
|
454
|
+
// int 8
|
455
|
+
if (value >= -0x80) {
|
456
|
+
view.setUint8(offset, 0xd0);
|
457
|
+
view.setInt8(offset + 1, value);
|
458
|
+
return 2;
|
459
|
+
}
|
460
|
+
// int 16
|
461
|
+
if (value >= -0x8000) {
|
462
|
+
view.setUint8(offset, 0xd1);
|
463
|
+
view.setInt16(offset + 1, value);
|
464
|
+
return 3;
|
465
|
+
}
|
466
|
+
// int 32
|
467
|
+
if (value >= -0x80000000) {
|
468
|
+
view.setUint8(offset, 0xd2);
|
469
|
+
view.setInt32(offset + 1, value);
|
470
|
+
return 5;
|
471
|
+
}
|
472
|
+
throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
|
473
|
+
}
|
474
|
+
|
475
|
+
// undefined
|
476
|
+
if (type === "undefined") {
|
477
|
+
view.setUint8(offset, 0xd4); // fixext 1
|
478
|
+
view.setUint8(offset + 1, 0); // type (undefined)
|
479
|
+
view.setUint8(offset + 2, 0); // data (ignored)
|
480
|
+
return 3;
|
481
|
+
}
|
482
|
+
|
483
|
+
// null
|
484
|
+
if (value === null) {
|
485
|
+
view.setUint8(offset, 0xc0);
|
486
|
+
return 1;
|
487
|
+
}
|
488
|
+
|
489
|
+
// Boolean
|
490
|
+
if (type === "boolean") {
|
491
|
+
view.setUint8(offset, value ? 0xc3 : 0xc2);
|
492
|
+
return 1;
|
493
|
+
}
|
494
|
+
|
495
|
+
// Container Types
|
496
|
+
if (type === "object") {
|
497
|
+
var length, size = 0;
|
498
|
+
var isArray = Array.isArray(value);
|
499
|
+
|
500
|
+
if (isArray) {
|
501
|
+
length = value.length;
|
502
|
+
}
|
503
|
+
else {
|
504
|
+
var keys = Object.keys(value);
|
505
|
+
length = keys.length;
|
506
|
+
}
|
507
|
+
|
508
|
+
var size;
|
509
|
+
if (length < 0x10) {
|
510
|
+
view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
|
511
|
+
size = 1;
|
512
|
+
}
|
513
|
+
else if (length < 0x10000) {
|
514
|
+
view.setUint8(offset, isArray ? 0xdc : 0xde);
|
515
|
+
view.setUint16(offset + 1, length);
|
516
|
+
size = 3;
|
517
|
+
}
|
518
|
+
else if (length < 0x100000000) {
|
519
|
+
view.setUint8(offset, isArray ? 0xdd : 0xdf);
|
520
|
+
view.setUint32(offset + 1, length);
|
521
|
+
size = 5;
|
522
|
+
}
|
523
|
+
|
524
|
+
if (isArray) {
|
525
|
+
for (var i = 0; i < length; i++) {
|
526
|
+
size += encode(value[i], view, offset + size);
|
527
|
+
}
|
528
|
+
}
|
529
|
+
else {
|
530
|
+
for (var i = 0; i < length; i++) {
|
531
|
+
var key = keys[i];
|
532
|
+
size += encode(key, view, offset + size);
|
533
|
+
size += encode(value[key], view, offset + size);
|
534
|
+
}
|
535
|
+
}
|
536
|
+
|
537
|
+
return size;
|
538
|
+
}
|
539
|
+
throw new Error("Unknown type " + type);
|
540
|
+
}
|
541
|
+
|
542
|
+
function encodedSize(value) {
|
543
|
+
var type = typeof value;
|
544
|
+
|
545
|
+
// Raw Bytes
|
546
|
+
if (type === "string") {
|
547
|
+
var length = utf8ByteCount(value);
|
548
|
+
if (length < 0x20) {
|
549
|
+
return 1 + length;
|
550
|
+
}
|
551
|
+
if (length < 0x100) {
|
552
|
+
return 2 + length;
|
553
|
+
}
|
554
|
+
if (length < 0x10000) {
|
555
|
+
return 3 + length;
|
556
|
+
}
|
557
|
+
if (length < 0x100000000) {
|
558
|
+
return 5 + length;
|
559
|
+
}
|
560
|
+
}
|
561
|
+
|
562
|
+
if (value instanceof ArrayBuffer) {
|
563
|
+
var length = value.byteLength;
|
564
|
+
if (length < 0x100) {
|
565
|
+
return 2 + length;
|
566
|
+
}
|
567
|
+
if (length < 0x10000) {
|
568
|
+
return 3 + length;
|
569
|
+
}
|
570
|
+
if (length < 0x100000000) {
|
571
|
+
return 5 + length;
|
572
|
+
}
|
573
|
+
}
|
574
|
+
|
575
|
+
if (type === "number") {
|
576
|
+
// Floating Point
|
577
|
+
// double
|
578
|
+
if (value << 0 !== value) return 9;
|
579
|
+
|
580
|
+
// Integers
|
581
|
+
if (value >=0) {
|
582
|
+
// positive fixnum
|
583
|
+
if (value < 0x80) return 1;
|
584
|
+
// uint 8
|
585
|
+
if (value < 0x100) return 2;
|
586
|
+
// uint 16
|
587
|
+
if (value < 0x10000) return 3;
|
588
|
+
// uint 32
|
589
|
+
if (value < 0x100000000) return 5;
|
590
|
+
// uint 64
|
591
|
+
if (value < 0x10000000000000000) return 9;
|
592
|
+
throw new Error("Number too big 0x" + value.toString(16));
|
593
|
+
}
|
594
|
+
// negative fixnum
|
595
|
+
if (value >= -0x20) return 1;
|
596
|
+
// int 8
|
597
|
+
if (value >= -0x80) return 2;
|
598
|
+
// int 16
|
599
|
+
if (value >= -0x8000) return 3;
|
600
|
+
// int 32
|
601
|
+
if (value >= -0x80000000) return 5;
|
602
|
+
// int 64
|
603
|
+
if (value >= -0x8000000000000000) return 9;
|
604
|
+
throw new Error("Number too small -0x" + value.toString(16).substr(1));
|
605
|
+
}
|
606
|
+
|
607
|
+
// undefined
|
608
|
+
if (type === "undefined") return 3;
|
609
|
+
|
610
|
+
// Boolean, null
|
611
|
+
if (type === "boolean" || value === null) return 1;
|
612
|
+
|
613
|
+
// Container Types
|
614
|
+
if (type === "object") {
|
615
|
+
var length, size = 0;
|
616
|
+
if (Array.isArray(value)) {
|
617
|
+
length = value.length;
|
618
|
+
for (var i = 0; i < length; i++) {
|
619
|
+
size += encodedSize(value[i]);
|
620
|
+
}
|
621
|
+
}
|
622
|
+
else {
|
623
|
+
var keys = Object.keys(value);
|
624
|
+
length = keys.length;
|
625
|
+
for (var i = 0; i < length; i++) {
|
626
|
+
var key = keys[i];
|
627
|
+
size += encodedSize(key) + encodedSize(value[key]);
|
628
|
+
}
|
629
|
+
}
|
630
|
+
if (length < 0x10) {
|
631
|
+
return 1 + size;
|
632
|
+
}
|
633
|
+
if (length < 0x10000) {
|
634
|
+
return 3 + size;
|
635
|
+
}
|
636
|
+
if (length < 0x100000000) {
|
637
|
+
return 5 + size;
|
638
|
+
}
|
639
|
+
throw new Error("Array or object too long 0x" + length.toString(16));
|
640
|
+
}
|
641
|
+
throw new Error("Unknown type " + type);
|
642
|
+
}
|
643
|
+
|
644
|
+
return exports;
|
645
|
+
|
646
|
+
});
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
</head>
|
3
|
+
<meta charset="utf-8" />
|
4
|
+
<title>WebSocket Test</title>
|
5
|
+
</head>
|
6
|
+
<!-- based on http://www.websocket.org/echo.html -->
|
7
|
+
<body>
|
8
|
+
<!-- https://github.com/creationix/msgpack-js-browser --><script src="./msgpack.js"></script>
|
9
|
+
<script language="javascript" type="text/javascript">
|
10
|
+
|
11
|
+
var wsUri = "ws://localhost:38080/";
|
12
|
+
var output;
|
13
|
+
var latestData; // for debugging
|
14
|
+
|
15
|
+
function init()
|
16
|
+
{
|
17
|
+
output = document.getElementById("output");
|
18
|
+
testWebSocket();
|
19
|
+
}
|
20
|
+
|
21
|
+
function testWebSocket()
|
22
|
+
{
|
23
|
+
websocket = new WebSocket(wsUri);
|
24
|
+
websocket.binaryType = "arraybuffer";
|
25
|
+
websocket.onopen = function(evt) { onOpen(evt) };
|
26
|
+
websocket.onclose = function(evt) { onClose(evt) };
|
27
|
+
websocket.onmessage = function(evt) { onMessage(evt) };
|
28
|
+
websocket.onerror = function(evt) { onError(evt) };
|
29
|
+
}
|
30
|
+
|
31
|
+
function onOpen(evt)
|
32
|
+
{
|
33
|
+
writeToScreen("CONNECTED");
|
34
|
+
doSend("onOpen");
|
35
|
+
}
|
36
|
+
|
37
|
+
function onClose(evt)
|
38
|
+
{
|
39
|
+
writeToScreen("DISCONNECTED");
|
40
|
+
}
|
41
|
+
|
42
|
+
function onMessage(evt)
|
43
|
+
{
|
44
|
+
latestData = evt.data
|
45
|
+
if (typeof(evt.data) == 'string') {
|
46
|
+
text = evt.data;
|
47
|
+
} else {
|
48
|
+
decoded = msgpack.decode(evt.data);
|
49
|
+
text = JSON.stringify(decoded.slice(1));
|
50
|
+
}
|
51
|
+
writeToScreen('<span style="color: blue;">RESPONSE: ' + text +'</span>');
|
52
|
+
}
|
53
|
+
|
54
|
+
function onError(evt)
|
55
|
+
{
|
56
|
+
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
|
57
|
+
}
|
58
|
+
|
59
|
+
function doSend(message)
|
60
|
+
{
|
61
|
+
writeToScreen("SENT: " + message);
|
62
|
+
websocket.send(message);
|
63
|
+
}
|
64
|
+
|
65
|
+
function writeToScreen(message)
|
66
|
+
{
|
67
|
+
var pre = document.createElement("p");
|
68
|
+
pre.style.wordWrap = "break-word";
|
69
|
+
pre.innerHTML = message;
|
70
|
+
output.appendChild(pre);
|
71
|
+
}
|
72
|
+
|
73
|
+
window.addEventListener("load", init, false);
|
74
|
+
|
75
|
+
</script>
|
76
|
+
|
77
|
+
<h2>WebSocket Test</h2>
|
78
|
+
|
79
|
+
<div id="output"></div>
|
80
|
+
</body>
|
81
|
+
|
@@ -3,8 +3,8 @@ $:.push File.expand_path('../lib', __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.name = "fluent-plugin-websocket"
|
6
|
-
gem.version = "0.1.
|
7
|
-
gem.authors = ["
|
6
|
+
gem.version = "0.1.8"
|
7
|
+
gem.authors = ["Tetsu Izawa (@moccos)"]
|
8
8
|
gem.email = ["tt.izawa@gmail.com"]
|
9
9
|
gem.homepage = "https://github.com/moccos/fluent-plugin-websocket"
|
10
10
|
gem.summary = %q{Fluentd websocket output plugin}
|
@@ -28,6 +28,7 @@ module Fluent
|
|
28
28
|
config_param :add_time, :bool, :default => false
|
29
29
|
config_param :add_tag, :bool, :default => true
|
30
30
|
config_param :buffered_messages, :integer, :default => 0
|
31
|
+
config_param :token, :string, :default => nil
|
31
32
|
|
32
33
|
def configure(conf)
|
33
34
|
super
|
@@ -37,19 +38,28 @@ module Fluent
|
|
37
38
|
EM.run {
|
38
39
|
EM::WebSocket.run(:host => @host, :port => @port) do |ws|
|
39
40
|
ws.onopen { |handshake|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
$log.info "WebSocket opened #{{
|
42
|
+
:path => handshake.path,
|
43
|
+
:query => handshake.query,
|
44
|
+
:origin => handshake.origin,
|
45
|
+
}}"
|
46
|
+
if doAuth(handshake.query)
|
47
|
+
callback = @use_msgpack ? proc{|msg| ws.send_binary(msg)} : proc{|msg| sendMsg(handshake.query, ws, msg)}
|
48
|
+
$lock.synchronize do
|
49
|
+
sid = $channel.subscribe callback
|
50
|
+
$log.trace "WebSocket connection: ID " + sid.to_s
|
51
|
+
ws.onclose {
|
52
|
+
$log.trace "Connection closed: ID " + sid.to_s
|
53
|
+
$lock.synchronize do
|
54
|
+
$channel.unsubscribe(sid)
|
55
|
+
end
|
56
|
+
}
|
57
|
+
@buffer.each do |msg|
|
58
|
+
sendMsg(handshake.query, ws, msg)
|
48
59
|
end
|
49
|
-
}
|
50
|
-
@buffer.each do |msg|
|
51
|
-
ws.send(msg)
|
52
60
|
end
|
61
|
+
else
|
62
|
+
ws.send("Unauthorized")
|
53
63
|
end
|
54
64
|
|
55
65
|
#ws.onmessage { |msg|
|
@@ -60,6 +70,31 @@ module Fluent
|
|
60
70
|
end
|
61
71
|
end
|
62
72
|
|
73
|
+
def doAuth(query)
|
74
|
+
if @token.nil? || ( query.key?("token") && @token == query["token"] )
|
75
|
+
$log.trace "Auth OK"
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
|
79
|
+
$log.trace "Auth failed"
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
def sendMsg(filters, ws, msg)
|
84
|
+
parser = Yajl::Parser.new
|
85
|
+
msgStruct = parser.parse(msg)
|
86
|
+
return if msgStruct.length != 2
|
87
|
+
msgContent = msgStruct[1]
|
88
|
+
|
89
|
+
pass = 0
|
90
|
+
|
91
|
+
filters.each do |key, value|
|
92
|
+
pass += 1 if key == 'token' || ( msgContent.key?(key) && msgContent[key] == value )
|
93
|
+
end
|
94
|
+
|
95
|
+
ws.send(msg) if filters.length == pass
|
96
|
+
end
|
97
|
+
|
63
98
|
def start
|
64
99
|
@buffer = []
|
65
100
|
super
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-websocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Tetsu Izawa (@moccos)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -107,6 +107,8 @@ files:
|
|
107
107
|
- LICENSE.txt
|
108
108
|
- README.rdoc
|
109
109
|
- Rakefile
|
110
|
+
- examples/msgpack.js
|
111
|
+
- examples/websocket.html
|
110
112
|
- fluent-plugin-websocket.gemspec
|
111
113
|
- lib/fluent/plugin/out_websocket.rb
|
112
114
|
- test/plugin/test_out_websocket.rb
|
@@ -130,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
132
|
version: '0'
|
131
133
|
requirements: []
|
132
134
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
135
|
+
rubygems_version: 2.6.11
|
134
136
|
signing_key:
|
135
137
|
specification_version: 4
|
136
138
|
summary: Fluentd websocket output plugin
|