itsi 0.1.14 → 0.1.18
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/Cargo.lock +124 -109
- data/Cargo.toml +6 -0
- data/crates/itsi_error/Cargo.toml +1 -0
- data/crates/itsi_error/src/lib.rs +100 -10
- data/crates/itsi_scheduler/src/itsi_scheduler.rs +1 -1
- data/crates/itsi_server/Cargo.toml +8 -10
- data/crates/itsi_server/src/default_responses/html/401.html +68 -0
- data/crates/itsi_server/src/default_responses/html/403.html +68 -0
- data/crates/itsi_server/src/default_responses/html/404.html +68 -0
- data/crates/itsi_server/src/default_responses/html/413.html +71 -0
- data/crates/itsi_server/src/default_responses/html/429.html +68 -0
- data/crates/itsi_server/src/default_responses/html/500.html +71 -0
- data/crates/itsi_server/src/default_responses/html/502.html +71 -0
- data/crates/itsi_server/src/default_responses/html/503.html +68 -0
- data/crates/itsi_server/src/default_responses/html/504.html +69 -0
- data/crates/itsi_server/src/default_responses/html/index.html +238 -0
- data/crates/itsi_server/src/default_responses/json/401.json +6 -0
- data/crates/itsi_server/src/default_responses/json/403.json +6 -0
- data/crates/itsi_server/src/default_responses/json/404.json +6 -0
- data/crates/itsi_server/src/default_responses/json/413.json +6 -0
- data/crates/itsi_server/src/default_responses/json/429.json +6 -0
- data/crates/itsi_server/src/default_responses/json/500.json +6 -0
- data/crates/itsi_server/src/default_responses/json/502.json +6 -0
- data/crates/itsi_server/src/default_responses/json/503.json +6 -0
- data/crates/itsi_server/src/default_responses/json/504.json +6 -0
- data/crates/itsi_server/src/default_responses/mod.rs +11 -0
- data/crates/itsi_server/src/lib.rs +58 -26
- data/crates/itsi_server/src/prelude.rs +2 -0
- data/crates/itsi_server/src/ruby_types/README.md +21 -0
- data/crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +8 -6
- data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
- data/crates/itsi_server/src/ruby_types/{itsi_grpc_stream → itsi_grpc_response_stream}/mod.rs +121 -73
- data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +103 -40
- data/crates/itsi_server/src/ruby_types/itsi_http_response.rs +8 -5
- data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +4 -4
- data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +37 -17
- data/crates/itsi_server/src/ruby_types/itsi_server.rs +4 -3
- data/crates/itsi_server/src/ruby_types/mod.rs +6 -13
- data/crates/itsi_server/src/server/{bind.rs → binds/bind.rs} +23 -4
- data/crates/itsi_server/src/server/{listener.rs → binds/listener.rs} +24 -10
- data/crates/itsi_server/src/server/binds/mod.rs +4 -0
- data/crates/itsi_server/src/server/{tls.rs → binds/tls.rs} +9 -4
- data/crates/itsi_server/src/server/http_message_types.rs +97 -0
- data/crates/itsi_server/src/server/io_stream.rs +2 -1
- data/crates/itsi_server/src/server/middleware_stack/middleware.rs +28 -16
- data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +17 -8
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +47 -18
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +13 -9
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +50 -29
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +5 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +37 -48
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +25 -20
- data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +14 -7
- data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +125 -95
- data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +9 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +1 -4
- data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +25 -19
- data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +4 -4
- data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +9 -4
- data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +260 -62
- data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +29 -22
- data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +6 -6
- data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +6 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +4 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +51 -18
- data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +31 -13
- data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +13 -8
- data/crates/itsi_server/src/server/middleware_stack/mod.rs +101 -69
- data/crates/itsi_server/src/server/mod.rs +3 -9
- data/crates/itsi_server/src/server/process_worker.rs +21 -3
- data/crates/itsi_server/src/server/request_job.rs +2 -2
- data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +8 -3
- data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +26 -26
- data/crates/itsi_server/src/server/signal.rs +24 -41
- data/crates/itsi_server/src/server/size_limited_incoming.rs +101 -0
- data/crates/itsi_server/src/server/thread_worker.rs +59 -28
- data/crates/itsi_server/src/services/itsi_http_service.rs +239 -0
- data/crates/itsi_server/src/services/mime_types.rs +1416 -0
- data/crates/itsi_server/src/services/mod.rs +6 -0
- data/crates/itsi_server/src/services/password_hasher.rs +83 -0
- data/crates/itsi_server/src/{server → services}/rate_limiter.rs +35 -31
- data/crates/itsi_server/src/{server → services}/static_file_server.rs +521 -181
- data/crates/itsi_tracing/src/lib.rs +145 -55
- data/{Itsi.rb → foo/Itsi.rb} +6 -9
- data/gems/scheduler/Cargo.lock +7 -0
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/test/helpers/test_helper.rb +0 -1
- data/gems/scheduler/test/test_address_resolve.rb +0 -1
- data/gems/scheduler/test/test_network_io.rb +1 -1
- data/gems/scheduler/test/test_process_wait.rb +0 -1
- data/gems/server/Cargo.lock +124 -109
- data/gems/server/exe/itsi +65 -19
- data/gems/server/itsi-server.gemspec +4 -3
- data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +74 -0
- data/gems/server/lib/itsi/http_request.rb +116 -17
- data/gems/server/lib/itsi/http_response.rb +2 -0
- data/gems/server/lib/itsi/passfile.rb +109 -0
- data/gems/server/lib/itsi/server/config/dsl.rb +160 -101
- data/gems/server/lib/itsi/server/config.rb +58 -23
- data/gems/server/lib/itsi/server/default_app/default_app.rb +25 -29
- data/gems/server/lib/itsi/server/default_app/index.html +113 -89
- data/gems/server/lib/itsi/server/{Itsi.rb → default_config/Itsi-rackup.rb} +1 -1
- data/gems/server/lib/itsi/server/default_config/Itsi.rb +107 -0
- data/gems/server/lib/itsi/server/grpc/grpc_call.rb +246 -0
- data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +100 -0
- data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
- data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
- data/gems/server/lib/itsi/server/route_tester.rb +107 -0
- data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +200 -0
- data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +55 -0
- data/gems/server/lib/itsi/server/typed_handlers.rb +17 -0
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +82 -12
- data/gems/server/lib/ruby_lsp/itsi/addon.rb +111 -0
- data/gems/server/lib/shell_completions/completions.rb +26 -0
- data/gems/server/test/helpers/test_helper.rb +2 -1
- data/lib/itsi/version.rb +1 -1
- data/sandbox/README.md +5 -0
- data/sandbox/itsi_file/Gemfile +4 -2
- data/sandbox/itsi_file/Gemfile.lock +48 -6
- data/sandbox/itsi_file/Itsi.rb +326 -129
- data/sandbox/itsi_file/call.json +1 -0
- data/sandbox/itsi_file/echo_client/Gemfile +10 -0
- data/sandbox/itsi_file/echo_client/Gemfile.lock +27 -0
- data/sandbox/itsi_file/echo_client/README.md +95 -0
- data/sandbox/itsi_file/echo_client/echo_client.rb +164 -0
- data/sandbox/itsi_file/echo_client/gen_proto.sh +17 -0
- data/sandbox/itsi_file/echo_client/lib/echo_pb.rb +16 -0
- data/sandbox/itsi_file/echo_client/lib/echo_services_pb.rb +29 -0
- data/sandbox/itsi_file/echo_client/run_client.rb +64 -0
- data/sandbox/itsi_file/echo_client/test_compressions.sh +20 -0
- data/sandbox/itsi_file/echo_service_nonitsi/Gemfile +10 -0
- data/sandbox/itsi_file/echo_service_nonitsi/Gemfile.lock +79 -0
- data/sandbox/itsi_file/echo_service_nonitsi/echo.proto +26 -0
- data/sandbox/itsi_file/echo_service_nonitsi/echo_pb.rb +16 -0
- data/sandbox/itsi_file/echo_service_nonitsi/echo_services_pb.rb +29 -0
- data/sandbox/itsi_file/echo_service_nonitsi/server.rb +52 -0
- data/sandbox/itsi_sandbox_async/config.ru +0 -1
- data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
- data/sandbox/itsi_sandbox_rails/Gemfile +2 -2
- data/sandbox/itsi_sandbox_rails/Gemfile.lock +76 -2
- data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +15 -0
- data/sandbox/itsi_sandbox_rails/config/environments/development.rb +1 -0
- data/sandbox/itsi_sandbox_rails/config/environments/production.rb +1 -0
- data/sandbox/itsi_sandbox_rails/config/routes.rb +2 -0
- data/sandbox/itsi_sinatra/app.rb +0 -1
- data/sandbox/static_files/.env +1 -0
- data/sandbox/static_files/404.html +25 -0
- data/sandbox/static_files/_DSC0102.NEF.jpg +0 -0
- data/sandbox/static_files/about.html +68 -0
- data/sandbox/static_files/tiny.html +1 -0
- data/sandbox/static_files/writebook.zip +0 -0
- data/tasks.txt +28 -33
- metadata +87 -26
- data/crates/itsi_error/src/from.rs +0 -68
- data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +0 -147
- data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +0 -19
- data/crates/itsi_server/src/server/itsi_service.rs +0 -172
- data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +0 -72
- data/crates/itsi_server/src/server/types.rs +0 -43
- data/gems/server/lib/itsi/server/grpc_interface.rb +0 -213
- data/sandbox/itsi_file/public/assets/index.html +0 -1
- /data/crates/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
- /data/crates/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +0 -0
- /data/crates/itsi_server/src/{server → services}/cache_store.rs +0 -0
data/sandbox/itsi_file/Itsi.rb
CHANGED
@@ -1,150 +1,359 @@
|
|
1
1
|
workers 1
|
2
2
|
threads 1
|
3
|
+
fiber_scheduler true
|
4
|
+
|
5
|
+
scheduler_threads 1
|
6
|
+
|
7
|
+
request_timeout 2
|
3
8
|
|
4
9
|
preload false
|
5
10
|
|
6
11
|
bind 'http://localhost:3000'
|
7
|
-
bind 'http://0.0.0.0:8000'
|
8
12
|
|
9
|
-
shutdown_timeout
|
10
|
-
multithreaded_reactor true
|
13
|
+
shutdown_timeout 10
|
11
14
|
|
12
|
-
|
15
|
+
auto_reload_config!
|
13
16
|
|
14
|
-
|
15
|
-
response = request.response
|
16
|
-
response.status = 200
|
17
|
-
response.add_header('Content-Type', 'text/plain')
|
18
|
-
response << 'Hello, user!'
|
19
|
-
response.close
|
20
|
-
end
|
17
|
+
log_format :plain
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
response.status = 201
|
25
|
-
response.add_header('Content-Type', 'text/plain')
|
26
|
-
response << 'User created!'
|
27
|
-
response.close
|
19
|
+
get "/root" do |req|
|
20
|
+
req.ok "Got from root"
|
28
21
|
end
|
29
22
|
|
30
|
-
location "/etag-test" do
|
31
|
-
etag type: 'strong', algorithm: 'sha256', min_body_size: 0
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
resp = req.response
|
39
|
-
req.respond("Content: #{content}.# Generated at: #{Time.now}")
|
24
|
+
location "app" do
|
25
|
+
location "/users" do
|
26
|
+
get "/:id" do |req|
|
27
|
+
req.ok "Got user #{req.url_params[:id]}"
|
28
|
+
end
|
40
29
|
end
|
30
|
+
|
31
|
+
run(->(env){
|
32
|
+
[200, {}, ["Fallback Rack app"]]
|
33
|
+
})
|
41
34
|
end
|
42
35
|
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
static_assets \
|
38
|
+
relative_path: true,
|
39
|
+
root_dir: "public",
|
40
|
+
not_found_behavior: "fallthrough",
|
41
|
+
try_html_extension: true,
|
42
|
+
auto_index: true,
|
43
|
+
max_file_size_in_memory: 1024 * 1024,
|
44
|
+
max_files_in_memory: 1000,
|
45
|
+
file_check_interval: 5,
|
46
|
+
serve_hidden_files: false
|
47
|
+
|
48
|
+
run(->(env){
|
49
|
+
[200, {}, ["Final Fallback Rack App"]]
|
50
|
+
})
|
51
|
+
# location %q{/foo/:id(\d+)/test/:name/bla} do
|
52
|
+
# get "/" do |req|
|
53
|
+
# req.respond json: req.url_params
|
54
|
+
# end
|
55
|
+
# end
|
47
56
|
|
48
|
-
|
49
|
-
|
57
|
+
# location "blocking" do
|
58
|
+
# run ->(env){
|
59
|
+
# sleep 0.25
|
60
|
+
# [200, {}, [:ok]]
|
61
|
+
# }
|
62
|
+
# end
|
50
63
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
64
|
+
# location "nonblocking" do
|
65
|
+
# run(->(env){
|
66
|
+
# sleep 0.25
|
67
|
+
# [200, {}, [:ok]]
|
68
|
+
# }, nonblocking: true)
|
69
|
+
# end
|
55
70
|
|
71
|
+
# require_relative 'echo_service/echo_service_impl'
|
56
72
|
|
57
|
-
|
58
|
-
|
73
|
+
# grpc EchoServiceImpl.new, nonblocking: false do
|
74
|
+
# end
|
59
75
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
get '/users/id' do |req|
|
64
|
-
user_id = 5
|
65
|
-
req.respond("User data for #{user_id}")
|
66
|
-
end
|
67
|
-
end
|
76
|
+
# location "foo" do
|
77
|
+
# static_response code: 200, headers: [["Headers","Foo"]], body: "This is my body"
|
78
|
+
# end
|
68
79
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
get '/' do |req|
|
79
|
-
puts "Headers are", "#{req["foo"]}"
|
80
|
-
req.respond("Is this still fast?")
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
80
|
+
# location "/public" do
|
81
|
+
# static_assets relative_path: true, root_dir: "public", not_found_behavior: {error: 'not_found'},
|
82
|
+
# try_html_extension: true, auto_index: true, max_file_size_in_memory: 1024 * 1024,
|
83
|
+
# # Maximum number of files to keep in memory cache
|
84
|
+
# max_files_in_memory: 1000,
|
85
|
+
# # Check for file modifications every 5 seconds
|
86
|
+
# file_check_interval: 5,
|
87
|
+
# serve_hidden_files: false
|
88
|
+
# end
|
84
89
|
|
85
|
-
|
86
|
-
|
87
|
-
cache_control max_age: 3600, public: true, vary: ['Accept-Encoding']
|
88
|
-
get '/' do |req|
|
89
|
-
req.respond("This content is cached for 1 hour.")
|
90
|
-
end
|
91
|
-
end
|
90
|
+
# require 'debug'
|
91
|
+
# require 'date'
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
content = "This content will have ETags. " * 20
|
98
|
-
req.respond(content)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
93
|
+
# UserSchema = {
|
94
|
+
# id: Integer,
|
95
|
+
# name: String
|
96
|
+
# }
|
102
97
|
|
103
98
|
|
99
|
+
# ResultSchema = {
|
100
|
+
# status_code: Integer,
|
101
|
+
# user: UserSchema
|
102
|
+
# }
|
104
103
|
|
105
|
-
#
|
106
|
-
location "/assets" do
|
107
|
-
cache_control max_age: 604800, s_max_age: 2592000,
|
108
|
-
stale_while_revalidate: 86400,
|
109
|
-
public: true, immutable: true
|
104
|
+
# module UserController
|
110
105
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
106
|
+
# def self.create(req)
|
107
|
+
# req.ok \
|
108
|
+
# json: {
|
109
|
+
# status: :created,
|
110
|
+
# user: user
|
111
|
+
# }
|
112
|
+
# end
|
113
|
+
|
114
|
+
# def self.create(req, params: UserSchema, return_type: ResultSchema)
|
115
|
+
# req.ok \
|
116
|
+
# json: {
|
117
|
+
# status_code: 5,
|
118
|
+
# user: params
|
119
|
+
# },
|
120
|
+
# as: return_type
|
121
|
+
# end
|
122
|
+
|
123
|
+
# def self.create_no_type(req, params)
|
124
|
+
# req.ok json: "foo"
|
125
|
+
# end
|
126
|
+
|
127
|
+
# end
|
128
|
+
|
129
|
+
# controller UserController
|
130
|
+
# post "/", :create
|
131
|
+
# get "/" do |req, return_type: ResultSchema|
|
132
|
+
# req.ok as: return_type, json: {
|
133
|
+
# status_code: 5,
|
134
|
+
# user: {
|
135
|
+
# id: 3,
|
136
|
+
# name: "Foo Bar"
|
137
|
+
# }
|
138
|
+
# }
|
139
|
+
# end
|
140
|
+
|
141
|
+
# post "/nt", :create_no_type
|
142
|
+
|
143
|
+
# location "/rack" do
|
144
|
+
# run(->(env){
|
145
|
+
# sleep 5
|
146
|
+
# [200, {}, [:ok]]
|
147
|
+
# })
|
148
|
+
# end
|
149
|
+
# location '*' do
|
150
|
+
# proxy to: 'http://{host}{path_and_query}', backends: ['127.0.0.1:8082','127.0.0.1:8080', '127.0.0.1:8081'], headers: {}, verify_ssl: false, timeout: 1, tls_sni: false, backend_priority: 'round_robin'
|
151
|
+
# end
|
116
152
|
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
153
|
+
# # require_relative 'echo_service/echo_service_impl'
|
154
|
+
|
155
|
+
# # grpc EchoServiceImpl.new do
|
156
|
+
|
157
|
+
# # end
|
158
|
+
|
159
|
+
# location '/' do
|
160
|
+
# # compress algorithms: ['zstd'], min_size: 0, compress_streams: true, mime_types: ['all'], level: 'fastest'
|
161
|
+
# max_body max_size: 5
|
162
|
+
# get '/' do |req|
|
163
|
+
# req.respond('Foo')
|
164
|
+
# end
|
165
|
+
# etag type: 'weak', algorithm: 'md5', min_body_size: 0
|
166
|
+
# post '/' do |req|
|
167
|
+
# puts "Post to me!"
|
168
|
+
# req.respond('Foo')
|
169
|
+
# end
|
170
|
+
# end
|
171
|
+
|
172
|
+
# location '/' do
|
173
|
+
# end
|
174
|
+
# rate_limit requests: 5, seconds: 5, key: 'address', store_config: { redis: { connection_url: 'redis://localhost:6379/0' } }, error_response: { plaintext: 'no way', code: 429, default: 'plaintext' }
|
175
|
+
|
176
|
+
#
|
177
|
+
|
178
|
+
# static_assets\
|
179
|
+
# relative_path: true,
|
180
|
+
# root_dir: 'spa/dist',
|
181
|
+
# # # Only allow certain file extensions
|
182
|
+
# # allowed_extensions: %w[css js jpg jpeg png gif svg ico woff woff2 ttf
|
183
|
+
# # otf html],
|
184
|
+
# # Return a 404 error if file is not found
|
185
|
+
# not_found_behavior: { index: 'index.html' },
|
186
|
+
# # Enable auto-indexing of directories
|
187
|
+
# auto_index: true,
|
188
|
+
# # Try adding .html extension to extensionless URLs
|
189
|
+
# try_html_extension: true,
|
190
|
+
# # Files under this size are cached in memory
|
191
|
+
# max_file_size_in_memory: 1024 * 1024, # 1MB
|
192
|
+
# # Maximum number of files to keep in memory cache
|
193
|
+
# max_files_in_memory: 1000,
|
194
|
+
# # Check for file modifications every 5 seconds
|
195
|
+
# file_check_interval: 5,
|
196
|
+
# # Add custom headers to all responses
|
197
|
+
# headers: {
|
198
|
+
# 'Cache-Control' => 'public, max-age=86400',
|
199
|
+
# 'X-Content-Type-Options' => 'nosniff'
|
200
|
+
# }
|
201
|
+
|
202
|
+
# run(lambda { |env|
|
203
|
+
# [200, {}, ["I'm a fallback"]]
|
204
|
+
# })
|
205
|
+
|
206
|
+
# def user_serve(request)
|
207
|
+
# response = request.response
|
208
|
+
# response.status = 200
|
209
|
+
# response.add_header('Content-Type', 'text/plain')
|
210
|
+
# response << 'Hello, user!'
|
211
|
+
# response.close
|
212
|
+
# end
|
213
|
+
|
214
|
+
# def user_create(request)
|
215
|
+
# response = request.response
|
216
|
+
# response.status = 201
|
217
|
+
# response.add_header('Content-Type', 'text/plain')
|
218
|
+
# response << 'User created!'
|
219
|
+
# response.close
|
220
|
+
# end
|
221
|
+
|
222
|
+
# location "/etag-test" do
|
223
|
+
# etag type: 'strong', algorithm: 'sha256', min_body_size: 0
|
224
|
+
|
225
|
+
# get '/' do |req|
|
226
|
+
# # Fixed content that will generate the same ETag each time
|
227
|
+
# content = "This is a fixed response that will always have the same ETag."
|
228
|
+
|
229
|
+
# # Add a timestamp as a comment to see the response is fresh
|
230
|
+
# resp = req.response
|
231
|
+
# req.respond("Content: #{content}.# Generated at: #{Time.now}")
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
|
235
|
+
# location "/cached-with-etag" do
|
236
|
+
# # Set up caching parameters
|
237
|
+
# cache_control max_age: 3600, public: true, vary: ['Accept-Encoding']
|
238
|
+
|
239
|
+
# # Add ETags for cache validation
|
240
|
+
# etag type: 'weak', algorithm: 'md5', min_body_size: 0
|
241
|
+
|
242
|
+
# get '/' do |req|
|
243
|
+
# req.respond("This response will have both cache headers and an ETag.")
|
244
|
+
# end
|
245
|
+
# end
|
246
|
+
|
247
|
+
# location "/" do
|
248
|
+
# intrusion_protection banned_time_seconds: 5, banned_url_patterns: [/\/admin/, /\/secret/], store_config: { redis: { connection_url: 'redis://localhost:6379/0' } }, error_response: { plaintext: 'no way', code: 403, default: 'plaintext' }
|
249
|
+
|
250
|
+
# # Example for API endpoints with ETags
|
251
|
+
# location "/api" do
|
252
|
+
# etag type: 'weak', algorithm: 'md5', min_body_size: 0
|
253
|
+
# get '/users/id' do |req|
|
254
|
+
# user_id = 5
|
255
|
+
# req.respond("User data for #{user_id}")
|
256
|
+
# end
|
257
|
+
# end
|
258
|
+
|
259
|
+
# location "/hey" do
|
260
|
+
# location "/world*" do
|
261
|
+
# request_headers additions: {"X-Custom-Req" => ["Foo", "Bar", "Baz"]}, removals: [""]
|
262
|
+
# response_headers additions: {"X-Custom-Resp" => ["Foo", "Bar"]}, removals: []
|
263
|
+
# rate_limit requests: 5, seconds: 30, key: 'address', store_config: { redis: { connection_url: 'redis://localhost:6379/0' } }, error_response: { plaintext: 'no way', code: 429, default: 'plaintext' }
|
264
|
+
# post '/' do |req|
|
265
|
+
# puts "I'm a post!"
|
266
|
+
# req.respond("Post successful!")
|
267
|
+
# end
|
268
|
+
# get '/' do |req|
|
269
|
+
# req.respond("Is this still fast?")
|
270
|
+
# end
|
271
|
+
# end
|
272
|
+
# end
|
273
|
+
|
274
|
+
# # Add a new location with cache_control middleware
|
275
|
+
# location "/cached" do
|
276
|
+
# cache_control max_age: 3600, public: true, vary: ['Accept-Encoding']
|
277
|
+
# get '/' do |req|
|
278
|
+
# req.respond("This content is cached for 1 hour.")
|
279
|
+
# end
|
280
|
+
# end
|
281
|
+
|
282
|
+
# location "/etag" do
|
283
|
+
# etag enabled: true, etag_type: 'strong', hash_algorithm: 'sha256', min_body_size: 0
|
284
|
+
# get '/' do |req|
|
285
|
+
# # Create a response large enough to be worth ETagging
|
286
|
+
# content = "This content will have ETags. " * 20
|
287
|
+
# req.respond(content)
|
288
|
+
# end
|
289
|
+
# end
|
290
|
+
|
291
|
+
# location "/jwt" do
|
292
|
+
# auth_jwt token_source: { header: { name: 'Authorization', prefix: 'Bearer ' } },
|
293
|
+
# verifiers: {
|
294
|
+
# 'hs256' => ["1V6nZzztO/F6Y3XAYXJ1I37AAXCJ/V7EVHJoVnD8lr4="],
|
295
|
+
# 'rs256' => [%Q{
|
296
|
+
# -----BEGIN PUBLIC KEY-----
|
297
|
+
# MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs8XK+wP7nnKkOGXP6+il
|
298
|
+
# +JDQMFRV8zoVg1BYYapGla6AzR0YCV6xq28lNB1FE8C6xhCEKYiOlnkXZwj+a4UW
|
299
|
+
# q4Bex/U9qvfza0zGxHlTnQT9T+vjwXNsWYuefYC4EAZjEd6bGeP23De128QfhlLc
|
300
|
+
# oQpcfW32/e8KjSYtn8rtWuKV6Anqf92o9zEbVn8y2OZwZbiW0LbfDnimazqP5ATy
|
301
|
+
# SI6a5kQorBeG9cU4WW93ctuT5nkyAbBaEpiejWIpjbMkofD5fj2pUgg7H/Xvh+eR
|
302
|
+
# S9A+//VGfy4A4SFjBooVewhJ04VhDkMnVC29fbVwVuNqm6Z+FZaxI5pqvisxvH8S
|
303
|
+
# XwIDAQAB
|
304
|
+
# -----END PUBLIC KEY-----
|
305
|
+
# }]
|
306
|
+
# }, error_response: { code: 401, plaintext: 'Unauthorized', default: 'plaintext' }
|
307
|
+
# get "/" do |req|
|
308
|
+
# req.respond('Hello, JWT user!')
|
309
|
+
# end
|
310
|
+
# end
|
311
|
+
|
312
|
+
# end
|
313
|
+
|
314
|
+
# # For an assets example
|
315
|
+
# location "/assets" do
|
316
|
+
# cache_control max_age: 604800, s_max_age: 2592000,
|
317
|
+
# stale_while_revalidate: 86400,
|
318
|
+
# public: true, immutable: true
|
319
|
+
|
320
|
+
# get "/:file" do |req|
|
321
|
+
# file_name = req.params["file"]
|
322
|
+
# req.respond("Pretending to serve #{file_name} with long-lived caching")
|
323
|
+
# end
|
324
|
+
# end
|
325
|
+
|
326
|
+
# # location '' do
|
327
|
+
|
328
|
+
# location '/spa' do
|
329
|
+
# # Serve static files from the "public/assets" directory
|
330
|
+
# log_requests before: { format: "REQUEST_ID={request_id} METHOD={method} PATH={path} QUERY={query} HOST={host} PORT={port} START_TIME={start_time}" , level: 'INFO'}, after: { format: "REQUEST_ID={request_id} RESPONSE_TIME={response_time}", level: 'INFO' }
|
331
|
+
# allow_list allowed_patterns: [/127.*/], error_response: { plaintext: 'no way', code: 401, default: 'plaintext' }
|
332
|
+
# static_assets\
|
333
|
+
# relative_path: true,
|
334
|
+
# root_dir: 'spa/dist',
|
335
|
+
# # # Only allow certain file extensions
|
336
|
+
# # allowed_extensions: %w[css js jpg jpeg png gif svg ico woff woff2 ttf
|
337
|
+
# # otf html],
|
338
|
+
# # Return a 404 error if file is not found
|
339
|
+
# not_found_behavior: { index: 'index.html' },
|
340
|
+
# # Enable auto-indexing of directories
|
341
|
+
# auto_index: true,
|
342
|
+
# # Try adding .html extension to extensionless URLs
|
343
|
+
# try_html_extension: true,
|
344
|
+
# # Files under this size are cached in memory
|
345
|
+
# max_file_size_in_memory: 1024 * 1024, # 1MB
|
346
|
+
# # Maximum number of files to keep in memory cache
|
347
|
+
# max_files_in_memory: 1000,
|
348
|
+
# # Check for file modifications every 5 seconds
|
349
|
+
# file_check_interval: 5,
|
350
|
+
# # Add custom headers to all responses
|
351
|
+
# headers: {
|
352
|
+
# 'Cache-Control' => 'public, max-age=86400',
|
353
|
+
# 'X-Content-Type-Options' => 'nosniff'
|
354
|
+
# }
|
355
|
+
# compress algorithms: ['zstd'], min_size: 0, compress_streams: true, mime_types: ['all'], level: 'fastest'
|
356
|
+
# end
|
148
357
|
# end
|
149
358
|
|
150
359
|
# location "/cors_test" do
|
@@ -154,17 +363,7 @@ end
|
|
154
363
|
# end
|
155
364
|
# end
|
156
365
|
|
157
|
-
# location "/basic" do
|
158
|
-
# auth_basic realm: 'My Realm', credential_pairs: { 'user' => 'password' }
|
159
|
-
# end
|
160
366
|
|
161
|
-
# location "/jwt" do
|
162
|
-
# auth_jwt token_source: { header: { name: 'Authorization', prefix: 'Bearer ' } }, verifiers: {'hs256' => ["1V6nZzztO/F6Y3XAYXJ1I37AAXCJ/V7EVHJoVnD8lr4="]
|
163
|
-
# }, error_response: { code: 401, plaintext: 'Unauthorized', default: 'plaintext' }
|
164
|
-
# get "/" do |req|
|
165
|
-
# req.respond('Hello, JWT user!')
|
166
|
-
# end
|
167
|
-
# end
|
168
367
|
|
169
368
|
# location '/proxy_as_foo_com' do
|
170
369
|
# compress algorithms: ['zstd'], min_size: 0, compress_streams: true, mime_types: ['all'], level: 'fastest'
|
@@ -229,7 +428,6 @@ end
|
|
229
428
|
# req.respond("This is a test")
|
230
429
|
# end
|
231
430
|
|
232
|
-
|
233
431
|
# location '*', protocols: :http do
|
234
432
|
# location 'foo' do
|
235
433
|
# redirect to: 'https://{host}:3001{path}'
|
@@ -272,5 +470,4 @@ end
|
|
272
470
|
|
273
471
|
# Example with both caching and ETags
|
274
472
|
|
275
|
-
|
276
473
|
# Simple ETag test endpoint with predictable content
|
@@ -0,0 +1 @@
|
|
1
|
+
{"message": "Hello, World!"}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
colorize (0.8.1)
|
5
|
+
google-protobuf (3.25.6)
|
6
|
+
googleapis-common-protos-types (1.19.0)
|
7
|
+
google-protobuf (>= 3.18, < 5.a)
|
8
|
+
grpc (1.71.0)
|
9
|
+
google-protobuf (>= 3.25, < 5.0)
|
10
|
+
googleapis-common-protos-types (~> 1.0)
|
11
|
+
grpc (1.71.0-arm64-darwin)
|
12
|
+
google-protobuf (>= 3.25, < 5.0)
|
13
|
+
googleapis-common-protos-types (~> 1.0)
|
14
|
+
grpc-tools (1.71.0)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
arm64-darwin-23
|
18
|
+
ruby
|
19
|
+
|
20
|
+
DEPENDENCIES
|
21
|
+
colorize (~> 0.8.1)
|
22
|
+
google-protobuf (~> 3.21)
|
23
|
+
grpc (~> 1.50)
|
24
|
+
grpc-tools (~> 1.50)
|
25
|
+
|
26
|
+
BUNDLED WITH
|
27
|
+
2.6.3
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Echo gRPC Client
|
2
|
+
|
3
|
+
A simple Ruby gRPC client for the Echo service.
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
1. Install dependencies:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
bundle install
|
11
|
+
```
|
12
|
+
|
13
|
+
2. Generate Ruby code from the proto file:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
./gen_proto.sh
|
17
|
+
```
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Run the client with optional compression:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
# Run without compression (default)
|
25
|
+
ruby echo_client.rb
|
26
|
+
|
27
|
+
# Run with gzip compression
|
28
|
+
ruby echo_client.rb gzip
|
29
|
+
|
30
|
+
# Run with deflate compression
|
31
|
+
ruby echo_client.rb deflate
|
32
|
+
|
33
|
+
# Show help
|
34
|
+
ruby echo_client.rb help
|
35
|
+
```
|
36
|
+
|
37
|
+
## Client Details
|
38
|
+
|
39
|
+
This client implements all four types of gRPC methods:
|
40
|
+
|
41
|
+
1. Unary RPC (`echo`)
|
42
|
+
2. Server streaming RPC (`echo_stream`)
|
43
|
+
3. Client streaming RPC (`echo_collect`)
|
44
|
+
4. Bidirectional streaming RPC (`echo_bidirectional`)
|
45
|
+
|
46
|
+
## Compression Options
|
47
|
+
|
48
|
+
You can control compression by modifying the client initialization in `echo_client.rb`:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# No compression
|
52
|
+
client = EchoClient.new('localhost', 50051, compression: nil)
|
53
|
+
|
54
|
+
# Gzip compression
|
55
|
+
client = EchoClient.new('localhost', 50051, compression: :gzip)
|
56
|
+
|
57
|
+
# Deflate compression
|
58
|
+
client = EchoClient.new('localhost', 50051, compression: :deflate)
|
59
|
+
```
|
60
|
+
|
61
|
+
The compression settings are implemented using the gRPC channel arguments, which allows you to test different compression algorithms.
|
62
|
+
|
63
|
+
## Troubleshooting
|
64
|
+
|
65
|
+
If you encounter any issues:
|
66
|
+
|
67
|
+
1. Make sure you have installed all dependencies with `bundle install`
|
68
|
+
2. Ensure the protocol buffer code has been generated with `./gen_proto.sh`
|
69
|
+
3. Check that the gRPC server is running on the specified host and port
|
70
|
+
4. If you see connectivity issues, try running with debugging enabled:
|
71
|
+
|
72
|
+
```bash
|
73
|
+
GRPC_VERBOSITY=DEBUG GRPC_TRACE=all ruby echo_client.rb
|
74
|
+
```
|
75
|
+
|
76
|
+
## Example Server
|
77
|
+
|
78
|
+
The client is designed to work with the EchoService server in the `../echo_service_nonitsi` directory. Make sure the server is running before starting the client.
|
79
|
+
|
80
|
+
## Compression Testing
|
81
|
+
|
82
|
+
To test different compression algorithms with the same message payload:
|
83
|
+
|
84
|
+
```bash
|
85
|
+
# Test without compression
|
86
|
+
./run_client.rb -m "Large message repeated many times" -c none
|
87
|
+
|
88
|
+
# Test with gzip compression
|
89
|
+
./run_client.rb -m "Large message repeated many times" -c gzip
|
90
|
+
|
91
|
+
# Test with deflate compression
|
92
|
+
./run_client.rb -m "Large message repeated many times" -c deflate
|
93
|
+
```
|
94
|
+
|
95
|
+
This allows you to compare the performance and behavior with different compression settings.
|