opal-up 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fd1f3da03559ae97160438ac56cab04162d985d069f73fdbb228e18a83f21757
4
+ data.tar.gz: 880e5c28a44a8aba0d160c07994d4ca69b5b15051e0fd9948e7aa5b0696a9b82
5
+ SHA512:
6
+ metadata.gz: '0491776446d5623ebe8ccacde009d9e448778bff5c5803ebfa4f30ea70b0178454fe5d9b39ba8f9e8d0e54be20a607a81e854f758c64aea5dc9cc4d7ae495821'
7
+ data.tar.gz: 25659ca070cc81c078599f2281f2f52c4862f10ebadf284257d9c420380319d98708b77233cd6fb684b064d931c58e50bc893aaedf763f2c5c42d35b81392f51
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ Gemfile.lock
3
+ package-lock.json
4
+ package.json
5
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jan Biedermann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ <img src="https://raw.githubusercontent.com/janbiedermann/up/master/up_logo.svg" alt="UP Logo">
2
+ <small>Original Image by <a href="https://www.freepik.com/free-vector/colorful-arrows_715199.htm#query=up&position=3&from_view=search&track=sph&uuid=63f9eddf-02a6-4e5c-8178-8cfa507ee33d">Freepik</a>, modified though</small>
3
+
4
+ # UP
5
+
6
+ A high performance Rack server for Opal Ruby, Tech Demo
7
+
8
+ ## Let Numbers speak first
9
+
10
+ ```
11
+ Requests per second:
12
+ Puma: 6391.01 req/s
13
+ Iodine: 18645.58 req/s
14
+ Up!: 20258.46 req/s <<< fastest
15
+
16
+ Time per Request, mean, across all concurrent requests:
17
+ Puma: 0.156ms
18
+ Iodine: 0.054ms
19
+ Up!: 0.049ms <<< fastest
20
+ ```
21
+ running on linux with:
22
+ ruby 3.3.0, YJit enabled
23
+ Opal 1.8.2 with node v2011.0
24
+ Puma 6.4.2, 4 workers, 4 threads
25
+ Iodine 0.7.57, 4 workers, 4 threads
26
+ Up! 0.0.1, 1 worker, no threads
27
+
28
+ running the example_rack_app from this repo, benchmarked with:
29
+ `ab -n 100000 -c 10 http://localhost:3000/`
30
+
31
+ ## Introduction
32
+
33
+ This is currently mainly a technical demonstration, demonstrating the speed of the Opal Ruby implementation employing Node and UWebSocketJs as runtime. Its not yet a generic, all purpose Reck server, but good for further experimentation, research and open for improvement.
34
+
35
+ ## Getting started
36
+
37
+ To start experimenting:
38
+ - clone this repo
39
+ - cd into it, bundle install
40
+ - cd example_rack_app
41
+ - bundle install
42
+ - bundle exec up
43
+
44
+ You may want to change the `gem 'up'` line in the Gemfile to use up from rubygems, if you want to run your app outside of the cloned repo.
45
+
46
+ ## Roda, Sinatra, others ...
47
+
48
+ ... currently do not work! Just basic Rack apps with a few dependencies.
49
+
50
+ Example apps for Roda and Sinatra are provided, for convenience of developing and expanding the capabilities of Opal.
51
+
data/bin/up ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if RUBY_ENGINE == 'opal'
4
+ require 'up-node'
5
+ Up::CLI.call
6
+ else
7
+ # check for commands
8
+ node_cmd = `which node`
9
+ npm_cmd = `which npm`
10
+ raise "Please install node first!" if !node_cmd || node_cmd.empty?
11
+ raise "Please install npm first!" if !npm_cmd || npm_cmd.empty?
12
+ node_cmd.chop! if node_cmd.end_with?("\n")
13
+ npm_cmd.chop! if npm_cmd.end_with?("\n")
14
+ got_uws = `npm list|grep uWebSockets.js@20`
15
+ `npm i uNetworking/uWebSockets.js#v20.41.0` if got_uws.empty?
16
+ lib_dir = File.expand_path("#{__dir__}/../lib")
17
+
18
+ # Opal does not yet support gems, so lets read the Gemfile and simply add each gem
19
+ # to the Opal load path and require it, works for some gems, fails for others
20
+ gems = ""
21
+ if File.exist?("Gemfile")
22
+ lines = File.readlines('Gemfile')
23
+ lines.each do |line|
24
+ m = /gem ['"](\w+)['"]/.match(line)
25
+ gems << " -g #{m[1]} -r #{m[1]}" if m && m[1] != 'up'
26
+ end
27
+ end
28
+ Kernel.exec("opal -Rnodejs -E -I. -I#{lib_dir} -g rack #{gems} #{__FILE__}")
29
+ end
data/bin/up_bun ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if RUBY_ENGINE == 'opal'
4
+ require 'up-bun'
5
+ Up::CLI.call
6
+ else
7
+ # check for commands
8
+ bun_cmd = `which bun`
9
+ raise "Please install bun first!" if !bun_cmd || bun_cmd.empty?
10
+ bun_cmd.chop! if bun_cmd.end_with?("\n")
11
+ lib_dir = File.expand_path("#{__dir__}/../lib")
12
+ # Opal does not yet support gems, so lets read the Gemfile and simply add each gem
13
+ # to the Opal load path and require it, works for some gems, fails for others
14
+ gems = ""
15
+ if File.exist?("Gemfile")
16
+ lines = File.readlines('Gemfile')
17
+ lines.each do |line|
18
+ m = /gem ['"](\w+)['"]/.match(line)
19
+ gems << " -g #{m[1]} -r #{m[1]}" if m && m[1] != 'up'
20
+ end
21
+ end
22
+ Kernel.exec("opal -Rbun -E -I. -I#{lib_dir} -g rack #{gems} #{__FILE__}")
23
+ end
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'opal-up', path: '../'
@@ -0,0 +1,6 @@
1
+ require_relative 'rack_app'
2
+ if defined? RubyVM
3
+ # ensure up contenders use a JIT
4
+ RubyVM::YJIT.enable
5
+ end
6
+ run RackApp
@@ -0,0 +1,5 @@
1
+ class RackApp
2
+ def self.call(env)
3
+ [200, {}, [env.to_s]]
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ gem 'opal', github: 'opal/opal'
5
+ gem 'opal-up', path: '../'
6
+ gem 'roda'
@@ -0,0 +1,6 @@
1
+ require_relative 'roda_app'
2
+ if defined? RubyVM
3
+ # ensure up contenders use a JIT
4
+ RubyVM::YJIT.enable
5
+ end
6
+ run RodaApp.freeze
@@ -0,0 +1,35 @@
1
+ require "roda"
2
+
3
+ class RodaApp < Roda
4
+ route do |r|
5
+ # GET / request
6
+ r.root do
7
+ r.redirect "/hello"
8
+ end
9
+
10
+ # /hello branch
11
+ r.on "hello" do
12
+ # Set variable for all routes in /hello branch
13
+ @greeting = 'Hello'
14
+
15
+ # GET /hello/world request
16
+ r.get "world" do
17
+ "#{@greeting} world!"
18
+ end
19
+
20
+ # /hello request
21
+ r.is do
22
+ # GET /hello request
23
+ r.get do
24
+ "#{@greeting}!"
25
+ end
26
+
27
+ # POST /hello request
28
+ r.post do
29
+ puts "Someone said #{@greeting}!"
30
+ r.redirect
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ gem 'opal', github: 'opal/opal'
5
+ gem 'opal-up', path: '../'
6
+ gem 'sinatra', '>= 4.0.0'
@@ -0,0 +1,6 @@
1
+ require_relative 'sinatra_app'
2
+ if defined? RubyVM
3
+ # ensure up contenders use a JIT
4
+ RubyVM::YJIT.enable
5
+ end
6
+ run SinatraApp
@@ -0,0 +1,7 @@
1
+ require 'sinatra/base'
2
+
3
+ class SinatraApp
4
+ get '/' do
5
+ 'Hello world!'
6
+ end
7
+ end
data/lib/up/bun.rb ADDED
@@ -0,0 +1,91 @@
1
+ # backtick_javascript: true
2
+
3
+ require 'up/bun_rack_env'
4
+
5
+ module Up
6
+ module Bun
7
+ def self.listen(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil)
8
+ port = port&.to_i
9
+ scheme ||= 'http'
10
+ host ||= 'localhost'
11
+ port ||= 3000
12
+ config = { handler: self.name, engine: "bun/#{`process.version`}", port: port, scheme: scheme, host: host }
13
+ %x{
14
+ if (scheme !== 'http' && scheme !== 'https') {
15
+ #{raise "unsupported scheme #{scheme}"}
16
+ }
17
+
18
+ var server_options = {
19
+ port: port,
20
+ hostname: host,
21
+ development: false,
22
+ fetch(req) {
23
+ const rack_res = app.$call(Opal.Up.BunRackEnv.$new(req, config));
24
+ const hdr = new Headers();
25
+ const headers = rack_res[1];
26
+ if (headers.$$is_hash) {
27
+ var header, k, v;
28
+ for(header of headers) {
29
+ k = header[0];
30
+ v = header[1];
31
+ if (!k.startsWith('rack.')) {
32
+ if (v.$$is_array) {
33
+ v = v.join("\n");
34
+ }
35
+ hdr.set(k, v);
36
+ }
37
+ }
38
+ }
39
+ var body = '';
40
+
41
+ #{
42
+ parts = `rack_res[2]`
43
+ if parts.respond_to?(:each)
44
+ parts.each do |part|
45
+ # this is not technically correct, just to make htings work
46
+ `body = body + part`
47
+ end
48
+ elsif parts.respond_to?(:call)
49
+ `body = parts.$call()`
50
+ end
51
+ parts.close if parts.respond_to?(:close)
52
+ }
53
+
54
+ return new Response(body, {status: rack_res[0], statusText: 'OK', headers: hdr});
55
+ }
56
+ };
57
+ if (scheme === 'https') {
58
+ server_options.tls = {
59
+ key: Bun.file(key_file),
60
+ cert: Bun.file(cert_file),
61
+ ca: Bun.file(ca_file)
62
+ };
63
+ }
64
+
65
+ Bun.serve(server_options);
66
+ console.log(`Server is running on http://${host}:${port}`);
67
+ }
68
+ end
69
+
70
+ def self.stop
71
+ sleep 0.1
72
+ puts 'deflating request chain links'
73
+ sleep 0.1
74
+ puts 'optimizing response distortion'
75
+ sleep 0.1
76
+ print 'releasing boost pressure: '
77
+ 3.times do
78
+ sleep 0.2
79
+ print '.'
80
+ end
81
+ 3.times do
82
+ puts "\nRED ALERT: boost pressure to high, cannot open release valve!1!!!"
83
+ sleep 0.1
84
+ print '.'
85
+ sleep 0.1
86
+ end
87
+ puts 'stopping engines failed, for further help see:'
88
+ puts 'https://www.youtube.com/watch?v=ecBco63zvas'
89
+ end
90
+ end
91
+ end
data/lib/up/bun_cli.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'opal/platform'
2
+ require 'bun/file'
3
+ require 'nodejs/require'
4
+ require 'opal-parser'
5
+ require 'rack/builder'
6
+ require 'up/rack_builder_patch'
7
+
8
+ module Up
9
+ module CLI
10
+ def self.try_file(filename)
11
+ return nil unless File.exist? filename
12
+ ::Rack::Builder.parse_file filename
13
+ end
14
+
15
+ def self.get_app(filename = 'config.ru')
16
+ app = nil
17
+ filename ||= 'config.ru'
18
+ app = try_file filename
19
+ if File.exist?("#{filename}.ru")
20
+ filename = "#{filename}.ru"
21
+ app ||= try_file filename
22
+ end
23
+ raise "Something wrong with #{filename}\n" unless app
24
+ app
25
+ end
26
+
27
+ def self.call
28
+ app = get_app
29
+ Up::BunRack.run(app)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Up
2
+ module BunRack
3
+ def self.run(app, options = {})
4
+ Up::Bun.listen(app: app, port: options[:port], host: options[:host])
5
+ true
6
+ end
7
+
8
+ def self.shutdown
9
+ Up::Bun.stop
10
+ end
11
+ end
12
+ end
13
+
14
+ ENV['RACK_HANDLER'] ||= 'up'
15
+
16
+ begin
17
+ ::Rackup::Handler.register('up', Up::BunRack) if defined?(::Rackup::Handler)
18
+ rescue StandardError
19
+ end
@@ -0,0 +1,102 @@
1
+ # backtick_javascript: true
2
+
3
+ require 'logger'
4
+ require 'up/version'
5
+
6
+ module Up
7
+ class BunRackEnv < ::Hash
8
+ RACK_VARS = %w[rack.errors rack.hijack rack.hijack? rack.input rack.logger
9
+ rack.multipart.buffer_size rack.multipart.tempfile_factory
10
+ rack.response_finished
11
+ rack.session rack.upgrade rack.upgrade? rack.url_scheme
12
+ HTTP_ACCEPT HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE
13
+ HTTP_CONNECTION HTTP_HOST HTTP_USER_AGENT PATH_INFO QUERY_STRING REQUEST_METHOD
14
+ SCRIPT_NAME SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE]
15
+ def initialize(req, config)
16
+ @req = req
17
+ @config = config
18
+ end
19
+
20
+ def [](key)
21
+ return super(key) if key?(key)
22
+ self[key] = case key
23
+ when 'rack.errors'
24
+ STDERR
25
+ when 'rack.hijack'
26
+ nil
27
+ when 'rack.hijack?'
28
+ false
29
+ when 'rack.input'
30
+ ::IO.new
31
+ when 'rack.logger'
32
+ ::Logger.new(self['rack.errors'])
33
+ when 'rack.multipart.buffer_size'
34
+ 4096
35
+ when 'rack.multipart.tempfile_factory'
36
+ proc { |_filename, _content_type| File.new }
37
+ when 'rack.response_finished'
38
+ []
39
+ when 'rack.session'
40
+ {}
41
+ when 'rack.upgrade'
42
+ nil
43
+ when 'rack.upgrade?'
44
+ nil
45
+ when 'rack.url_scheme'
46
+ @config[:scheme]
47
+ when 'PATH_INFO'
48
+ `#@req.url`
49
+ when 'QUERY_STRING'
50
+ ""
51
+ when 'RACK_ERRORS'
52
+ self['rack.errors']
53
+ when 'RACK_LOGGER'
54
+ self['rack.logger']
55
+ when 'REQUEST_METHOD'
56
+ `#@req.method`
57
+ when 'SCRIPT_NAME'
58
+ ""
59
+ when 'SERVER_NAME'
60
+ @config[:host]
61
+ when 'SERVER_PORT'
62
+ @config[:port].to_s
63
+ when 'SERVER_PROTOCOL'
64
+ ""
65
+ when 'SERVER_SOFTWARE'
66
+ "#{@config[:handler]}/#{Up::VERSION} #{@config[:engine]}"
67
+ else
68
+ if key.start_with?('HTTP_')
69
+ key = key[5..].gsub(/_/, '-')
70
+ `#@req.headers.get(key.toLowerCase())`
71
+ else
72
+ nil
73
+ end
74
+ end
75
+ end
76
+
77
+ def req_headers
78
+ h = {}
79
+ %x{
80
+ var hdr, hds = #@req.headers;
81
+ for (hdr in hds) { h.set(hdr[0], hdr[1]); }
82
+ }
83
+ h
84
+ end
85
+
86
+ def each
87
+ unless @got_them_all
88
+ RACK_VARS.each { |k| self[k] unless self.key?(k) }
89
+ @got_them_all = true
90
+ end
91
+ super
92
+ end
93
+
94
+ def to_s
95
+ unless @got_them_all
96
+ RACK_VARS.each { |k| self[k] unless self.key?(k) }
97
+ @got_them_all = true
98
+ end
99
+ super
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,17 @@
1
+ module Rack
2
+ class Builder
3
+ def self.load_file(path, **options)
4
+ config = ::File.read(path)
5
+
6
+ # config = config.slice(/\A#{UTF_8_BOM}/) if config.encoding == Encoding::UTF_8
7
+
8
+ if config[/^#\\(.*)/]
9
+ fail "Parsing options from the first comment line is no longer supported: #{path}"
10
+ end
11
+
12
+ config = config.sub(/^__END__\n.*\Z/m, '')
13
+
14
+ return new_from_string(config, path, **options)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,83 @@
1
+ # backtick_javascript: true
2
+
3
+ %x{
4
+ module.paths.push(process.cwd() + '/node_modules');
5
+ const uws = require('uWebSockets.js');
6
+ const cluster = require('node:cluster');
7
+ }
8
+
9
+ require 'up/uws_rack_env'
10
+
11
+ module Up
12
+ module UWebSocket
13
+ def self.listen(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil)
14
+ port = port&.to_i
15
+ scheme ||= 'http'
16
+ host ||= 'localhost'
17
+ port ||= 3000
18
+ config = { handler: self.name, engine: "node/#{`process.version`}", port: port, scheme: scheme, host: host }
19
+ %x{
20
+ let server;
21
+ if (scheme == 'http') {
22
+ server = uws.App();
23
+ } else if (scheme == 'https') {
24
+ server = uws.SSLApp({ ca_file_name: ca_file, cert_file_name: cert_file, key_file_name: key_file });
25
+ } else {
26
+ #{raise "unsupported scheme #{scheme}"}
27
+ }
28
+ server.get('/*', (res, req) => {
29
+ const rack_res = app.$call(Opal.Up.UwsRackEnv.$new(req, config));
30
+ res.writeStatus(`${rack_res[0].toString()} OK`);
31
+ const headers = rack_res[1];
32
+ if (headers.$$is_hash) {
33
+ var header, k, v;
34
+ for(header of headers) {
35
+ k = header[0];
36
+ v = header[1];
37
+ if (!k.startsWith('rack.')) {
38
+ if (v.$$is_array) {
39
+ v = v.join("\n");
40
+ }
41
+ res.writeHeader(k, v);
42
+ }
43
+ }
44
+ }
45
+ #{
46
+ parts = `rack_res[2]`
47
+ if parts.respond_to?(:each)
48
+ parts.each do |part|
49
+ `res.write(part)`
50
+ end
51
+ elsif parts.respond_to?(:call)
52
+ `res.write(parts.$call())`
53
+ end
54
+ parts.close if parts.respond_to?(:close)
55
+ }
56
+ res.end();
57
+ });
58
+ server.listen(port, host, () => { console.log(`Server is running on http://${host}:${port}`)});
59
+ }
60
+ end
61
+
62
+ def self.stop
63
+ sleep 0.1
64
+ puts 'deflating request chain links'
65
+ sleep 0.1
66
+ puts 'optimizing response distortion'
67
+ sleep 0.1
68
+ print 'releasing boost pressure: '
69
+ 3.times do
70
+ sleep 0.2
71
+ print '.'
72
+ end
73
+ 3.times do
74
+ puts "\nRED ALERT: boost pressure to high, cannot open release valve!1!!!"
75
+ sleep 0.1
76
+ print '.'
77
+ sleep 0.1
78
+ end
79
+ puts 'stopping engines failed, for further help see:'
80
+ puts 'https://www.youtube.com/watch?v=ecBco63zvas'
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,89 @@
1
+ # backtick_javascript: true
2
+
3
+ %x{
4
+ module.paths.push(process.cwd() + '/node_modules');
5
+ const uws = require('uWebSockets.js');
6
+ const cluster = require('node:cluster');
7
+ }
8
+
9
+ require 'up/uws_rack_env'
10
+
11
+ module Up
12
+ module UWebSocket
13
+ def self.listen(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, workers: 4)
14
+ port = port&.to_i
15
+ scheme ||= 'http'
16
+ host ||= 'localhost'
17
+ port ||= 3000
18
+ config = { handler: self.name, engine: "node/#{`process.version`}", port: port, scheme: scheme, host: host }
19
+ %x{
20
+ if (cluster.isPrimary) {
21
+ for (let i = 0; i < workers; i++) {
22
+ cluster.fork();
23
+ }
24
+ } else {
25
+ let server;
26
+ if (scheme == 'http') {
27
+ server = uws.App();
28
+ } else if (scheme == 'https') {
29
+ server = uws.SSLApp({ ca_file_name: ca_file, cert_file_name: cert_file, key_file_name: key_file });
30
+ } else {
31
+ #{raise "unsupported scheme #{scheme}"}
32
+ }
33
+ server.get('/*', (res, req) => {
34
+ const rack_res = app.$call(Opal.Up.UwsRackEnv.$new(req, config));
35
+ res.writeStatus(`${rack_res[0].toString()} OK`);
36
+ const headers = rack_res[1];
37
+ if (headers.$$is_hash) {
38
+ var header, k, v;
39
+ for(header of headers) {
40
+ k = header[0];
41
+ v = header[1];
42
+ if (!k.startsWith('rack.')) {
43
+ if (v.$$is_array) {
44
+ v = v.join("\n");
45
+ }
46
+ res.writeHeader(k, v);
47
+ }
48
+ }
49
+ }
50
+ #{
51
+ parts = `rack_res[2]`
52
+ if parts.respond_to?(:each)
53
+ parts.each do |part|
54
+ `res.write(part)`
55
+ end
56
+ elsif parts.respond_to?(:call)
57
+ `res.write(parts.$call())`
58
+ end
59
+ parts.close if parts.respond_to?(:close)
60
+ }
61
+ res.end();
62
+ });
63
+ server.listen(port, host, () => { console.log(`Server is running on http://${host}:${port}`)});
64
+ }
65
+ }
66
+ end
67
+
68
+ def self.stop
69
+ sleep 0.1
70
+ puts 'deflating request chain links'
71
+ sleep 0.1
72
+ puts 'optimizing response distortion'
73
+ sleep 0.1
74
+ print 'releasing boost pressure: '
75
+ 3.times do
76
+ sleep 0.2
77
+ print '.'
78
+ end
79
+ 3.times do
80
+ puts "\nRED ALERT: boost pressure to high, cannot open release valve!1!!!"
81
+ sleep 0.1
82
+ print '.'
83
+ sleep 0.1
84
+ end
85
+ puts 'stopping engines failed, for further help see:'
86
+ puts 'https://www.youtube.com/watch?v=ecBco63zvas'
87
+ end
88
+ end
89
+ end
data/lib/up/uws_cli.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'opal/platform'
2
+ require 'nodejs/file'
3
+ require 'nodejs/require'
4
+ require 'opal-parser'
5
+ require 'rack/builder'
6
+ require 'up/rack_builder_patch'
7
+
8
+ module Up
9
+ module CLI
10
+ def self.try_file(filename)
11
+ return nil unless File.exist? filename
12
+ ::Rack::Builder.parse_file filename
13
+ end
14
+
15
+ def self.get_app(filename = 'config.ru')
16
+ app = nil
17
+ filename ||= 'config.ru'
18
+ app = try_file filename
19
+ if File.exist?("#{filename}.ru")
20
+ filename = "#{filename}.ru"
21
+ app ||= try_file filename
22
+ end
23
+ raise "Something wrong with #{filename}\n" unless app
24
+ app
25
+ end
26
+
27
+ def self.call
28
+ app = get_app
29
+ Up::UwsRack.run(app)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Up
2
+ module UwsRack
3
+ def self.run(app, options = {})
4
+ Up::UWebSocket.listen(app: app, port: options[:port], host: options[:host])
5
+ true
6
+ end
7
+
8
+ def self.shutdown
9
+ Up::UWebSocket.stop
10
+ end
11
+ end
12
+ end
13
+
14
+ ENV['RACK_HANDLER'] ||= 'up'
15
+
16
+ begin
17
+ ::Rackup::Handler.register('up', Up::UwsRack) if defined?(::Rackup::Handler)
18
+ rescue StandardError
19
+ end
@@ -0,0 +1,99 @@
1
+ # backtick_javascript: true
2
+
3
+ require 'logger'
4
+ require 'up/version'
5
+
6
+ module Up
7
+ class UwsRackEnv < ::Hash
8
+ RACK_VARS = %w[rack.errors rack.hijack rack.hijack? rack.input rack.logger
9
+ rack.multipart.buffer_size rack.multipart.tempfile_factory
10
+ rack.response_finished
11
+ rack.session rack.upgrade rack.upgrade? rack.url_scheme
12
+ HTTP_ACCEPT HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE
13
+ HTTP_CONNECTION HTTP_HOST HTTP_USER_AGENT PATH_INFO QUERY_STRING REQUEST_METHOD
14
+ SCRIPT_NAME SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE]
15
+ def initialize(req, config)
16
+ @req = req
17
+ @config = config
18
+ end
19
+
20
+ def [](key)
21
+ return super(key) if key?(key)
22
+ self[key] = case key
23
+ when 'rack.errors'
24
+ STDERR
25
+ when 'rack.hijack'
26
+ nil
27
+ when 'rack.hijack?'
28
+ false
29
+ when 'rack.input'
30
+ ::IO.new
31
+ when 'rack.logger'
32
+ ::Logger.new(self['rack.errors'])
33
+ when 'rack.multipart.buffer_size'
34
+ 4096
35
+ when 'rack.multipart.tempfile_factory'
36
+ proc { |_filename, _content_type| File.new }
37
+ when 'rack.response_finished'
38
+ []
39
+ when 'rack.session'
40
+ {}
41
+ when 'rack.upgrade'
42
+ nil
43
+ when 'rack.upgrade?'
44
+ nil
45
+ when 'rack.url_scheme'
46
+ @config[:scheme]
47
+ when 'PATH_INFO'
48
+ `#@req.getUrl()`
49
+ when 'QUERY_STRING'
50
+ `#@req.getQuery()`
51
+ when 'RACK_ERRORS'
52
+ self['rack.errors']
53
+ when 'RACK_LOGGER'
54
+ self['rack.logger']
55
+ when 'REQUEST_METHOD'
56
+ `#@req.getMethod().toUpperCase()`
57
+ when 'SCRIPT_NAME'
58
+ ""
59
+ when 'SERVER_NAME'
60
+ @config[:host]
61
+ when 'SERVER_PORT'
62
+ @config[:port].to_s
63
+ when 'SERVER_PROTOCOL'
64
+ `#@req.getHeader('protocol')`
65
+ when 'SERVER_SOFTWARE'
66
+ "#{@config[:handler]}/#{Up::VERSION} #{@config[:engine]}"
67
+ else
68
+ if key.start_with?('HTTP_')
69
+ key = key[5..].gsub(/_/, '-')
70
+ `#@req.getHeader(key.toLowerCase())`
71
+ else
72
+ nil
73
+ end
74
+ end
75
+ end
76
+
77
+ def req_headers
78
+ h = {}
79
+ `#@req.forEach((k, v) => { h.set(k, v); })`
80
+ h
81
+ end
82
+
83
+ def each
84
+ unless @got_them_all
85
+ RACK_VARS.each { |k| self[k] unless self.key?(k) }
86
+ @got_them_all = true
87
+ end
88
+ super
89
+ end
90
+
91
+ def to_s
92
+ unless @got_them_all
93
+ RACK_VARS.each { |k| self[k] unless self.key?(k) }
94
+ @got_them_all = true
95
+ end
96
+ super
97
+ end
98
+ end
99
+ end
data/lib/up/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Up
2
+ VERSION = '0.0.1'.freeze
3
+ end
data/lib/up-bun.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Up
2
+ end
3
+
4
+ require 'up/bun_cli'
5
+ require 'up/bun'
6
+ require 'up/bun_rack'
7
+ require 'up/bun_rack_env'
data/lib/up-node.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Up
2
+ end
3
+
4
+ require 'up/uws_cli'
5
+ require 'up/u_web_socket'
6
+ require 'up/uws_rack'
7
+ require 'up/uws_rack_env'
data/opal-up.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require_relative 'lib/up/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'opal-up'
7
+ spec.version = Up::VERSION
8
+ spec.authors = ['Jan Biedermann']
9
+ spec.email = ['jan@kursator.de']
10
+
11
+ spec.summary = 'Rack server for Opal'
12
+ spec.description = 'High performance Rack server for Opal Ruby'
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test_app|test|spec|features)/}) }
16
+ spec.bindir = 'bin'
17
+ spec.executables = %w[up up_bun]
18
+ spec.require_paths = %w[lib]
19
+
20
+ spec.add_dependency 'logger', '~> 1.6.0'
21
+ spec.add_dependency 'opal', '>= 1.8.2', '< 3.0.0'
22
+ spec.add_dependency 'rack', '~> 3.0.9'
23
+ spec.add_dependency 'rackup', '>= 0.2.2', '< 3.0.0'
24
+
25
+ spec.add_development_dependency 'rake', '~> 13.1.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.12.0'
27
+ end
data/up_logo.svg ADDED
@@ -0,0 +1,256 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+
4
+ <svg
5
+ version="1.1"
6
+ id="Capa_1"
7
+ x="0px"
8
+ y="0px"
9
+ viewBox="0 0 799.92104 945.28792"
10
+ xml:space="preserve"
11
+ width="799.92102"
12
+ height="945.2879"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
15
+ id="defs65"><rect
16
+ x="222.77943"
17
+ y="327.29486"
18
+ width="357.86758"
19
+ height="243.77267"
20
+ id="rect66" /><rect
21
+ x="27.871536"
22
+ y="730.54065"
23
+ width="778.40509"
24
+ height="77.992775"
25
+ id="rect65" /></defs>
26
+ <rect
27
+ y="0"
28
+ style="clip-rule:evenodd;fill:#a0dbfa;fill-rule:evenodd;stroke-width:1.08707"
29
+ width="799.91998"
30
+ height="945.2879"
31
+ id="rect1"
32
+ x="0.001" />
33
+ <polygon
34
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
35
+ points="658.991,136.939 654.959,136.939 654.959,377.684 646.655,377.684 646.655,136.939 642.378,136.939 650.684,125.153 "
36
+ id="polygon1"
37
+ transform="translate(0.001,145.36792)" />
38
+ <path
39
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
40
+ d="m 51.406,361.61492 -10.996,-15.601 -11.853,16.817 v -77.905 H 43.49 l -28.997,-41.142 -14.492,20.562 v 680.942 c 287.066,0 608.08,0 799.92,0 v -667.871 l -23.525,33.38 h 13.71 v 49.736 l -9.558,-13.56 -8.285,11.756 v -97.417 h 14.933 l -28.997,-41.143 -28.998,41.143 h 14.075 v 32.453 l -6.645,-9.426 -19.901,28.237 h 9.66 v 31.023 l -11.389,-16.159 -12.573,17.839 v -58.049 h 14.933 l -28.997,-41.143 -28.997,41.143 h 14.075 v 48.193 l -11.716,-16.623 -28.996,41.143 h 14.074 v 33.128 l -10.901,-15.468 -12.667,17.972 v -82.428 h 14.933 l -28.997,-41.143 -28.997,41.143 h 14.075 v 23.414 l -10.996,-15.601 -11.853,16.818 v -77.905 h 14.933 l -28.997,-41.143 -28.997,41.143 h 14.075 v 48.954 l -9.197,-13.05 -28.244,40.074 h 13.709 v 49.736 l -9.557,-13.56 -8.285,11.756 v -97.417 h 14.932 l -28.997,-41.142 -28.996,41.142 h 14.074 v 32.453 l -6.643,-9.426 -19.901,28.237 h 9.66 v 31.023 l -11.389,-16.159 -12.573,17.839 v -58.049 h 14.933 l -28.997,-41.142 -28.997,41.142 h 14.075 v 48.193 l -11.716,-16.623 -28.997,41.142 h 14.075 v 29.21 l -11.853,-16.817 -11.715,16.623 v -75.811 h 14.932 l -28.997,-41.142 -28.996,41.142 h 14.075 v 23.414 l -10.996,-15.601 -11.853,16.817 v -77.905 h 14.932 l -28.997,-41.143 -28.997,41.143 h 14.075 v 23.9 l -9.197,-13.05 -28.244,40.074 h 13.71 v 49.736 l -9.557,-13.56 -8.286,11.756 v -137.781 h 14.933 l -28.997,-41.142 -28.996,41.142 h 14.075 v 72.818 l -6.644,-9.426 -19.902,28.237 h 9.66 v 31.023 l -11.389,-16.159 -12.573,17.839 v -58.049 h 14.933 l -28.997,-41.142 -28.996,41.142 h 14.075 v 48.193 l -11.715,-16.623 -28.997,41.142 h 14.075 v 22.63 l -12.349,-17.521 -11.22,15.92 v -67.824 h 14.933 l -28.997,-41.142 -29.001,41.143 h 14.075 z"
41
+ id="path1" />
42
+ <polygon
43
+ style="clip-rule:evenodd;fill:#0073a2;fill-rule:evenodd"
44
+ points="154.962,396.856 130.926,396.856 130.926,784.116 81.428,784.116 81.428,396.856 55.928,396.856 105.445,326.598 "
45
+ id="polygon2"
46
+ transform="translate(0.001,145.36792)" />
47
+ <polygon
48
+ style="clip-rule:evenodd;fill:#f4b200;fill-rule:evenodd"
49
+ points="114.003,487.786 89.967,487.786 89.967,784.116 40.468,784.116 40.468,487.786 14.968,487.786 64.485,417.528 "
50
+ id="polygon3"
51
+ transform="translate(0.001,145.36792)" />
52
+ <polygon
53
+ style="clip-rule:evenodd;fill:#e95818;fill-rule:evenodd"
54
+ points="89.967,487.786 89.967,784.116 81.428,784.116 81.428,441.566 114.003,487.786 "
55
+ id="polygon4"
56
+ transform="translate(0.001,145.36792)" />
57
+ <polygon
58
+ style="clip-rule:evenodd;fill:#dd0031;fill-rule:evenodd"
59
+ points="195.102,525.469 171.067,525.469 171.067,784.116 121.568,784.116 121.568,525.469 96.068,525.469 145.585,455.211 "
60
+ id="polygon5"
61
+ transform="translate(0.001,145.36792)" />
62
+ <polygon
63
+ style="clip-rule:evenodd;fill:#6f3969;fill-rule:evenodd"
64
+ points="130.926,784.116 121.568,784.116 121.568,525.469 96.068,525.469 130.926,476.01 "
65
+ id="polygon6"
66
+ transform="translate(0.001,145.36792)" />
67
+ <polygon
68
+ style="clip-rule:evenodd;fill:#a1ba24;fill-rule:evenodd"
69
+ points="236.166,307.834 212.13,307.834 212.13,784.116 162.631,784.116 162.631,307.834 137.132,307.834 186.649,237.576 "
70
+ id="polygon7"
71
+ transform="translate(0.001,145.36792)" />
72
+ <polygon
73
+ style="clip-rule:evenodd;fill:#bf5c2a;fill-rule:evenodd"
74
+ points="171.067,525.469 171.067,784.116 162.631,784.116 162.631,479.396 195.102,525.469 "
75
+ id="polygon8"
76
+ transform="translate(0.001,145.36792)" />
77
+ <polygon
78
+ style="clip-rule:evenodd;fill:#801d88;fill-rule:evenodd"
79
+ points="277.229,222.627 253.193,222.627 253.193,784.116 203.694,784.116 203.694,222.627 178.195,222.627 227.712,152.37 "
80
+ id="polygon9"
81
+ transform="translate(0.001,145.36792)" />
82
+ <polygon
83
+ style="clip-rule:evenodd;fill:#916c56;fill-rule:evenodd"
84
+ points="212.13,307.834 212.13,784.116 203.694,784.116 203.694,261.761 236.166,307.834 "
85
+ id="polygon10"
86
+ transform="translate(0.001,145.36792)" />
87
+ <polygon
88
+ style="clip-rule:evenodd;fill:#ed6500;fill-rule:evenodd"
89
+ points="319.225,360.012 295.189,360.012 295.189,784.116 245.69,784.116 245.69,360.012 220.19,360.012 269.707,289.754 "
90
+ id="polygon11"
91
+ transform="translate(0.001,145.36792)" />
92
+ <polygon
93
+ style="clip-rule:evenodd;fill:#b74144;fill-rule:evenodd"
94
+ points="253.193,784.116 245.69,784.116 245.69,360.012 220.19,360.012 253.193,313.185 "
95
+ id="polygon12"
96
+ transform="translate(0.001,145.36792)" />
97
+ <polygon
98
+ style="clip-rule:evenodd;fill:#0073a2;fill-rule:evenodd"
99
+ points="360.754,438.811 336.719,438.811 336.719,784.116 287.22,784.116 287.22,438.811 261.72,438.811 311.237,368.553 "
100
+ id="polygon13"
101
+ transform="translate(0.001,145.36792)" />
102
+ <polygon
103
+ style="clip-rule:evenodd;fill:#766c51;fill-rule:evenodd"
104
+ points="287.22,784.116 287.22,438.811 261.72,438.811 295.189,391.323 295.189,784.116 "
105
+ id="polygon14"
106
+ transform="translate(0.001,145.36792)" />
107
+ <polygon
108
+ style="clip-rule:evenodd;fill:#f4b200;fill-rule:evenodd"
109
+ points="402.284,289.731 378.248,289.731 378.248,784.116 328.749,784.116 328.749,289.731 303.249,289.731 352.767,219.473 "
110
+ id="polygon15"
111
+ transform="translate(0.001,145.36792)" />
112
+ <polygon
113
+ style="clip-rule:evenodd;fill:#7a9350;fill-rule:evenodd"
114
+ points="336.719,438.811 336.719,784.116 328.749,784.116 328.749,393.4 360.754,438.811 "
115
+ id="polygon16"
116
+ transform="translate(0.001,145.36792)" />
117
+ <polygon
118
+ style="clip-rule:evenodd;fill:#c5007e;fill-rule:evenodd"
119
+ points="443.813,385.568 419.777,385.568 419.777,784.116 370.278,784.116 370.278,385.568 344.779,385.568 394.296,315.311 "
120
+ id="polygon17"
121
+ transform="translate(0.001,145.36792)" />
122
+ <polygon
123
+ style="clip-rule:evenodd;fill:#dd593e;fill-rule:evenodd"
124
+ points="378.248,784.116 370.278,784.116 370.278,385.568 344.779,385.568 378.248,338.08 "
125
+ id="polygon18"
126
+ transform="translate(0.001,145.36792)" />
127
+ <polygon
128
+ style="clip-rule:evenodd;fill:#801d88;fill-rule:evenodd"
129
+ points="462.372,784.116 412.873,784.116 412.873,494.185 387.373,494.185 436.891,423.926 486.407,494.185 462.372,494.185 "
130
+ id="polygon19"
131
+ transform="translate(0.001,145.36792)" />
132
+ <polygon
133
+ style="clip-rule:evenodd;fill:#a30e83;fill-rule:evenodd"
134
+ points="419.777,784.116 412.873,784.116 412.873,494.185 387.373,494.185 419.777,448.207 "
135
+ id="polygon20"
136
+ transform="translate(0.001,145.36792)" />
137
+ <polygon
138
+ style="clip-rule:evenodd;fill:#dd0031;fill-rule:evenodd"
139
+ points="530.066,585.762 506.03,585.762 506.03,784.116 456.532,784.116 456.532,585.762 431.032,585.762 480.55,515.504 "
140
+ id="polygon21"
141
+ transform="translate(0.001,145.36792)" />
142
+ <polygon
143
+ style="clip-rule:evenodd;fill:#af0e5c;fill-rule:evenodd"
144
+ points="456.532,784.116 456.532,585.762 431.032,585.762 462.372,541.295 462.372,784.116 "
145
+ id="polygon22"
146
+ transform="translate(0.001,145.36792)" />
147
+ <polygon
148
+ style="clip-rule:evenodd;fill:#ed6500;fill-rule:evenodd"
149
+ points="572.661,424.968 548.625,424.968 548.625,784.116 499.126,784.116 499.126,424.968 473.627,424.968 523.144,354.71 "
150
+ id="polygon23"
151
+ transform="translate(0.001,145.36792)" />
152
+ <polygon
153
+ style="clip-rule:evenodd;fill:#e53218;fill-rule:evenodd"
154
+ points="506.03,585.762 506.03,784.116 499.126,784.116 499.126,541.861 530.066,585.762 "
155
+ id="polygon24"
156
+ transform="translate(0.001,145.36792)" />
157
+ <polygon
158
+ style="clip-rule:evenodd;fill:#0073a2;fill-rule:evenodd"
159
+ points="615.255,327.001 591.22,327.001 591.22,784.116 541.721,784.116 541.721,327.001 516.221,327.001 565.738,256.743 "
160
+ id="polygon25"
161
+ transform="translate(0.001,145.36792)" />
162
+ <polygon
163
+ style="clip-rule:evenodd;fill:#766c51;fill-rule:evenodd"
164
+ points="548.625,424.968 548.625,784.116 541.721,784.116 541.721,381.068 572.661,424.968 "
165
+ id="polygon26"
166
+ transform="translate(0.001,145.36792)" />
167
+ <polygon
168
+ style="clip-rule:evenodd;fill:#f4b200;fill-rule:evenodd"
169
+ points="657.85,472.887 633.813,472.887 633.813,784.116 584.315,784.116 584.315,472.887 558.815,472.887 608.332,402.629 "
170
+ id="polygon27"
171
+ transform="translate(0.001,145.36792)" />
172
+ <polygon
173
+ style="clip-rule:evenodd;fill:#7a9350;fill-rule:evenodd"
174
+ points="584.315,784.116 584.315,472.887 558.815,472.887 591.22,426.909 591.22,784.116 "
175
+ id="polygon28"
176
+ transform="translate(0.001,145.36792)" />
177
+ <polygon
178
+ style="clip-rule:evenodd;fill:#801d88;fill-rule:evenodd"
179
+ points="701.509,571.919 677.473,571.919 677.473,784.116 627.974,784.116 627.974,571.919 602.475,571.919 651.991,501.66 "
180
+ id="polygon29"
181
+ transform="translate(0.001,145.36792)" />
182
+ <polygon
183
+ style="clip-rule:evenodd;fill:#ba6744;fill-rule:evenodd"
184
+ points="633.813,784.116 627.974,784.116 627.974,571.919 602.475,571.919 633.813,527.452 "
185
+ id="polygon30"
186
+ transform="translate(0.001,145.36792)" />
187
+ <polygon
188
+ style="clip-rule:evenodd;fill:#a1ba24;fill-rule:evenodd"
189
+ points="744.102,399.412 720.067,399.412 720.067,784.116 670.568,784.116 670.568,399.412 645.068,399.412 694.586,329.153 "
190
+ id="polygon31"
191
+ transform="translate(0.001,145.36792)" />
192
+ <polygon
193
+ style="clip-rule:evenodd;fill:#916c56;fill-rule:evenodd"
194
+ points="677.473,571.919 677.473,784.116 670.568,784.116 670.568,528.018 701.509,571.919 "
195
+ id="polygon32"
196
+ transform="translate(0.001,145.36792)" />
197
+ <polygon
198
+ style="clip-rule:evenodd;fill:#dd0031;fill-rule:evenodd"
199
+ points="786.697,511.222 762.661,511.222 762.661,784.116 713.162,784.116 713.162,511.222 687.662,511.222 737.18,440.964 "
200
+ id="polygon33"
201
+ transform="translate(0.001,145.36792)" />
202
+ <polygon
203
+ style="clip-rule:evenodd;fill:#bf5c2a;fill-rule:evenodd"
204
+ points="713.162,784.116 713.162,511.222 687.662,511.222 720.067,465.244 720.067,784.116 "
205
+ id="polygon34"
206
+ transform="translate(0.001,145.36792)" />
207
+ <path
208
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
209
+ d="m 140.554,690.37292 28.997,-41.143 28.997,41.143 h -14.075 v 64.45 l 10.996,-15.602 28.997,41.143 h -14.075 v 23.414 l 10.996,-15.602 11.852,16.817 v -77.905 h -14.932 l 28.997,-41.142 28.997,41.142 h -14.075 v 48.954 l 9.197,-13.05 28.245,40.075 h -13.71 v 49.735 l 9.557,-13.56 8.286,11.757 v -97.417 h -14.933 l 28.997,-41.142 28.997,41.142 h -14.075 v 32.453 l 6.644,-9.427 19.901,28.238 h -9.66 v 31.022 l 11.389,-16.159 12.573,17.839 v -58.049 h -14.933 l 28.997,-41.143 28.997,41.143 H 402.62 v 48.193 l 11.716,-16.623 21.46416,30.45686 5.31084,-6.92086 11.716,16.622 v -45.81 h -14.933 l 28.997,-41.142 28.997,41.142 h -14.075 v 23.414 l 10.996,-15.601 11.853,16.817 v -77.905 h -14.933 l 28.997,-41.143 28.997,41.143 h -14.075 v 23.899 l 9.198,-13.05 28.243,40.075 H 557.38 v 49.735 l 9.557,-13.56 8.286,11.757 v -137.78 H 560.29 l 28.997,-41.142 28.997,41.142 h -14.075 v 72.818 l 6.644,-9.427 19.901,28.238 h -9.66 v 31.022 l 11.39,-16.159 12.572,17.839 v -58.049 h -14.933 l 28.997,-41.143 28.997,41.143 h -14.075 v 48.193 l 11.716,-16.623 22.43456,30.47358 4.83644,-6.22158 11.22,15.92 v -45.824 h -14.932 l 28.997,-41.142 28.996,41.142 h -14.074 v 23.414 l 10.995,-15.601 11.852,16.817 v -77.905 l -11.98653,-0.65137 26.05053,-40.49163 9.773,13.867 v 208.42 H 0 v -195.348 l 28.244,40.074 h -13.71 v 49.735 l 9.557,-13.56 8.286,11.756 v -97.416 H 17.446 l 28.997,-41.143 28.997,41.143 H 61.365 v 32.452 l 6.644,-9.426 19.901,28.237 h -9.66 v 31.022 l 11.389,-16.159 12.573,17.839 v -58.049 H 87.279 l 28.997,-41.142 28.997,41.142 h -14.075 v 48.193 l 11.716,-16.622 12.573,17.839 v -113.481 z"
210
+ id="path34" />
211
+
212
+ <polygon
213
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
214
+ points="73.967,118.991 69.935,118.991 69.935,359.736 61.631,359.736 61.631,118.991 57.354,118.991 65.66,107.205 "
215
+ id="polygon60"
216
+ transform="translate(0.001,145.36792)" />
217
+ <polygon
218
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
219
+ points="156.145,37.469 152.112,37.469 152.112,278.214 143.809,278.214 143.809,37.469 139.531,37.469 147.837,25.683 "
220
+ id="polygon61"
221
+ transform="translate(0.001,145.36792)" />
222
+ <polygon
223
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
224
+ points="653.848,606.583 649.815,606.583 649.815,756.577 641.512,756.577 641.512,606.583 637.234,606.583 645.541,594.797 "
225
+ id="polygon62"
226
+ transform="translate(0.001,145.36792)" />
227
+ <polygon
228
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
229
+ points="132.417,541.98 128.384,541.98 128.384,691.976 120.081,691.976 120.081,541.98 115.803,541.98 124.109,530.194 "
230
+ id="polygon63"
231
+ transform="translate(0.001,145.36792)" />
232
+ <polygon
233
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
234
+ points="752.289,592.739 748.256,592.739 748.256,742.734 739.953,742.734 739.953,592.739 735.675,592.739 743.981,580.953 "
235
+ id="polygon64"
236
+ transform="translate(0.001,145.36792)" />
237
+ <polygon
238
+ style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd"
239
+ points="471.004,75.805 466.972,75.805 466.972,316.55 458.668,316.55 458.668,75.805 454.391,75.805 462.697,64.019 "
240
+ id="polygon65"
241
+ transform="translate(0.001,145.36792)" />
242
+ <text
243
+ xml:space="preserve"
244
+ id="text65"
245
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:53.3333px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect65);fill:#000000"
246
+ transform="translate(-11.999,133.36792)"><tspan
247
+ x="27.871094"
248
+ y="778.58122"
249
+ id="tspan1">UNEXPECTED PROMPTITUDE</tspan></text><text
250
+ xml:space="preserve"
251
+ id="text66"
252
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:192px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect66);fill:#000000"
253
+ transform="translate(20.13016,-317.87561)"><tspan
254
+ x="222.7793"
255
+ y="500.23977"
256
+ id="tspan2">UP!</tspan></text></svg>
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opal-up
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jan Biedermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logger
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: opal
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.2
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: 3.0.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.8.2
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rack
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 3.0.9
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.0.9
61
+ - !ruby/object:Gem::Dependency
62
+ name: rackup
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 0.2.2
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: 3.0.0
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 0.2.2
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: 3.0.0
81
+ - !ruby/object:Gem::Dependency
82
+ name: rake
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: 13.1.0
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: 13.1.0
95
+ - !ruby/object:Gem::Dependency
96
+ name: rspec
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: 3.12.0
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: 3.12.0
109
+ description: High performance Rack server for Opal Ruby
110
+ email:
111
+ - jan@kursator.de
112
+ executables:
113
+ - up
114
+ - up_bun
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - bin/up
123
+ - bin/up_bun
124
+ - example_rack_app/Gemfile
125
+ - example_rack_app/config.ru
126
+ - example_rack_app/rack_app.rb
127
+ - example_roda_app/Gemfile
128
+ - example_roda_app/config.ru
129
+ - example_roda_app/roda_app.rb
130
+ - example_sinatra_app/Gemfile
131
+ - example_sinatra_app/config.ru
132
+ - example_sinatra_app/sinatra_app.rb
133
+ - lib/up-bun.rb
134
+ - lib/up-node.rb
135
+ - lib/up/bun.rb
136
+ - lib/up/bun_cli.rb
137
+ - lib/up/bun_rack.rb
138
+ - lib/up/bun_rack_env.rb
139
+ - lib/up/rack_builder_patch.rb
140
+ - lib/up/u_web_socket.rb
141
+ - lib/up/u_web_socket_cluster.rb
142
+ - lib/up/uws_cli.rb
143
+ - lib/up/uws_rack.rb
144
+ - lib/up/uws_rack_env.rb
145
+ - lib/up/version.rb
146
+ - opal-up.gemspec
147
+ - up_logo.svg
148
+ homepage: ''
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubygems_version: 3.5.3
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Rack server for Opal
171
+ test_files: []