opal-up 0.0.2 → 0.0.4

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +209 -0
  3. data/README.md +97 -29
  4. data/bin/up_ruby +4 -0
  5. data/bin/up_ruby_cluster +4 -0
  6. data/ext/up_ext/App.h +606 -0
  7. data/ext/up_ext/AsyncSocket.h +355 -0
  8. data/ext/up_ext/AsyncSocketData.h +87 -0
  9. data/ext/up_ext/BloomFilter.h +83 -0
  10. data/ext/up_ext/ChunkedEncoding.h +236 -0
  11. data/ext/up_ext/ClientApp.h +36 -0
  12. data/ext/up_ext/HttpContext.h +502 -0
  13. data/ext/up_ext/HttpContextData.h +56 -0
  14. data/ext/up_ext/HttpErrors.h +53 -0
  15. data/ext/up_ext/HttpParser.h +680 -0
  16. data/ext/up_ext/HttpResponse.h +578 -0
  17. data/ext/up_ext/HttpResponseData.h +95 -0
  18. data/ext/up_ext/HttpRouter.h +380 -0
  19. data/ext/up_ext/Loop.h +204 -0
  20. data/ext/up_ext/LoopData.h +112 -0
  21. data/ext/up_ext/MoveOnlyFunction.h +377 -0
  22. data/ext/up_ext/PerMessageDeflate.h +315 -0
  23. data/ext/up_ext/ProxyParser.h +163 -0
  24. data/ext/up_ext/QueryParser.h +120 -0
  25. data/ext/up_ext/TopicTree.h +363 -0
  26. data/ext/up_ext/Utilities.h +66 -0
  27. data/ext/up_ext/WebSocket.h +381 -0
  28. data/ext/up_ext/WebSocketContext.h +434 -0
  29. data/ext/up_ext/WebSocketContextData.h +109 -0
  30. data/ext/up_ext/WebSocketData.h +86 -0
  31. data/ext/up_ext/WebSocketExtensions.h +256 -0
  32. data/ext/up_ext/WebSocketHandshake.h +145 -0
  33. data/ext/up_ext/WebSocketProtocol.h +506 -0
  34. data/ext/up_ext/bsd.c +767 -0
  35. data/ext/up_ext/bsd.h +109 -0
  36. data/ext/up_ext/context.c +524 -0
  37. data/ext/up_ext/epoll_kqueue.c +458 -0
  38. data/ext/up_ext/epoll_kqueue.h +67 -0
  39. data/ext/up_ext/extconf.rb +5 -0
  40. data/ext/up_ext/internal.h +224 -0
  41. data/ext/up_ext/libusockets.h +350 -0
  42. data/ext/up_ext/libuwebsockets.cpp +1344 -0
  43. data/ext/up_ext/libuwebsockets.h +396 -0
  44. data/ext/up_ext/loop.c +386 -0
  45. data/ext/up_ext/loop_data.h +38 -0
  46. data/ext/up_ext/socket.c +231 -0
  47. data/ext/up_ext/up_ext.c +930 -0
  48. data/lib/up/bun/rack_env.rb +1 -13
  49. data/lib/up/bun/server.rb +93 -19
  50. data/lib/up/cli.rb +3 -0
  51. data/lib/up/client.rb +68 -0
  52. data/lib/up/ruby/cluster.rb +39 -0
  53. data/lib/up/ruby/cluster_cli.rb +10 -0
  54. data/lib/up/{node → ruby}/rack_cluster.rb +5 -4
  55. data/lib/up/{node → ruby}/rack_server.rb +4 -4
  56. data/lib/up/ruby/server_cli.rb +10 -0
  57. data/lib/up/u_web_socket/cluster.rb +18 -3
  58. data/lib/up/u_web_socket/server.rb +108 -15
  59. data/lib/up/version.rb +1 -1
  60. metadata +72 -30
  61. data/.gitignore +0 -5
  62. data/Gemfile +0 -2
  63. data/bin/up_node +0 -12
  64. data/bin/up_node_cluster +0 -12
  65. data/example_rack_app/Gemfile +0 -3
  66. data/example_rack_app/config.ru +0 -6
  67. data/example_rack_app/rack_app.rb +0 -5
  68. data/example_roda_app/Gemfile +0 -6
  69. data/example_roda_app/config.ru +0 -6
  70. data/example_roda_app/roda_app.rb +0 -37
  71. data/example_sinatra_app/Gemfile +0 -6
  72. data/example_sinatra_app/config.ru +0 -6
  73. data/example_sinatra_app/sinatra_app.rb +0 -7
  74. data/lib/up/node/cluster.rb +0 -39
  75. data/lib/up/node/cluster_cli.rb +0 -15
  76. data/lib/up/node/rack_env.rb +0 -106
  77. data/lib/up/node/server.rb +0 -84
  78. data/lib/up/node/server_cli.rb +0 -15
  79. data/lib/up/u_web_socket/rack_env.rb +0 -101
  80. data/opal-up.gemspec +0 -27
  81. data/up_logo.svg +0 -256
@@ -23,26 +23,14 @@ module Up
23
23
  self[key] = case key
24
24
  when 'rack.errors'
25
25
  STDERR
26
- when 'rack.hijack'
27
- nil
28
- when 'rack.hijack?'
29
- false
30
- when 'rack.input'
31
- ::IO.new
32
26
  when 'rack.logger'
33
- ::Logger.new(self['rack.errors'])
27
+ @config[:logger]
34
28
  when 'rack.multipart.buffer_size'
35
29
  4096
36
30
  when 'rack.multipart.tempfile_factory'
37
31
  proc { |_filename, _content_type| File.new }
38
- when 'rack.response_finished'
39
- []
40
32
  when 'rack.session'
41
33
  {}
42
- when 'rack.upgrade'
43
- nil
44
- when 'rack.upgrade?'
45
- nil
46
34
  when 'rack.url_scheme'
47
35
  @config[:scheme]
48
36
  when 'PATH_INFO'
data/lib/up/bun/server.rb CHANGED
@@ -1,36 +1,37 @@
1
1
  # backtick_javascript: true
2
+ require 'logger'
2
3
  require 'up/cli'
3
- require 'up/bun/rack_env'
4
+ require 'up/client'
4
5
 
5
6
  module Up
6
7
  module Bun
7
8
  class Server
8
- def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil)
9
+ def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR))
9
10
  @app = app
10
11
  @scheme = scheme || 'http'
11
12
  raise "unsupported scheme #{@scheme}" unless %w[http https].include?(@scheme)
12
13
  @host = host || 'localhost'
13
14
  @port = port&.to_i || 3000
14
- @config = { handler: self.class.name, engine: "bun/#{`process.version`}", port: port, scheme: scheme, host: host }.freeze
15
+ @config = { handler: self.class.name, engine: "bun/#{`process.version`}", port: port, scheme: scheme, host: host, logger: logger }.freeze
15
16
  @ca_file = ca_file
16
17
  @cert_file = cert_file
17
18
  @key_file = key_file
18
- @server = nil
19
+ @default_input = IO.new
20
+ @server = nil
21
+ @logger = logger
22
+ @t_factory = proc { |filename, _content_type| File.new(filename, 'a+') }
19
23
  end
20
24
 
21
25
  %x{
22
26
  self.handle_headers = function(rack_headers, bun_hdr) {
23
27
  if (rack_headers.$$is_hash) {
24
- var header, k, v;
28
+ var header, v;
25
29
  for(header of rack_headers) {
26
- k = header[0];
27
- if (!k.startsWith('rack.')) {
28
- v = header[1];
29
- if (v.$$is_array) {
30
- v = v.join("\n");
31
- }
32
- bun_hdr.set(k, v);
30
+ v = header[1];
31
+ if (v.$$is_array) {
32
+ v = v.join("\n");
33
33
  }
34
+ bun_hdr.set(header[0].toLowerCase(), v);
34
35
  }
35
36
  }
36
37
  }
@@ -49,20 +50,93 @@ module Up
49
50
  def listen
50
51
  raise "already running" if @server
51
52
  %x{
52
- const oubr = Opal.Up.Bun.RackEnv;
53
53
  const oubs = Opal.Up.Bun.Server;
54
-
54
+ const ouwc = Opal.Up.Client;
55
+ const deco = new TextDecoder();
55
56
  var server_options = {
56
57
  port: #@port,
57
58
  hostname: #@host,
58
59
  development: false,
59
- fetch(req) {
60
- const rack_res = #@app.$call(oubr.$new(req, #@config));
61
- const hdr = new Headers();
62
- oubs.handle_headers(rack_res[1]);
60
+ fetch(req, server) {
61
+ const upgrade = req.headers.get('Upgrade');
62
+ const env = new Map();
63
+ env.set('rack.errors',#{STDERR});
64
+ env.set('rack.input', #@default_input);
65
+ env.set('rack.logger', #@logger);
66
+ env.set('rack.multipart.buffer_size', 4096);
67
+ env.set('rack.multipart.tempfile_factory', #@t_factory);
68
+ if (upgrade) {
69
+ env.set('rack.upgrade?', #{:websocket});
70
+ }
71
+ env.set('rack.url_scheme', #@scheme);
72
+ env.set('SCRIPT_NAME', "");
73
+ env.set('SERVER_PROTOCOL', req.httpVersion);
74
+ env.set('HTTP_VERSION', req.httpVersion);
75
+ env.set('SERVER_NAME', #@host);
76
+ env.set('SERVER_PORT', #@port);
77
+ env.set('QUERY_STRING', "");
78
+ env.set('REQUEST_METHOD', req.method);
79
+ env.set('PATH_INFO', req.url);
80
+ req.headers.forEach((k, v) => { env.set('HTTP_' + k.toUpperCase().replaceAll('-', '_'), v) });
81
+ const rack_res = #@app.$call(env);
82
+ if (upgrade) {
83
+ const handler = env.get('rack.upgrade');
84
+ if (rack_res[0] < 300 && handler && handler !== nil) {
85
+ const client = ouwc.$new();
86
+ client.env = env;
87
+ client.open = false;
88
+ client.handler = handler
89
+ client.protocol = #{:websocket};
90
+ client.server = server;
91
+ client.timeout = 120;
92
+ server.upgrade(req, { data: { client: client }});
93
+ return;
94
+ }
95
+ }
96
+ const hdrs = new Headers();
97
+ oubs.handle_headers(rack_res[1], hdrs);
63
98
  var body = '';
64
99
  body = oubs.handle_response(rack_res[2], body);
65
- return new Response(body, {status: rack_res[0], statusText: 'OK', headers: hdr});
100
+ return new Response(body, {status: rack_res[0], statusText: 'OK', headers: hdrs});
101
+ },
102
+ websocket: {
103
+ close: (ws) => {
104
+ const client = ws.data.client;
105
+ if (typeof(client.handler.$on_close) === 'function') {
106
+ client.ws = ws;
107
+ client.open = false;
108
+ client.handler.$on_close(client);
109
+ client.ws = null;
110
+ }
111
+ },
112
+ drain: (ws) => {
113
+ const client = ws.data.client;
114
+ if (typeof(client.handler.$on_drained) === 'function') {
115
+ client.ws = ws;
116
+ client.handler.$on_drained(client);
117
+ client.ws = null;
118
+ }
119
+ },
120
+ message: (ws, message) => {
121
+ const client = ws.data.client;
122
+ if (typeof(client.handler.$on_message) === 'function') {
123
+ if (typeof(message) !== 'string') {
124
+ message = deco.decode(message);
125
+ }
126
+ client.ws = ws;
127
+ client.handler.$on_message(client, message);
128
+ client.ws = null;
129
+ }
130
+ },
131
+ open: (ws) => {
132
+ const client = ws.data.client;
133
+ if (typeof(client.handler.$on_open) === 'function') {
134
+ client.ws = ws;
135
+ client.open = true;
136
+ client.handler.$on_open(client);
137
+ client.ws = null;
138
+ }
139
+ }
66
140
  }
67
141
  };
68
142
  if (#@scheme === 'https') {
data/lib/up/cli.rb CHANGED
@@ -32,6 +32,9 @@ module Up
32
32
  on('-k', '--key-file FILE', String, 'File with the servers certificate') do |key_file|
33
33
  options[:key_file] = key_file
34
34
  end
35
+ on('-l', '--log-file FILE', String, 'log file') do |log_file|
36
+ options[:logger] = Logger.new(File.new(log_file, 'a+'))
37
+ end
35
38
  on('-v', '--version', 'Show version') do
36
39
  puts "Up! v#{Up::VERSION}"
37
40
  exit
data/lib/up/client.rb ADDED
@@ -0,0 +1,68 @@
1
+ # backtick_javascript: true
2
+ if RUBY_ENGINE == 'opal'
3
+ %x{
4
+ const process = require('node:process');
5
+ }
6
+ end
7
+
8
+ module Up
9
+ class Client
10
+ # instance vars are set by the server
11
+
12
+ attr_reader :env, :handler, :protocol, :timeout
13
+
14
+ def handler=(h)
15
+ @handler.on_close(self)
16
+ @handler = h
17
+ @handler.on_open(self)
18
+ end
19
+
20
+ def open?
21
+ @open
22
+ end
23
+
24
+ def pubsub?
25
+ true
26
+ end
27
+
28
+ if RUBY_ENGINE == 'opal'
29
+ def close
30
+ @open = false
31
+ `#@ws?.close()`
32
+ end
33
+
34
+ def pending
35
+ return -1 unless @open
36
+ `#@ws?.getBufferedAmount()`
37
+ end
38
+
39
+ def publish(channel, message, engine = nil)
40
+ res = false
41
+ raise 'publish engine not supported' if engine
42
+ %x{
43
+ if (!message.$$is_string) {
44
+ message = JSON.stringify(message);
45
+ }
46
+ res = #@server?.publish(channel, message);
47
+ if (engine !== false && self.worker) {
48
+ process.send({c: channel, m: message});
49
+ }
50
+ }
51
+ res
52
+ end
53
+
54
+ def subscribe(channel, is_pattern = false, &block)
55
+ @sub_block = block
56
+ `#@ws?.subscribe(channel)`
57
+ end
58
+
59
+ def unsubscribe(channel, is_pattern = false)
60
+ `#@ws?.unsubscribe(channel)`
61
+ end
62
+
63
+ def write(data)
64
+ `#@ws?.send(data, false)`
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ # backtick_javascript: true
2
+ require 'etc'
3
+ require 'random/formatter'
4
+ require 'up_ext'
5
+
6
+ module Up
7
+ module Ruby
8
+ class Cluster < Up::Ruby::Server
9
+ def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR), workers: nil)
10
+ super(app: app, host: host, port: port)
11
+ @secret = Random.uuid
12
+ @workers = workers || Etc.nprocessors
13
+ @members = []
14
+ end
15
+
16
+ def listen
17
+ raise "already running" unless @members.empty?
18
+ @workers.times do
19
+ @members << fork do
20
+ @member_id = @members.size + 1
21
+ super
22
+ end
23
+ end
24
+
25
+ Process.waitall
26
+ @members.each do |member|
27
+ Process.kill("KILL", member)
28
+ end
29
+ end
30
+
31
+ def stop
32
+ if Up::CLI::stoppable?
33
+ @members.each { |m| Process.kill(m) }
34
+ @members.clear
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ require 'rack/builder'
2
+ require 'up/ruby/rack_cluster'
3
+
4
+ module Up
5
+ module CLI
6
+ def self.call
7
+ Up::Ruby::RackCluster.run(get_app, get_options)
8
+ end
9
+ end
10
+ end
@@ -1,11 +1,12 @@
1
- require 'up/node/cluster'
1
+ require 'up_ext'
2
+ require 'up/ruby/cluster'
2
3
 
3
4
  module Up
4
- module Node
5
+ module Ruby
5
6
  module RackCluster
6
7
  def self.run(app, options = {})
7
8
  raise "already running" if @server
8
- @server = Up::Node::Cluster.new(app: app, **options).listen
9
+ @server = Up::Ruby::Cluster.new(app: app, **options).listen
9
10
  true
10
11
  end
11
12
 
@@ -20,6 +21,6 @@ end
20
21
  ENV['RACK_HANDLER'] ||= 'up'
21
22
 
22
23
  begin
23
- ::Rackup::Handler.register('up', Up::Node::RackCluster) if defined?(::Rackup::Handler)
24
+ ::Rackup::Handler.register('up', Up::Ruby::RackCluster) if defined?(::Rackup::Handler)
24
25
  rescue StandardError
25
26
  end
@@ -1,11 +1,11 @@
1
- require 'up/node/server'
1
+ require 'up_ext'
2
2
 
3
3
  module Up
4
- module Node
4
+ module Ruby
5
5
  module RackServer
6
6
  def self.run(app, options = {})
7
7
  raise "already running" if @server
8
- @server = Up::Node::Server.new(app: app, **options).listen
8
+ @server = Up::Ruby::Server.new(app: app, **options).listen
9
9
  true
10
10
  end
11
11
 
@@ -20,6 +20,6 @@ end
20
20
  ENV['RACK_HANDLER'] ||= 'up'
21
21
 
22
22
  begin
23
- ::Rackup::Handler.register('up', Up::Node::RackServer) if defined?(::Rackup::Handler)
23
+ ::Rackup::Handler.register('up', Up::Ruby::RackServer) if defined?(::Rackup::Handler)
24
24
  rescue StandardError
25
25
  end
@@ -0,0 +1,10 @@
1
+ require 'rack/builder'
2
+ require 'up/ruby/rack_server'
3
+
4
+ module Up
5
+ module CLI
6
+ def self.call
7
+ Up::Ruby::RackServer.run(get_app, get_options)
8
+ end
9
+ end
10
+ end
@@ -2,6 +2,7 @@
2
2
  require 'up/u_web_socket/server'
3
3
 
4
4
  %x{
5
+ const process = require('node:process');
5
6
  const cluster = require('node:cluster');
6
7
  const num_workers = require('node:os').availableParallelism();
7
8
  }
@@ -9,8 +10,8 @@ require 'up/u_web_socket/server'
9
10
  module Up
10
11
  module UWebSocket
11
12
  class Cluster < Up::UWebSocket::Server
12
- def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, workers: nil)
13
- super(app: app, host: host, port: port, scheme: scheme, ca_file: ca_file, cert_file: cert_file, key_file: key_file)
13
+ def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR), workers: nil)
14
+ super(app: app, host: host, port: port, scheme: scheme, ca_file: ca_file, cert_file: cert_file, key_file: key_file, logger: logger)
14
15
  @workers = workers || `num_workers`
15
16
  @members = []
16
17
  end
@@ -19,10 +20,24 @@ module Up
19
20
  raise "already running" unless @members.empty?
20
21
  %x{
21
22
  if (cluster.isPrimary) {
23
+ cluster.on('message', (worker, message, handle) => {
24
+ if (message.c && message.m) {
25
+ for (let member of #@members) {
26
+ if (member !== worker) {
27
+ member.send(message);
28
+ }
29
+ }
30
+ }
31
+ });
22
32
  for (let i = 0; i < #@workers; i++) {
23
- #@members.push(cluster.fork());
33
+ #@members[i] = cluster.fork();
24
34
  }
25
35
  } else {
36
+ self.worker = true;
37
+ function process_message_handler(message, handle) {
38
+ self.server.publish(message.c, message.m);
39
+ }
40
+ process.on('message', process_message_handler);
26
41
  #{super}
27
42
  }
28
43
  }
@@ -1,8 +1,10 @@
1
1
  # backtick_javascript: true
2
+ require 'logger'
2
3
  require 'up/cli'
3
- require 'up/u_web_socket/rack_env'
4
+ require 'up/client'
4
5
 
5
6
  %x{
7
+ const process = require('node:process');
6
8
  module.paths.push(process.cwd() + '/node_modules');
7
9
  const uws = require('uWebSockets.js');
8
10
  }
@@ -10,32 +12,32 @@ require 'up/u_web_socket/rack_env'
10
12
  module Up
11
13
  module UWebSocket
12
14
  class Server
13
- def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil)
15
+ def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR))
14
16
  @app = app
15
17
  @scheme = scheme || 'http'
16
18
  raise "unsupported scheme #{@scheme}" unless %w[http https].include?(@scheme)
17
19
  @host = host || 'localhost'
18
20
  @port = port&.to_i || 3000
19
- @config = { handler: self.class.name, engine: "node/#{`process.version`}", port: port, scheme: scheme, host: host }.freeze
21
+ @config = { handler: self.class.name, engine: "node/#{`process.version`}" }.freeze
20
22
  @ca_file = ca_file
21
23
  @cert_file = cert_file
22
24
  @key_file = key_file
23
- @server = nil
25
+ @default_input = IO.new
26
+ @server = nil
27
+ @logger = logger
28
+ @t_factory = proc { |filename, _content_type| File.new(filename, 'a+') }
24
29
  end
25
30
 
26
31
  %x{
27
32
  self.handle_headers = function(rack_headers, uws_res) {
28
33
  if (rack_headers.$$is_hash) {
29
- var header, k, v;
34
+ var header, v;
30
35
  for(header of rack_headers) {
31
- k = header[0];
32
- if (!k.startsWith('rack.')) {
33
- v = header[1];
34
- if (v.$$is_array) {
35
- v = v.join("\n");
36
- }
37
- uws_res.writeHeader(k, v);
36
+ v = header[1];
37
+ if (v.$$is_array) {
38
+ v = v.join("\n");
38
39
  }
40
+ uws_res.writeHeader(header[0].toLowerCase(), v);
39
41
  }
40
42
  }
41
43
  }
@@ -48,25 +50,116 @@ module Up
48
50
  }
49
51
  #{`parts`.close if `parts`.respond_to?(:close)}
50
52
  }
53
+
54
+ self.prepare_env = function(req) {
55
+ const env = new Map();
56
+ env.set('rack.errors',#{STDERR});
57
+ env.set('rack.input', #@default_input);
58
+ env.set('rack.logger', #@logger);
59
+ env.set('rack.multipart.buffer_size', 4096);
60
+ env.set('rack.multipart.tempfile_factory', #@t_factory);
61
+ env.set('rack.url_scheme', #@scheme);
62
+ env.set('SCRIPT_NAME', "");
63
+ env.set('SERVER_PROTOCOL', 'HTTP/1.1');
64
+ env.set('HTTP_VERSION', 'HTTP/1.1');
65
+ env.set('SERVER_NAME', #@host);
66
+ env.set('SERVER_PORT', #@port);
67
+ env.set('QUERY_STRING', req.getQuery());
68
+ env.set('REQUEST_METHOD', req.getMethod().toUpperCase());
69
+ env.set('PATH_INFO', req.getUrl());
70
+ req.forEach((k, v) => { env.set('HTTP_' + k.toUpperCase().replaceAll('-', '_'), v) });
71
+ return env;
72
+ }
51
73
  }
52
74
 
53
75
  def listen
54
76
  raise "already running" if @server
55
77
  %x{
56
- const ouwr = Opal.Up.UWebSocket.RackEnv;
57
78
  const ouws = Opal.Up.UWebSocket.Server;
79
+ const ouwc = Opal.Up.Client;
80
+ const deco = new TextDecoder();
58
81
  if (#@scheme == 'https') {
59
82
  #@server = uws.SSLApp({ ca_file_name: #@ca_file, cert_file_name: #@cert_file, key_file_name: #@key_file });
60
83
  } else {
61
84
  #@server = uws.App();
62
85
  }
63
86
  #@server.any('/*', (res, req) => {
64
- const rack_res = #@app.$call(ouwr.$new(req, #@config));
65
- res.writeStatus(`${rack_res[0].toString()} OK`);
87
+ const rack_res = #@app.$call(ouws.prepare_env(req));
88
+ res.writeStatus(rack_res[0].toString() + ' OK');
66
89
  ouws.handle_headers(rack_res[1], res);
67
90
  ouws.handle_response(rack_res[2], res);
68
91
  res.end();
69
92
  });
93
+ #@server.ws('/*', {
94
+ close: (ws, code, message) => {
95
+ const user_data = ws.getUserData();
96
+ if (typeof(user_data.client.handler.$on_close) === 'function') {
97
+ user_data.client.ws = ws;
98
+ user_data.client.open = false;
99
+ user_data.client.handler.$on_close(user_data.client);
100
+ user_data.client.ws = null;
101
+ }
102
+ },
103
+ drain: (ws) => {
104
+ const user_data = ws.getUserData();
105
+ if (typeof(user_data.client.handler.$on_drained) === 'function') {
106
+ user_data.client.ws = ws;
107
+ user_data.client.handler.$on_drained(user_data.client);
108
+ user_data.client.ws = null;
109
+ }
110
+ },
111
+ message: (ws, message, isBinary) => {
112
+ const user_data = ws.getUserData();
113
+ if (typeof(user_data.client.handler.$on_message) === 'function') {
114
+ const msg = deco.decode(message);
115
+ user_data.client.ws = ws;
116
+ user_data.client.handler.$on_message(user_data.client, msg);
117
+ user_data.client.ws = null;
118
+ }
119
+ },
120
+ open: (ws) => {
121
+ const user_data = ws.getUserData();
122
+ if (typeof(user_data.client.handler.$on_open) === 'function') {
123
+ user_data.client.ws = ws;
124
+ user_data.client.open = true;
125
+ user_data.client.handler.$on_open(user_data.client);
126
+ user_data.client.ws = null;
127
+ }
128
+ },
129
+ sendPingsAutomatically: true,
130
+ upgrade: (res, req, context) => {
131
+ const env = ouws.prepare_env(req);
132
+ env.set('rack.upgrade?', #{:websocket});
133
+ const rack_res = #@app.$call(env);
134
+ const handler = env.get('rack.upgrade');
135
+ if (rack_res[0] < 300 && handler && handler !== nil) {
136
+ const client = ouwc.$new();
137
+ client.env = env;
138
+ client.open = false;
139
+ client.handler = handler
140
+ client.protocol = #{:websocket};
141
+ client.server = self.server;
142
+ client.timeout = 120;
143
+ if (self.worker) {
144
+ client.worker = true;
145
+ }
146
+ res.upgrade({ client: client },
147
+ req.getHeader('sec-websocket-key'),
148
+ req.getHeader('sec-websocket-protocol'),
149
+ req.getHeader('sec-websocket-extensions'),
150
+ context);
151
+ } else {
152
+ if (rack_res[0] >= 300) {
153
+ env.delete('rack.upgrade');
154
+ }
155
+ res.writeStatus(rack_res[0].toString() + ' OK');
156
+ ouws.handle_headers(rack_res[1], res);
157
+ ouws.handle_response(rack_res[2], res);
158
+ res.end();
159
+ }
160
+ },
161
+
162
+ });
70
163
  #@server.listen(#@port, #@host, () => { console.log(`Server is running on ${#@scheme}://${#@host}:${#@port}`)});
71
164
  }
72
165
  end
data/lib/up/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Up
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.4'.freeze
3
3
  end