opal-up 0.0.1

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 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: []