rage-rb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +15 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +96 -0
- data/Rakefile +8 -0
- data/exe/rage +4 -0
- data/lib/rage/application.rb +34 -0
- data/lib/rage/cli.rb +49 -0
- data/lib/rage/controller/api.rb +123 -0
- data/lib/rage/fiber.rb +9 -0
- data/lib/rage/fiber_scheduler.rb +98 -0
- data/lib/rage/router/README.md +19 -0
- data/lib/rage/router/backend.rb +249 -0
- data/lib/rage/router/constrainer.rb +91 -0
- data/lib/rage/router/dsl.rb +135 -0
- data/lib/rage/router/handler_storage.rb +153 -0
- data/lib/rage/router/node.rb +202 -0
- data/lib/rage/router/strategies/host.rb +50 -0
- data/lib/rage/setup.rb +6 -0
- data/lib/rage/templates/Gemfile +6 -0
- data/lib/rage/templates/app-controllers-application_controller.rb +2 -0
- data/lib/rage/templates/config-application.rb +4 -0
- data/lib/rage/templates/config-routes.rb +3 -0
- data/lib/rage/templates/config.ru +3 -0
- data/lib/rage/templates/lib-.keep +0 -0
- data/lib/rage/templates/log-.keep +0 -0
- data/lib/rage/templates/public-.keep +0 -0
- data/lib/rage/version.rb +5 -0
- data/lib/rage.rb +40 -0
- data/rage.gemspec +33 -0
- metadata +120 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module Rage::Router
|
6
|
+
class Node
|
7
|
+
STATIC = 0
|
8
|
+
PARAMETRIC = 1
|
9
|
+
WILDCARD = 2
|
10
|
+
|
11
|
+
attr_reader :is_leaf_node, :handler_storage, :kind
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@is_leaf_node = false
|
15
|
+
@routes = nil
|
16
|
+
@handler_storage = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_route(route, constrainer)
|
20
|
+
@routes ||= []
|
21
|
+
@handler_storage ||= HandlerStorage.new
|
22
|
+
|
23
|
+
@is_leaf_node = true
|
24
|
+
@routes << route
|
25
|
+
@handler_storage.add_handler(constrainer, route)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ParentNode < Node
|
30
|
+
attr_reader :static_children
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
super
|
34
|
+
@static_children = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_static_matching_child(path, path_index)
|
38
|
+
static_child = @static_children[path[path_index]]
|
39
|
+
|
40
|
+
if !static_child || !static_child.match_prefix.call(path, path_index)
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
|
44
|
+
static_child
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_static_child(path)
|
48
|
+
if path.length == 0
|
49
|
+
return self
|
50
|
+
end
|
51
|
+
|
52
|
+
static_child = @static_children[path[0]]
|
53
|
+
if static_child
|
54
|
+
i = 1
|
55
|
+
while i < static_child.prefix.length
|
56
|
+
if path[i] != static_child.prefix[i]
|
57
|
+
static_child = static_child.split(self, i)
|
58
|
+
break
|
59
|
+
end
|
60
|
+
i += 1
|
61
|
+
end
|
62
|
+
|
63
|
+
return static_child.create_static_child(path[i, path.length - i])
|
64
|
+
end
|
65
|
+
|
66
|
+
@static_children[path[0]] = StaticNode.new(path)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class StaticNode < ParentNode
|
71
|
+
attr_reader :prefix, :match_prefix
|
72
|
+
|
73
|
+
def initialize(prefix)
|
74
|
+
super()
|
75
|
+
@prefix = prefix
|
76
|
+
@wildcard_child = nil
|
77
|
+
@parametric_children = []
|
78
|
+
@kind = Node::STATIC
|
79
|
+
|
80
|
+
compile_prefix_match
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_parametric_child(static_suffix, node_path)
|
84
|
+
parametric_child = @parametric_children[0]
|
85
|
+
|
86
|
+
if parametric_child
|
87
|
+
parametric_child.node_paths.add(node_path)
|
88
|
+
return parametric_child
|
89
|
+
end
|
90
|
+
|
91
|
+
parametric_child = ParametricNode.new(static_suffix, node_path)
|
92
|
+
@parametric_children << parametric_child
|
93
|
+
@parametric_children.sort! do |child1, child2|
|
94
|
+
if child1.static_suffix.nil?
|
95
|
+
1
|
96
|
+
elsif child2.static_suffix.nil?
|
97
|
+
-1
|
98
|
+
elsif child2.static_suffix.end_with?(child1.static_suffix)
|
99
|
+
1
|
100
|
+
elsif child1.static_suffix.end_with?(child2.static_suffix)
|
101
|
+
-1
|
102
|
+
else
|
103
|
+
0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
parametric_child
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_wildcard_child
|
111
|
+
@wildcard_child ||= WildcardNode.new
|
112
|
+
end
|
113
|
+
|
114
|
+
def split(parent_node, length)
|
115
|
+
parent_prefix = @prefix[0, length]
|
116
|
+
child_prefix = @prefix[length, @prefix.length - length]
|
117
|
+
|
118
|
+
@prefix = child_prefix
|
119
|
+
compile_prefix_match
|
120
|
+
|
121
|
+
static_node = StaticNode.new(parent_prefix)
|
122
|
+
static_node.static_children[child_prefix[0]] = self
|
123
|
+
parent_node.static_children[parent_prefix[0]] = static_node
|
124
|
+
|
125
|
+
static_node
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_next_node(path, path_index, node_stack, params_count)
|
129
|
+
node = find_static_matching_child(path, path_index)
|
130
|
+
parametric_brother_node_index = 0
|
131
|
+
|
132
|
+
unless node
|
133
|
+
return @wildcard_child if @parametric_children.empty?
|
134
|
+
|
135
|
+
node = @parametric_children[0]
|
136
|
+
parametric_brother_node_index = 1
|
137
|
+
end
|
138
|
+
|
139
|
+
if @wildcard_child
|
140
|
+
node_stack << {
|
141
|
+
params_count: params_count,
|
142
|
+
brother_path_index: path_index,
|
143
|
+
brother_node: @wildcard_child
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
i = @parametric_children.length - 1
|
148
|
+
while i >= parametric_brother_node_index
|
149
|
+
node_stack << {
|
150
|
+
params_count: params_count,
|
151
|
+
brother_path_index: path_index,
|
152
|
+
brother_node: @parametric_children[i]
|
153
|
+
}
|
154
|
+
i -= 1
|
155
|
+
end
|
156
|
+
|
157
|
+
node
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def compile_prefix_match
|
163
|
+
if @prefix.length == 1
|
164
|
+
@match_prefix = ->(_, _) { true }
|
165
|
+
return
|
166
|
+
end
|
167
|
+
|
168
|
+
lines = (1...@prefix.length).map do |i|
|
169
|
+
"path[i + #{i}]&.ord == #{@prefix[i].ord}"
|
170
|
+
end
|
171
|
+
|
172
|
+
@match_prefix = eval("->(path, i) { #{lines.join(" && ")} }")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class ParametricNode < ParentNode
|
177
|
+
attr_reader :static_suffix, :node_paths
|
178
|
+
|
179
|
+
def initialize(static_suffix, node_path)
|
180
|
+
super()
|
181
|
+
@static_suffix = static_suffix
|
182
|
+
@kind = Node::PARAMETRIC
|
183
|
+
|
184
|
+
@node_paths = Set.new([node_path])
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_next_node(path, path_index, _, _)
|
188
|
+
find_static_matching_child(path, path_index)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class WildcardNode < Node
|
193
|
+
def initialize
|
194
|
+
super
|
195
|
+
@kind = Node::WILDCARD
|
196
|
+
end
|
197
|
+
|
198
|
+
def get_next_node(*)
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Rage::Router::Strategies::Host
|
4
|
+
attr_reader :name, :must_match_when_derived
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@name = "host"
|
8
|
+
@must_match_when_derived = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def storage
|
12
|
+
HostStorage.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def custom?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate(value)
|
20
|
+
if !value.is_a?(String) && !value.is_a?(Regexp)
|
21
|
+
raise "Host should be a string or a Regexp"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class HostStorage
|
26
|
+
def initialize
|
27
|
+
@hosts = {}
|
28
|
+
@regexp_hosts = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(host)
|
32
|
+
exact = @hosts[host]
|
33
|
+
return exact if exact
|
34
|
+
|
35
|
+
@regexp_hosts.each do |regexp|
|
36
|
+
return regexp[:value] if regexp[:host] =~ host.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def set(host, value)
|
43
|
+
if host.is_a?(Regexp)
|
44
|
+
@regexp_hosts << { host: host, value: value }
|
45
|
+
else
|
46
|
+
@hosts[host] = value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/rage/setup.rb
ADDED
File without changes
|
File without changes
|
File without changes
|
data/lib/rage/version.rb
ADDED
data/lib/rage.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack"
|
4
|
+
require "json"
|
5
|
+
require "iodine"
|
6
|
+
|
7
|
+
module Rage
|
8
|
+
def self.application
|
9
|
+
Application.new(__router)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.routes
|
13
|
+
Rage::Router::DSL.new(__router)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.__router
|
17
|
+
@__router ||= Rage::Router::Backend.new
|
18
|
+
end
|
19
|
+
|
20
|
+
module Router
|
21
|
+
module Strategies
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module RageController
|
27
|
+
end
|
28
|
+
|
29
|
+
require_relative "rage/application"
|
30
|
+
require_relative "rage/fiber"
|
31
|
+
require_relative "rage/fiber_scheduler"
|
32
|
+
|
33
|
+
require_relative "rage/router/strategies/host"
|
34
|
+
require_relative "rage/router/backend"
|
35
|
+
require_relative "rage/router/constrainer"
|
36
|
+
require_relative "rage/router/dsl"
|
37
|
+
require_relative "rage/router/handler_storage"
|
38
|
+
require_relative "rage/router/node"
|
39
|
+
|
40
|
+
require_relative "rage/controller/api"
|
data/rage.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/rage/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rage-rb"
|
7
|
+
spec.version = Rage::VERSION
|
8
|
+
spec.authors = ["Roman Samoilov"]
|
9
|
+
spec.email = ["rsamoi@icloud.com"]
|
10
|
+
|
11
|
+
spec.summary = "Fast web framework compatible with Rails."
|
12
|
+
spec.homepage = "https://github.com/rage-rb/rage"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = ">= 3.0.0"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/rage-rb/rage"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = ["rage"]
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_dependency "thor"
|
31
|
+
spec.add_dependency "rack", "~> 2.0"
|
32
|
+
spec.add_dependency "rage-iodine", "~> 1.0"
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rage-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roman Samoilov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rage-iodine
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- rsamoi@icloud.com
|
58
|
+
executables:
|
59
|
+
- rage
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".rspec"
|
64
|
+
- CHANGELOG.md
|
65
|
+
- CODE_OF_CONDUCT.md
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- exe/rage
|
71
|
+
- lib/rage.rb
|
72
|
+
- lib/rage/application.rb
|
73
|
+
- lib/rage/cli.rb
|
74
|
+
- lib/rage/controller/api.rb
|
75
|
+
- lib/rage/fiber.rb
|
76
|
+
- lib/rage/fiber_scheduler.rb
|
77
|
+
- lib/rage/router/README.md
|
78
|
+
- lib/rage/router/backend.rb
|
79
|
+
- lib/rage/router/constrainer.rb
|
80
|
+
- lib/rage/router/dsl.rb
|
81
|
+
- lib/rage/router/handler_storage.rb
|
82
|
+
- lib/rage/router/node.rb
|
83
|
+
- lib/rage/router/strategies/host.rb
|
84
|
+
- lib/rage/setup.rb
|
85
|
+
- lib/rage/templates/Gemfile
|
86
|
+
- lib/rage/templates/app-controllers-application_controller.rb
|
87
|
+
- lib/rage/templates/config-application.rb
|
88
|
+
- lib/rage/templates/config-routes.rb
|
89
|
+
- lib/rage/templates/config.ru
|
90
|
+
- lib/rage/templates/lib-.keep
|
91
|
+
- lib/rage/templates/log-.keep
|
92
|
+
- lib/rage/templates/public-.keep
|
93
|
+
- lib/rage/version.rb
|
94
|
+
- rage.gemspec
|
95
|
+
homepage: https://github.com/rage-rb/rage
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata:
|
99
|
+
homepage_uri: https://github.com/rage-rb/rage
|
100
|
+
source_code_uri: https://github.com/rage-rb/rage
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 3.0.0
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubygems_version: 3.4.10
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Fast web framework compatible with Rails.
|
120
|
+
test_files: []
|