iodine 0.7.59 → 0.8.0
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/.clang-format +15 -0
- data/.rspec +1 -0
- data/.yardopts +1 -3
- data/CHANGELOG.md +132 -12
- data/Gemfile +5 -7
- data/LICENSE.txt +1 -1
- data/README.md +147 -671
- data/Rakefile +9 -16
- data/examples/chatroom.nru +9 -0
- data/examples/client +74 -0
- data/examples/config-hello.nru +9 -0
- data/examples/config-hello.ru +11 -0
- data/examples/config-hijack.ru +13 -0
- data/examples/config-shootout.ru +43 -0
- data/examples/config.nru +120 -0
- data/examples/config.rb +37 -0
- data/examples/config.ru +42 -53
- data/examples/fake +24 -0
- data/examples/hello_neorack +137 -0
- data/examples/routes.nru +29 -0
- data/examples/routes.ru +42 -0
- data/exe/iodine +218 -258
- data/ext/iodine/extconf.rb +27 -100
- data/ext/iodine/fio-stl.h +128336 -0
- data/ext/iodine/fio-stl.md +26396 -0
- data/ext/iodine/iodine.c +213 -1393
- data/ext/iodine/iodine.h +250 -55
- data/ext/iodine/iodine_arg_helper.h +329 -0
- data/ext/iodine/iodine_caller.h +234 -25
- data/ext/iodine/iodine_cli.h +434 -0
- data/ext/iodine/iodine_compression.h +312 -0
- data/ext/iodine/iodine_connection.h +3484 -34
- data/ext/iodine/iodine_core.h +363 -0
- data/ext/iodine/iodine_crypto.h +1441 -0
- data/ext/iodine/iodine_defer.h +225 -4
- data/ext/iodine/iodine_json.h +738 -4
- data/ext/iodine/iodine_listener.h +263 -0
- data/ext/iodine/iodine_log.h +297 -0
- data/ext/iodine/iodine_minimap.h +543 -0
- data/ext/iodine/iodine_mustache.h +461 -4
- data/ext/iodine/iodine_pubsub_eng.h +729 -0
- data/ext/iodine/iodine_pubsub_history.h +547 -0
- data/ext/iodine/iodine_pubsub_msg.h +228 -0
- data/ext/iodine/iodine_redis.h +322 -0
- data/ext/iodine/iodine_store.h +418 -16
- data/ext/iodine/iodine_threads.h +279 -0
- data/ext/iodine/iodine_tls.h +515 -6
- data/ext/iodine/iodine_utils.h +923 -0
- data/iodine.gemspec +37 -42
- data/lib/iodine/benchmark.rb +1690 -0
- data/lib/iodine/documentation.rb +3085 -0
- data/lib/iodine/version.rb +17 -1
- data/lib/iodine.rb +54 -255
- data/logo.svg +36 -0
- data/mustache.md +55 -0
- data/sig/iodine.rbs +4 -0
- metadata +58 -184
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- data/.github/workflows/ruby.yml +0 -42
- data/.gitignore +0 -20
- data/LIMITS.md +0 -41
- data/SPEC-PubSub-Draft.md +0 -159
- data/SPEC-WebSocket-Draft.md +0 -239
- data/bin/console +0 -22
- data/bin/info.md +0 -353
- data/bin/mustache_bench.rb +0 -100
- data/bin/poc/Gemfile.lock +0 -23
- data/bin/poc/README.md +0 -37
- data/bin/poc/config.ru +0 -66
- data/bin/poc/gemfile +0 -1
- data/bin/poc/www/index.html +0 -57
- data/examples/async_task.ru +0 -92
- data/examples/bates/README.md +0 -3
- data/examples/bates/config.ru +0 -342
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +0 -600
- data/examples/echo.ru +0 -59
- data/examples/etag.ru +0 -16
- data/examples/hello.ru +0 -29
- data/examples/pubsub_engine.ru +0 -81
- data/examples/rack3.ru +0 -12
- data/examples/redis.ru +0 -70
- data/examples/shootout.ru +0 -73
- data/examples/sub-protocols.ru +0 -90
- data/examples/tcp_client.rb +0 -66
- data/examples/x-sendfile.ru +0 -14
- data/ext/iodine/fio.c +0 -11995
- data/ext/iodine/fio.h +0 -6371
- data/ext/iodine/fio_cli.c +0 -431
- data/ext/iodine/fio_cli.h +0 -189
- data/ext/iodine/fio_json_parser.h +0 -688
- data/ext/iodine/fio_siphash.c +0 -157
- data/ext/iodine/fio_siphash.h +0 -37
- data/ext/iodine/fio_tls.h +0 -129
- data/ext/iodine/fio_tls_missing.c +0 -649
- data/ext/iodine/fio_tls_openssl.c +0 -1106
- data/ext/iodine/fio_tmpfile.h +0 -50
- data/ext/iodine/fiobj.h +0 -44
- data/ext/iodine/fiobj4fio.h +0 -21
- data/ext/iodine/fiobj_ary.c +0 -333
- data/ext/iodine/fiobj_ary.h +0 -139
- data/ext/iodine/fiobj_data.c +0 -1187
- data/ext/iodine/fiobj_data.h +0 -167
- data/ext/iodine/fiobj_hash.c +0 -409
- data/ext/iodine/fiobj_hash.h +0 -176
- data/ext/iodine/fiobj_json.c +0 -622
- data/ext/iodine/fiobj_json.h +0 -68
- data/ext/iodine/fiobj_mem.h +0 -71
- data/ext/iodine/fiobj_mustache.c +0 -317
- data/ext/iodine/fiobj_mustache.h +0 -62
- data/ext/iodine/fiobj_numbers.c +0 -344
- data/ext/iodine/fiobj_numbers.h +0 -127
- data/ext/iodine/fiobj_str.c +0 -433
- data/ext/iodine/fiobj_str.h +0 -172
- data/ext/iodine/fiobject.c +0 -620
- data/ext/iodine/fiobject.h +0 -655
- data/ext/iodine/hpack.h +0 -1923
- data/ext/iodine/http.c +0 -2743
- data/ext/iodine/http.h +0 -1002
- data/ext/iodine/http1.c +0 -910
- data/ext/iodine/http1.h +0 -29
- data/ext/iodine/http1_parser.h +0 -878
- data/ext/iodine/http_internal.c +0 -1279
- data/ext/iodine/http_internal.h +0 -237
- data/ext/iodine/http_mime_parser.h +0 -350
- data/ext/iodine/iodine_caller.c +0 -230
- data/ext/iodine/iodine_connection.c +0 -941
- data/ext/iodine/iodine_defer.c +0 -420
- data/ext/iodine/iodine_fiobj2rb.h +0 -120
- data/ext/iodine/iodine_helpers.c +0 -282
- data/ext/iodine/iodine_helpers.h +0 -12
- data/ext/iodine/iodine_http.c +0 -1181
- data/ext/iodine/iodine_http.h +0 -23
- data/ext/iodine/iodine_json.c +0 -302
- data/ext/iodine/iodine_mustache.c +0 -567
- data/ext/iodine/iodine_pubsub.c +0 -580
- data/ext/iodine/iodine_pubsub.h +0 -26
- data/ext/iodine/iodine_rack_io.c +0 -273
- data/ext/iodine/iodine_rack_io.h +0 -20
- data/ext/iodine/iodine_store.c +0 -146
- data/ext/iodine/iodine_tcp.c +0 -346
- data/ext/iodine/iodine_tcp.h +0 -13
- data/ext/iodine/iodine_tls.c +0 -261
- data/ext/iodine/mustache_parser.h +0 -1546
- data/ext/iodine/redis_engine.c +0 -957
- data/ext/iodine/redis_engine.h +0 -79
- data/ext/iodine/resp_parser.h +0 -317
- data/ext/iodine/websocket_parser.h +0 -506
- data/ext/iodine/websockets.c +0 -743
- data/ext/iodine/websockets.h +0 -185
- data/lib/iodine/connection.rb +0 -61
- data/lib/iodine/json.rb +0 -42
- data/lib/iodine/mustache.rb +0 -113
- data/lib/iodine/pubsub.rb +0 -55
- data/lib/iodine/rack_utils.rb +0 -43
- data/lib/iodine/tls.rb +0 -16
- data/lib/rack/handler/iodine.rb +0 -33
- data/logo.png +0 -0
data/bin/mustache_bench.rb
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require 'benchmark/ips'
|
|
4
|
-
require 'mustache'
|
|
5
|
-
require 'iodine'
|
|
6
|
-
|
|
7
|
-
def benchmark_mustache
|
|
8
|
-
# benchmark code was copied, in part, from:
|
|
9
|
-
# https://github.com/mustache/mustache/blob/master/benchmarks/render_collection_benchmark.rb
|
|
10
|
-
template = """
|
|
11
|
-
{{#products}}
|
|
12
|
-
<div class='product_brick'>
|
|
13
|
-
<div class='container'>
|
|
14
|
-
<div class='element'>
|
|
15
|
-
<img src='images/{{image}}' class='product_miniature' />
|
|
16
|
-
</div>
|
|
17
|
-
<div class='element description'>
|
|
18
|
-
<a href={{url}} class='product_name block bold'>
|
|
19
|
-
{{external_index}}
|
|
20
|
-
</a>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
{{/products}}
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
IO.write "test_template.mustache", template
|
|
28
|
-
filename = "test_template.mustache"
|
|
29
|
-
|
|
30
|
-
data_1 = {
|
|
31
|
-
products: [ {
|
|
32
|
-
:external_index=>"This <product> should've been \"properly\" escaped.",
|
|
33
|
-
:url=>"/products/7",
|
|
34
|
-
:image=>"products/product.jpg"
|
|
35
|
-
} ]
|
|
36
|
-
}
|
|
37
|
-
data_1000 = {
|
|
38
|
-
products: []
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
1000.times do
|
|
42
|
-
data_1000[:products] << {
|
|
43
|
-
:external_index=>"product",
|
|
44
|
-
:url=>"/products/7",
|
|
45
|
-
:image=>"products/product.jpg"
|
|
46
|
-
}
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
data_1000_escaped = {
|
|
50
|
-
products: []
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
1000.times do
|
|
54
|
-
data_1000_escaped[:products] << {
|
|
55
|
-
:external_index=>"This <product> should've been \"properly\" escaped.",
|
|
56
|
-
:url=>"/products/7",
|
|
57
|
-
:image=>"products/product.jpg"
|
|
58
|
-
}
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
view = Mustache.new
|
|
62
|
-
view.template = template
|
|
63
|
-
view.render # Call render once so the template will be compiled
|
|
64
|
-
iodine_view = Iodine::Mustache.new(filename)
|
|
65
|
-
|
|
66
|
-
puts "Ruby Mustache rendering (and HTML escaping) results in:",
|
|
67
|
-
view.render(data_1), "",
|
|
68
|
-
"Notice that Iodine::Mustache rendering (and HTML escaping) results in agressive escaping:",
|
|
69
|
-
iodine_view.render(data_1), "", "----"
|
|
70
|
-
|
|
71
|
-
# return;
|
|
72
|
-
|
|
73
|
-
Benchmark.ips do |x|
|
|
74
|
-
x.report("Ruby Mustache render list of 1000") do |times|
|
|
75
|
-
view.render(data_1000)
|
|
76
|
-
end
|
|
77
|
-
x.report("Iodine::Mustache render list of 1000") do |times|
|
|
78
|
-
iodine_view.render(data_1000)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
x.report("Ruby Mustache render list of 1000 with escaped data") do |times|
|
|
82
|
-
view.render(data_1000_escaped)
|
|
83
|
-
end
|
|
84
|
-
x.report("Iodine::Mustache render list of 1000 with escaped data") do |times|
|
|
85
|
-
iodine_view.render(data_1000_escaped)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
x.report("Ruby Mustache - no chaching - render list of 1000") do |times|
|
|
89
|
-
tmp = Mustache.new
|
|
90
|
-
tmp.template = template
|
|
91
|
-
tmp.render(data_1000)
|
|
92
|
-
end
|
|
93
|
-
x.report("Iodine::Mustache - no chaching - render list of 1000") do |times|
|
|
94
|
-
Iodine::Mustache.render(nil, data_1000, template)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
benchmark_mustache
|
data/bin/poc/Gemfile.lock
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
GIT
|
|
2
|
-
remote: https://github.com/boazsegev/iodine.git
|
|
3
|
-
revision: 8b57a5f2008b9c35f2cf589be7ed121823a84582
|
|
4
|
-
specs:
|
|
5
|
-
iodine (0.2.0)
|
|
6
|
-
rack
|
|
7
|
-
rake-compiler
|
|
8
|
-
|
|
9
|
-
GEM
|
|
10
|
-
specs:
|
|
11
|
-
rack (2.0.1)
|
|
12
|
-
rake (11.2.2)
|
|
13
|
-
rake-compiler (0.9.5)
|
|
14
|
-
rake
|
|
15
|
-
|
|
16
|
-
PLATFORMS
|
|
17
|
-
ruby
|
|
18
|
-
|
|
19
|
-
DEPENDENCIES
|
|
20
|
-
iodine!
|
|
21
|
-
|
|
22
|
-
BUNDLED WITH
|
|
23
|
-
1.12.5
|
data/bin/poc/README.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# A proof of concept for Rack's `env['rack.websocket']`
|
|
2
|
-
|
|
3
|
-
This is a proof of concept for Rack based Websocket connections, showing how the Rack API can be adjusted to support server native real-time connections.
|
|
4
|
-
|
|
5
|
-
The chosen proof of concept was the ugliest chatroom I could find.
|
|
6
|
-
|
|
7
|
-
Although my hope is that Rack will adopt the concept and make `env['rack.websocket?']` and `env['rack.websocket']` part of it's standard, at the moment it's an Iodine specific feature, implemented using `env['iodine.websocket']`.
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
Install required gems using:
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
bundler install
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Run
|
|
18
|
-
|
|
19
|
-
Run this application single threaded:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
bundler exec iodine -- -www ./www
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Or both multi-threaded and forked (you'll notice that memory barriers for forked processes prevent websocket broadcasting from reaching websockets connected to a different process).
|
|
26
|
-
|
|
27
|
-
```sh
|
|
28
|
-
bundler exec iodine -- -www ./www -t 16 -w 4
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Further reading
|
|
32
|
-
|
|
33
|
-
* https://github.com/rack/rack/issues/1093
|
|
34
|
-
|
|
35
|
-
* https://bowild.wordpress.com/2016/07/31/the-dark-side-of-the-rack
|
|
36
|
-
|
|
37
|
-
* https://github.com/boazsegev/iodine
|
data/bin/poc/config.ru
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# The Rack Application container
|
|
2
|
-
module MyRackApplication
|
|
3
|
-
# Rack applications use the `call` callback to handle HTTP requests.
|
|
4
|
-
def self.call(env)
|
|
5
|
-
# if upgrading...
|
|
6
|
-
if env['HTTP_UPGRADE'.freeze] =~ /websocket/i
|
|
7
|
-
# We can assign a class or an instance that implements callbacks.
|
|
8
|
-
# We will assign an object, passing it the request information (`env`)
|
|
9
|
-
env['iodine.websocket'.freeze] = MyWebsocket.new(env)
|
|
10
|
-
# Rack responses must be a 3 item array
|
|
11
|
-
# [status, {http: :headers}, ["response body"]]
|
|
12
|
-
return [0, {}, []]
|
|
13
|
-
end
|
|
14
|
-
# a semi-regualr HTTP response
|
|
15
|
-
out = File.open File.expand_path('../www/index.html', __FILE__)
|
|
16
|
-
[200, { 'X-Sendfile' => File.expand_path('../www/index.html', __FILE__),
|
|
17
|
-
'Content-Length' => out.size }, out]
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# The Websocket Callback Object
|
|
22
|
-
class MyWebsocket
|
|
23
|
-
# this is optional, but I wanted the object to have the nickname provided in
|
|
24
|
-
# the HTTP request
|
|
25
|
-
def initialize(env)
|
|
26
|
-
# we need to change the ASCI Rack encoding to UTF-8,
|
|
27
|
-
# otherwise everything with the nickname will be a binary "blob" in the
|
|
28
|
-
# Javascript layer
|
|
29
|
-
@nickname = env['PATH_INFO'][1..-1].force_encoding 'UTF-8'
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# A classic websocket callback, called when the connection is opened and
|
|
33
|
-
# linked to this object
|
|
34
|
-
def on_open
|
|
35
|
-
puts 'We have a websocket connection'
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# A classic websocket callback, called when the connection is closed
|
|
39
|
-
# (after disconnection).
|
|
40
|
-
def on_close
|
|
41
|
-
puts "Bye Bye... #{count} connections left..."
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# A server-side niceness, called when the server if shutting down,
|
|
45
|
-
# to gracefully disconnect (before disconnection).
|
|
46
|
-
def on_shutdown
|
|
47
|
-
write 'The server is shutting down, goodbye.'
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def on_message(data)
|
|
51
|
-
puts "got message: #{data} encoded as #{data.encoding}"
|
|
52
|
-
# data is a temporary string, it's buffer cleared as soon as we return.
|
|
53
|
-
# So we make a copy with the desired format.
|
|
54
|
-
tmp = "#{@nickname}: #{data}"
|
|
55
|
-
# The `write` method was added by the server and writes to the current
|
|
56
|
-
# connection
|
|
57
|
-
write tmp
|
|
58
|
-
puts "broadcasting #{tmp.bytesize} bytes with encoding #{tmp.encoding}"
|
|
59
|
-
# `each` was added by the server and excludes this connection
|
|
60
|
-
# (each except self).
|
|
61
|
-
each { |h| h.write tmp }
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# `run` is a Rack API command, telling Rack where the `call(env)` callback is located.
|
|
66
|
-
run MyRackApplication
|
data/bin/poc/gemfile
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gem 'iodine', git: 'https://github.com/boazsegev/iodine.git'
|
data/bin/poc/www/index.html
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
|
5
|
-
<script>
|
|
6
|
-
ws = NaN
|
|
7
|
-
handle = ''
|
|
8
|
-
function onsubmit(e) {
|
|
9
|
-
e.preventDefault();
|
|
10
|
-
if($('#text')[0].value == '') {return false}
|
|
11
|
-
if(ws && ws.readyState == 1) {
|
|
12
|
-
ws.send($('#text')[0].value);
|
|
13
|
-
$('#text')[0].value = '';
|
|
14
|
-
} else {
|
|
15
|
-
handle = $('#text')[0].value
|
|
16
|
-
var url = (window.location.protocol.match(/https/) ? 'wss' : 'ws') +
|
|
17
|
-
'://' + window.document.location.host +
|
|
18
|
-
'/' + $('#text')[0].value
|
|
19
|
-
ws = new WebSocket(url)
|
|
20
|
-
ws.onopen = function(e) {
|
|
21
|
-
output("<b>Connected :-)</b>");
|
|
22
|
-
$('#text')[0].value = '';
|
|
23
|
-
$('#text')[0].placeholder = 'your message';
|
|
24
|
-
}
|
|
25
|
-
ws.onclose = function(e) {
|
|
26
|
-
output("<b>Disonnected :-/</b>")
|
|
27
|
-
$('#text')[0].value = '';
|
|
28
|
-
$('#text')[0].placeholder = 'nickname';
|
|
29
|
-
$('#text')[0].value = handle
|
|
30
|
-
}
|
|
31
|
-
ws.onmessage = function(e) {
|
|
32
|
-
output(e.data);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
function output(data) {
|
|
38
|
-
$('#output').append("<li>" + data + "</li>")
|
|
39
|
-
$('#output').animate({ scrollTop:
|
|
40
|
-
$('#output')[0].scrollHeight }, "slow");
|
|
41
|
-
}
|
|
42
|
-
</script>
|
|
43
|
-
<style>
|
|
44
|
-
html, body {width:100%; height: 100%; background-color: #ddd; color: #111;}
|
|
45
|
-
h3, form {text-align: center;}
|
|
46
|
-
input {background-color: #fff; color: #111; padding: 0.3em;}
|
|
47
|
-
</style>
|
|
48
|
-
</head><body>
|
|
49
|
-
<h3>The Ugly Chatroom POC</h3>
|
|
50
|
-
<form id='form'>
|
|
51
|
-
<input type='text' id='text' name='text' placeholder='nickname'></input>
|
|
52
|
-
<input type='submit' value='send'></input>
|
|
53
|
-
</form>
|
|
54
|
-
<script> $('#form')[0].onsubmit = onsubmit </script>
|
|
55
|
-
<ul id='output'></ul>
|
|
56
|
-
</body>
|
|
57
|
-
</html>
|
data/examples/async_task.ru
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# This is a task scheduling WebSocket push example application.
|
|
2
|
-
#
|
|
3
|
-
# Benchmark HTTPP with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
|
|
4
|
-
#
|
|
5
|
-
# ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
|
|
6
|
-
# wrk -c2000 -d5 -t12 http://localhost:3000/
|
|
7
|
-
#
|
|
8
|
-
# Test websocket tasks using the browser. For example:
|
|
9
|
-
# ws = new WebSocket("ws://localhost:3000/userID"); ws.onmessage = function(e) {console.log(e.data);}; ws.onclose = function(e) {console.log("closed")};
|
|
10
|
-
# ws.onopen = function(e) {ws.send(JSON.stringify({'task': 'echo', 'data': 'Hello!'}));};
|
|
11
|
-
require 'iodine'
|
|
12
|
-
require 'json'
|
|
13
|
-
|
|
14
|
-
TASK_PUBLISHING_ENGINE = Iodine::PubSub::PROCESS
|
|
15
|
-
|
|
16
|
-
# This module handles tasks and send them back to the frontend
|
|
17
|
-
module TaskHandler
|
|
18
|
-
def echo msg
|
|
19
|
-
msg = Iodine::JSON.parse(msg, symbolize_names: true)
|
|
20
|
-
publish_to = msg.delete(:from)
|
|
21
|
-
Iodine.publish(publish_to, msg.to_json, TASK_PUBLISHING_ENGINE) if publish_to
|
|
22
|
-
puts "performed 'echo' task"
|
|
23
|
-
rescue => e
|
|
24
|
-
puts "JSON task message error? #{e.message} - under attack?"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def add msg
|
|
28
|
-
msg = Iodine::JSON.parse(msg, symbolize_names: true)
|
|
29
|
-
raise "addition task requires an array of numbers" unless msg[:data].is_a?(Array)
|
|
30
|
-
msg[:data] = msg[:data].inject(0){|sum,x| sum + x }
|
|
31
|
-
publish_to = msg.delete(:from)
|
|
32
|
-
Iodine.publish(publish_to, msg.to_json, TASK_PUBLISHING_ENGINE) if publish_to
|
|
33
|
-
puts "performed 'add' task"
|
|
34
|
-
rescue => e
|
|
35
|
-
puts
|
|
36
|
-
"JSON task message error? #{e.message} - under attack?"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def listen2tasks
|
|
40
|
-
Iodine.subscribe(:echo) {|ch,msg| TaskHandler.echo(msg) }
|
|
41
|
-
Iodine.subscribe(:add) {|ch,msg| TaskHandler.add(msg) }
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
extend self
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
module WebsocketClient
|
|
48
|
-
def on_open client
|
|
49
|
-
# Pub/Sub directly to the client (or use a block to process the messages)
|
|
50
|
-
client.subscribe client.env['PATH_INFO'.freeze]
|
|
51
|
-
end
|
|
52
|
-
def on_message client, data
|
|
53
|
-
# Strings and symbol channel names are equivalent.
|
|
54
|
-
msg = Iodine::JSON.parse(data, symbolize_names: true)
|
|
55
|
-
raise "no valid task" unless ["echo".freeze, "add".freeze].include? msg[:task]
|
|
56
|
-
msg[:from] = client.env['PATH_INFO'.freeze]
|
|
57
|
-
client.publish msg[:task], msg.to_json, TASK_PUBLISHING_ENGINE
|
|
58
|
-
rescue => e
|
|
59
|
-
puts "JSON message error? #{e.message}\n\t#{data}\n\t#{msg}"
|
|
60
|
-
end
|
|
61
|
-
extend self
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
APP = Proc.new do |env|
|
|
65
|
-
if env['rack.upgrade?'.freeze] == :websocket
|
|
66
|
-
env['rack.upgrade'.freeze] = WebsocketClient
|
|
67
|
-
[0,{}, []] # It's possible to set cookies for the response.
|
|
68
|
-
elsif env['rack.upgrade?'.freeze] == :sse
|
|
69
|
-
puts "SSE connections can only receive data from the server, the can't write."
|
|
70
|
-
env['rack.upgrade'.freeze] = WebsocketClient
|
|
71
|
-
[0,{}, []] # It's possible to set cookies for the response.
|
|
72
|
-
else
|
|
73
|
-
[200, {"Content-Type" => "text/plain"}, ["Send messages with WebSockets using JSON.\ni.e.: {\"task\":\"add\", \"data\":[1,2]}"]]
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# test automatically for Redis extensions.
|
|
78
|
-
if(Iodine::PubSub.default.is_a? Iodine::PubSub::Redis)
|
|
79
|
-
TASK_PUBLISHING_ENGINE = Iodine::PubSub.default
|
|
80
|
-
if(ARGV.include? "worker")
|
|
81
|
-
TaskHandler.listen2tasks
|
|
82
|
-
Iodine.workers = 1
|
|
83
|
-
Iodine.threads = 16 if Iodine.threads == 0
|
|
84
|
-
Iodine.start
|
|
85
|
-
exit(0)
|
|
86
|
-
end
|
|
87
|
-
else
|
|
88
|
-
TaskHandler.listen2tasks
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# # or in config.ru
|
|
92
|
-
run APP
|
data/examples/bates/README.md
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
# Bates numbering with CombinePDF and Rack
|
|
2
|
-
|
|
3
|
-
This folder holds a demo application combining Iodine's `X-Sendfile` support with the [`combine_pdf` gem](https://github.com/boazsegev/combine_pdf) to create a "bates numbering" tool that is common to the one used by some court systems (such as Israeli courts).
|