opal-up 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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