itsi-server 0.1.11 → 0.1.12
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +7 -0
- data/Cargo.lock +1536 -45
- data/README.md +4 -0
- data/_index.md +6 -0
- data/exe/itsi +33 -74
- data/ext/itsi_error/src/lib.rs +9 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
- data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
- data/ext/itsi_rb_helpers/Cargo.toml +1 -0
- data/ext/itsi_rb_helpers/src/heap_value.rs +18 -0
- data/ext/itsi_rb_helpers/src/lib.rs +34 -7
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
- data/ext/itsi_rb_helpers/target/debug/build/rb-sys-eb9ed4ff3a60f995/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
- data/ext/itsi_server/Cargo.toml +69 -30
- data/ext/itsi_server/src/lib.rs +79 -147
- data/ext/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
- data/ext/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +22 -3
- data/ext/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
- data/ext/itsi_server/src/{request/itsi_request.rs → ruby_types/itsi_http_request.rs} +101 -117
- data/ext/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
- data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +82 -0
- data/ext/itsi_server/src/ruby_types/mod.rs +55 -0
- data/ext/itsi_server/src/server/bind.rs +13 -5
- data/ext/itsi_server/src/server/byte_frame.rs +32 -0
- data/ext/itsi_server/src/server/cache_store.rs +74 -0
- data/ext/itsi_server/src/server/itsi_service.rs +172 -0
- data/ext/itsi_server/src/server/lifecycle_event.rs +3 -0
- data/ext/itsi_server/src/server/listener.rs +102 -2
- data/ext/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
- data/ext/itsi_server/src/server/middleware_stack/mod.rs +315 -0
- data/ext/itsi_server/src/server/mod.rs +8 -1
- data/ext/itsi_server/src/server/process_worker.rs +38 -12
- data/ext/itsi_server/src/server/rate_limiter.rs +565 -0
- data/ext/itsi_server/src/server/request_job.rs +11 -0
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +119 -42
- data/ext/itsi_server/src/server/serve_strategy/mod.rs +9 -6
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +256 -111
- data/ext/itsi_server/src/server/signal.rs +19 -0
- data/ext/itsi_server/src/server/static_file_server.rs +984 -0
- data/ext/itsi_server/src/server/thread_worker.rs +139 -94
- data/ext/itsi_server/src/server/types.rs +43 -0
- data/ext/itsi_tracing/Cargo.toml +1 -0
- data/ext/itsi_tracing/src/lib.rs +216 -45
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
- data/lib/itsi/{request.rb → http_request.rb} +29 -5
- data/lib/itsi/http_response.rb +39 -0
- data/lib/itsi/server/Itsi.rb +11 -19
- data/lib/itsi/server/config/dsl.rb +506 -0
- data/lib/itsi/server/config.rb +103 -8
- data/lib/itsi/server/default_app/default_app.rb +38 -0
- data/lib/itsi/server/grpc_interface.rb +213 -0
- data/lib/itsi/server/rack/handler/itsi.rb +8 -17
- data/lib/itsi/server/rack_interface.rb +23 -4
- data/lib/itsi/server/scheduler_interface.rb +1 -1
- data/lib/itsi/server/scheduler_mode.rb +4 -0
- data/lib/itsi/server/signal_trap.rb +7 -1
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +74 -63
- data/lib/itsi/standard_headers.rb +86 -0
- metadata +84 -15
- data/ext/itsi_scheduler/extconf.rb +0 -6
- data/ext/itsi_server/src/body_proxy/mod.rs +0 -2
- data/ext/itsi_server/src/request/mod.rs +0 -1
- data/ext/itsi_server/src/response/mod.rs +0 -1
- data/ext/itsi_server/src/server/itsi_server.rs +0 -288
- data/lib/itsi/server/options_dsl.rb +0 -401
- data/lib/itsi/stream_io.rb +0 -38
- /data/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -1,401 +0,0 @@
|
|
1
|
-
module Itsi
|
2
|
-
class Server
|
3
|
-
class OptionsDSL
|
4
|
-
attr_reader :parent, :children, :filters, :endpoint_defs, :controller_class
|
5
|
-
|
6
|
-
def self.evaluate(filename)
|
7
|
-
new do
|
8
|
-
instance_eval(IO.read(filename))
|
9
|
-
end.to_options
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(parent = nil, route_specs = [], &block)
|
13
|
-
@parent = parent
|
14
|
-
@children = []
|
15
|
-
@filters = {}
|
16
|
-
@endpoint_defs = [] # Each is [subpath, *endpoint_args]
|
17
|
-
@controller_class = nil
|
18
|
-
@options = {}
|
19
|
-
|
20
|
-
# We'll store our array of route specs (strings or a single Regexp).
|
21
|
-
@route_specs = Array(route_specs).flatten
|
22
|
-
|
23
|
-
validate_path_specs!(@route_specs)
|
24
|
-
instance_exec(&block)
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_options
|
28
|
-
@options.merge(
|
29
|
-
{
|
30
|
-
routes: flatten_routes
|
31
|
-
}
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
|
-
def workers(workers)
|
36
|
-
raise "Workers must be set at the root" unless @parent.nil?
|
37
|
-
|
38
|
-
@options[:workers] = [workers.to_i, 1].max
|
39
|
-
end
|
40
|
-
|
41
|
-
def threads(threads)
|
42
|
-
raise "Threads must be set at the root" unless @parent.nil?
|
43
|
-
|
44
|
-
@options[:threads] = [threads.to_i, 1].max
|
45
|
-
end
|
46
|
-
|
47
|
-
def rackup_file(rackup_file)
|
48
|
-
raise "Rackup file must be set at the root" unless @parent.nil?
|
49
|
-
raise "rackup_file already set" if @options[:rackup_file]
|
50
|
-
raise "Cannot provide a rackup_file if app is defined" if @options[:app]
|
51
|
-
|
52
|
-
if rackup_file.is_a?(File) && rackup_file.exist?
|
53
|
-
@options[:rackup_file] = file_path
|
54
|
-
else
|
55
|
-
file_path = rackup_file
|
56
|
-
@options[:rackup_file] = file_path if File.exist?(file_path)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def oob_gc_responses_threshold(threshold)
|
61
|
-
raise "OOB GC responses threshold must be set at the root" unless @parent.nil?
|
62
|
-
|
63
|
-
@options[:oob_gc_responses_threshold] = threshold.to_i
|
64
|
-
end
|
65
|
-
|
66
|
-
def log_level(level)
|
67
|
-
raise "Log level must be set at the root" unless @parent.nil?
|
68
|
-
|
69
|
-
ENV["ITSI_LOG"] = level.to_s
|
70
|
-
end
|
71
|
-
|
72
|
-
def log_format(format)
|
73
|
-
raise "Log format must be set at the root" unless @parent.nil?
|
74
|
-
|
75
|
-
case format.to_s
|
76
|
-
when "auto"
|
77
|
-
when "ansi" then ENV['ITSI_LOG_ANSI'] = "true"
|
78
|
-
when "json", "plain" then ENV['ITSI_LOG_PLAIN'] = "true"
|
79
|
-
else raise "Invalid log format '#{format}'"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def run(app)
|
84
|
-
raise "App must be set at the root" unless @parent.nil?
|
85
|
-
raise "App already set" if @options[:app]
|
86
|
-
raise "Cannot provide an app if rackup_file is defined" if @options[:rackup_file]
|
87
|
-
|
88
|
-
@options[:app] = app
|
89
|
-
end
|
90
|
-
|
91
|
-
def bind(bind_str)
|
92
|
-
raise "Bind must be set at the root" unless @parent.nil?
|
93
|
-
|
94
|
-
@options[:binds] ||= []
|
95
|
-
@options[:binds] << bind_str.to_s
|
96
|
-
end
|
97
|
-
|
98
|
-
def after_fork(&block)
|
99
|
-
raise "After fork must be set at the root" unless @parent.nil?
|
100
|
-
|
101
|
-
@options[:hooks] ||= {}
|
102
|
-
@options[:hooks][:after_fork] = block
|
103
|
-
end
|
104
|
-
|
105
|
-
def before_fork(&block)
|
106
|
-
raise "Before fork must be set at the root" unless @parent.nil?
|
107
|
-
|
108
|
-
@options[:hooks] ||= {}
|
109
|
-
@options[:hooks][:before_fork] = block
|
110
|
-
end
|
111
|
-
|
112
|
-
def after_memory_threshold_reached(&block)
|
113
|
-
raise "Before fork must be set at the root" unless @parent.nil?
|
114
|
-
|
115
|
-
@options[:hooks] ||= {}
|
116
|
-
@options[:hooks][:after_memory_threshold_reached] = block
|
117
|
-
end
|
118
|
-
|
119
|
-
def worker_memory_limit(memory_limit)
|
120
|
-
raise "Worker memory limit must be set at the root" unless @parent.nil?
|
121
|
-
|
122
|
-
@options[:worker_memory_limit] = memory_limit
|
123
|
-
end
|
124
|
-
|
125
|
-
def fiber_scheduler(klass_name)
|
126
|
-
raise "Fiber scheduler must be set at the root" unless @parent.nil?
|
127
|
-
|
128
|
-
@options[:scheduler_class] = klass_name if klass_name
|
129
|
-
end
|
130
|
-
|
131
|
-
def preload(preload)
|
132
|
-
raise "Preload must be set at the root" unless @parent.nil?
|
133
|
-
|
134
|
-
@options[:preload] = preload
|
135
|
-
end
|
136
|
-
|
137
|
-
def shutdown_timeout(shutdown_timeout)
|
138
|
-
raise "Shutdown timeout must be set at the root" unless @parent.nil?
|
139
|
-
|
140
|
-
@options[:shutdown_timeout] = shutdown_timeout.to_f
|
141
|
-
end
|
142
|
-
|
143
|
-
def script_name(script_name)
|
144
|
-
raise "Script name must be set at the root" unless @parent.nil?
|
145
|
-
|
146
|
-
@options[:script_name] = script_name.to_s
|
147
|
-
end
|
148
|
-
|
149
|
-
def stream_body(stream_body)
|
150
|
-
raise "Stream body must be set at the root" unless @parent.nil?
|
151
|
-
|
152
|
-
@options[:stream_body] = !!stream_body
|
153
|
-
end
|
154
|
-
|
155
|
-
def location(*route_specs, &block)
|
156
|
-
route_specs = route_specs.flatten
|
157
|
-
child = OptionsDSL.new(self, route_specs, &block)
|
158
|
-
@children << child
|
159
|
-
end
|
160
|
-
|
161
|
-
# define endpoints
|
162
|
-
def endpoint(subpath, *args)
|
163
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
164
|
-
|
165
|
-
@endpoint_defs << [subpath, *args]
|
166
|
-
end
|
167
|
-
|
168
|
-
def controller(klass)
|
169
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
170
|
-
|
171
|
-
@controller_class = klass
|
172
|
-
end
|
173
|
-
|
174
|
-
# define some filters
|
175
|
-
def basic_auth(**args)
|
176
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
177
|
-
|
178
|
-
@filters[:basic_auth] = args
|
179
|
-
end
|
180
|
-
|
181
|
-
# define some filters
|
182
|
-
def redirect(**args)
|
183
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
184
|
-
|
185
|
-
@filters[:redirect] = args
|
186
|
-
end
|
187
|
-
|
188
|
-
def jwt_auth(**args)
|
189
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
190
|
-
|
191
|
-
@filters[:jwt_auth] = args
|
192
|
-
end
|
193
|
-
|
194
|
-
def api_key_auth(**args)
|
195
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
196
|
-
|
197
|
-
@filters[:api_key_auth] = args
|
198
|
-
end
|
199
|
-
|
200
|
-
def compress(**args)
|
201
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
202
|
-
|
203
|
-
@filters[:compress] = args
|
204
|
-
end
|
205
|
-
|
206
|
-
def rate_limit(name, **args)
|
207
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
208
|
-
|
209
|
-
@filters[:rate_limit] = { name: name }.merge(args)
|
210
|
-
end
|
211
|
-
|
212
|
-
def cors(**args)
|
213
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
214
|
-
|
215
|
-
@filters[:cors] = args
|
216
|
-
end
|
217
|
-
|
218
|
-
def file_server(**args)
|
219
|
-
raise "Endpoint must be set inside a location block" if @parent.is_nil?
|
220
|
-
|
221
|
-
@filters[:file_server] = args
|
222
|
-
end
|
223
|
-
|
224
|
-
def flatten_routes
|
225
|
-
child_routes = @children.flat_map(&:flatten_routes)
|
226
|
-
base_expansions = combined_paths_from_parent
|
227
|
-
endpoint_routes = @endpoint_defs.map do |(endpoint_subpath, *endpoint_args)|
|
228
|
-
ep_expansions = expand_single_subpath(endpoint_subpath)
|
229
|
-
final_regex_str = or_pattern_for(cartesian_combine(base_expansions, ep_expansions))
|
230
|
-
|
231
|
-
{
|
232
|
-
route: Regexp.new("^#{final_regex_str}$"),
|
233
|
-
filters: effective_filters_with_endpoint(endpoint_args)
|
234
|
-
}
|
235
|
-
end
|
236
|
-
|
237
|
-
location_route = unless @route_specs.empty?
|
238
|
-
pattern_str = or_pattern_for(base_expansions) # the expansions themselves
|
239
|
-
{
|
240
|
-
route: Regexp.new("^#{pattern_str}$"),
|
241
|
-
filters: effective_filters
|
242
|
-
}
|
243
|
-
end
|
244
|
-
|
245
|
-
result = []
|
246
|
-
result.concat(child_routes)
|
247
|
-
result.concat(endpoint_routes)
|
248
|
-
result << location_route if location_route
|
249
|
-
result
|
250
|
-
end
|
251
|
-
|
252
|
-
def validate_path_specs!(specs)
|
253
|
-
regexes = specs.select { |s| s.is_a?(Regexp) }
|
254
|
-
return unless regexes.size > 1
|
255
|
-
|
256
|
-
raise ArgumentError, "Cannot have multiple raw Regex route specs in a single location."
|
257
|
-
end
|
258
|
-
|
259
|
-
# Called by flatten_routes to get expansions from the parent's expansions combined with mine
|
260
|
-
def combined_paths_from_parent
|
261
|
-
if parent
|
262
|
-
pex = parent.combined_paths_from_parent_for_children
|
263
|
-
cartesian_combine(pex, expansions_for(@route_specs))
|
264
|
-
else
|
265
|
-
expansions_for(@route_specs)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
def combined_paths_from_parent_for_children
|
270
|
-
if parent
|
271
|
-
pex = parent.combined_paths_from_parent_for_children
|
272
|
-
cartesian_combine(pex, expansions_for(@route_specs))
|
273
|
-
else
|
274
|
-
expansions_for(@route_specs)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
def expand_single_subpath(subpath)
|
279
|
-
expansions_for([subpath]) # just treat it as a mini specs array
|
280
|
-
end
|
281
|
-
|
282
|
-
def expansions_for(specs)
|
283
|
-
return [] if specs.empty?
|
284
|
-
|
285
|
-
if specs.any? { |s| s.is_a? Regexp }
|
286
|
-
raise "Cannot combine a raw Regexp with other strings in the same location." if specs.size > 1
|
287
|
-
|
288
|
-
[[:raw_regex, specs.first]]
|
289
|
-
else
|
290
|
-
specs.map do |string_spec|
|
291
|
-
string_spec = string_spec.sub(%r{^/}, "")
|
292
|
-
string_spec
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
def cartesian_combine(parent_exps, child_exps)
|
298
|
-
return child_exps if parent_exps.empty?
|
299
|
-
return parent_exps if child_exps.empty?
|
300
|
-
|
301
|
-
if parent_exps.size == 1 && parent_exps.first.is_a?(Array) && parent_exps.first.first == :raw_regex
|
302
|
-
raise "Cannot nest under a raw Regexp route."
|
303
|
-
end
|
304
|
-
|
305
|
-
if child_exps.size == 1 && child_exps.first.is_a?(Array) && child_exps.first.first == :raw_regex
|
306
|
-
raise "Cannot nest a raw Regexp route under a parent string route."
|
307
|
-
end
|
308
|
-
|
309
|
-
results = []
|
310
|
-
parent_exps.each do |p|
|
311
|
-
child_exps.each do |c|
|
312
|
-
joined = [p, c].reject(&:empty?).join("/")
|
313
|
-
results << joined
|
314
|
-
end
|
315
|
-
end
|
316
|
-
results
|
317
|
-
end
|
318
|
-
|
319
|
-
def or_pattern_for(expansions)
|
320
|
-
return "" if expansions.empty?
|
321
|
-
|
322
|
-
if expansions.size == 1 && expansions.first.is_a?(Array) && expansions.first.first == :raw_regex
|
323
|
-
raw = expansions.first.last
|
324
|
-
return raw.source # Use the raw Regexp's source
|
325
|
-
end
|
326
|
-
|
327
|
-
pattern_pieces = expansions.map do |exp|
|
328
|
-
if exp.empty?
|
329
|
-
"" # => means top-level "/"
|
330
|
-
else
|
331
|
-
segment_to_regex_with_slash(exp)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
joined = pattern_pieces.join("|")
|
336
|
-
|
337
|
-
"(?:#{joined})"
|
338
|
-
end
|
339
|
-
|
340
|
-
def segment_to_regex_with_slash(path_str)
|
341
|
-
return "" if path_str == ""
|
342
|
-
|
343
|
-
segments = path_str.split("/")
|
344
|
-
|
345
|
-
converted = segments.map do |seg|
|
346
|
-
# wildcard?
|
347
|
-
next ".*" if seg == "*"
|
348
|
-
|
349
|
-
# :param(...)?
|
350
|
-
if seg =~ /^:([A-Za-z_]\w*)(?:\(([^)]*)\))?$/
|
351
|
-
param_name = Regexp.last_match(1)
|
352
|
-
custom = Regexp.last_match(2)
|
353
|
-
if custom && !custom.empty?
|
354
|
-
"(?<#{param_name}>#{custom})"
|
355
|
-
else
|
356
|
-
"(?<#{param_name}>[^/]+)"
|
357
|
-
end
|
358
|
-
else
|
359
|
-
Regexp.escape(seg)
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
converted.join("/")
|
364
|
-
end
|
365
|
-
|
366
|
-
def effective_filters
|
367
|
-
# gather from root -> self, overriding duplicates
|
368
|
-
merged = merge_ancestor_filters
|
369
|
-
# turn into array
|
370
|
-
merged.map { |k, v| { type: k, params: v } }
|
371
|
-
end
|
372
|
-
|
373
|
-
def effective_filters_with_endpoint(endpoint_args)
|
374
|
-
arr = effective_filters
|
375
|
-
# endpoint filter last
|
376
|
-
ep_filter_params = endpoint_args.dup
|
377
|
-
ep_filter_params << @controller_class if @controller_class
|
378
|
-
arr << { type: :endpoint, params: ep_filter_params }
|
379
|
-
arr
|
380
|
-
end
|
381
|
-
|
382
|
-
def merge_ancestor_filters
|
383
|
-
chain = []
|
384
|
-
node = self
|
385
|
-
while node
|
386
|
-
chain << node
|
387
|
-
node = node.parent
|
388
|
-
end
|
389
|
-
chain.reverse!
|
390
|
-
|
391
|
-
merged = {}
|
392
|
-
chain.each do |n|
|
393
|
-
n.filters.each do |k, v|
|
394
|
-
merged[k] = v
|
395
|
-
end
|
396
|
-
end
|
397
|
-
merged
|
398
|
-
end
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
data/lib/itsi/stream_io.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Itsi
|
2
|
-
class StreamIO
|
3
|
-
attr :response
|
4
|
-
def initialize(response)
|
5
|
-
@response = response
|
6
|
-
end
|
7
|
-
|
8
|
-
def read
|
9
|
-
response.recv_frame
|
10
|
-
end
|
11
|
-
|
12
|
-
def write(string)
|
13
|
-
response.send_frame(string)
|
14
|
-
end
|
15
|
-
|
16
|
-
def <<(string)
|
17
|
-
response.send_frame(string)
|
18
|
-
end
|
19
|
-
|
20
|
-
def flush
|
21
|
-
# No-op
|
22
|
-
end
|
23
|
-
|
24
|
-
def close
|
25
|
-
close_read
|
26
|
-
close_write
|
27
|
-
end
|
28
|
-
|
29
|
-
def close_read
|
30
|
-
response.close_read
|
31
|
-
end
|
32
|
-
|
33
|
-
def close_write
|
34
|
-
response.close_write
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
File without changes
|