itsi 0.2.15 → 0.2.17

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.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/Cargo.lock +76 -74
  4. data/crates/itsi_acme/Cargo.toml +1 -1
  5. data/crates/itsi_scheduler/Cargo.toml +1 -1
  6. data/crates/itsi_scheduler/extconf.rb +3 -1
  7. data/crates/itsi_server/Cargo.lock +1 -1
  8. data/crates/itsi_server/Cargo.toml +3 -1
  9. data/crates/itsi_server/extconf.rb +3 -1
  10. data/crates/itsi_server/src/lib.rs +7 -1
  11. data/crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +2 -0
  12. data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +6 -6
  13. data/crates/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +14 -13
  14. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +71 -42
  15. data/crates/itsi_server/src/ruby_types/itsi_http_response.rs +151 -152
  16. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +6 -15
  17. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +32 -6
  18. data/crates/itsi_server/src/ruby_types/itsi_server.rs +1 -1
  19. data/crates/itsi_server/src/server/binds/listener.rs +49 -8
  20. data/crates/itsi_server/src/server/frame_stream.rs +142 -0
  21. data/crates/itsi_server/src/server/http_message_types.rs +143 -10
  22. data/crates/itsi_server/src/server/io_stream.rs +28 -5
  23. data/crates/itsi_server/src/server/lifecycle_event.rs +1 -1
  24. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +2 -3
  25. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +8 -10
  26. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +2 -3
  27. data/crates/itsi_server/src/server/middleware_stack/middlewares/csp.rs +3 -3
  28. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +54 -58
  29. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +6 -9
  30. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +27 -42
  31. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
  32. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
  33. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +8 -11
  34. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
  35. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +2 -3
  36. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
  37. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +1 -2
  38. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +13 -6
  39. data/crates/itsi_server/src/server/mod.rs +1 -0
  40. data/crates/itsi_server/src/server/process_worker.rs +5 -5
  41. data/crates/itsi_server/src/server/serve_strategy/acceptor.rs +100 -0
  42. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +87 -31
  43. data/crates/itsi_server/src/server/serve_strategy/mod.rs +1 -0
  44. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +166 -206
  45. data/crates/itsi_server/src/server/signal.rs +37 -9
  46. data/crates/itsi_server/src/server/thread_worker.rs +92 -70
  47. data/crates/itsi_server/src/services/itsi_http_service.rs +67 -62
  48. data/crates/itsi_server/src/services/mime_types.rs +185 -183
  49. data/crates/itsi_server/src/services/rate_limiter.rs +16 -34
  50. data/crates/itsi_server/src/services/static_file_server.rs +35 -60
  51. data/docs/benchmark-dashboard/.gitignore +27 -0
  52. data/docs/benchmark-dashboard/app/api/benchmarks/route.ts +22 -0
  53. data/docs/benchmark-dashboard/app/globals.css +94 -0
  54. data/docs/benchmark-dashboard/app/layout.tsx +20 -0
  55. data/docs/benchmark-dashboard/app/page.tsx +252 -0
  56. data/docs/benchmark-dashboard/components/benchmark-dashboard.tsx +1663 -0
  57. data/docs/benchmark-dashboard/components/theme-provider.tsx +11 -0
  58. data/docs/benchmark-dashboard/components/ui/accordion.tsx +58 -0
  59. data/docs/benchmark-dashboard/components/ui/alert-dialog.tsx +141 -0
  60. data/docs/benchmark-dashboard/components/ui/alert.tsx +59 -0
  61. data/docs/benchmark-dashboard/components/ui/aspect-ratio.tsx +7 -0
  62. data/docs/benchmark-dashboard/components/ui/avatar.tsx +50 -0
  63. data/docs/benchmark-dashboard/components/ui/badge.tsx +36 -0
  64. data/docs/benchmark-dashboard/components/ui/breadcrumb.tsx +115 -0
  65. data/docs/benchmark-dashboard/components/ui/button.tsx +56 -0
  66. data/docs/benchmark-dashboard/components/ui/calendar.tsx +66 -0
  67. data/docs/benchmark-dashboard/components/ui/card.tsx +79 -0
  68. data/docs/benchmark-dashboard/components/ui/carousel.tsx +262 -0
  69. data/docs/benchmark-dashboard/components/ui/chart.tsx +365 -0
  70. data/docs/benchmark-dashboard/components/ui/checkbox.tsx +30 -0
  71. data/docs/benchmark-dashboard/components/ui/collapsible.tsx +11 -0
  72. data/docs/benchmark-dashboard/components/ui/command.tsx +153 -0
  73. data/docs/benchmark-dashboard/components/ui/context-menu.tsx +200 -0
  74. data/docs/benchmark-dashboard/components/ui/dialog.tsx +122 -0
  75. data/docs/benchmark-dashboard/components/ui/drawer.tsx +118 -0
  76. data/docs/benchmark-dashboard/components/ui/dropdown-menu.tsx +200 -0
  77. data/docs/benchmark-dashboard/components/ui/form.tsx +178 -0
  78. data/docs/benchmark-dashboard/components/ui/hover-card.tsx +29 -0
  79. data/docs/benchmark-dashboard/components/ui/input-otp.tsx +71 -0
  80. data/docs/benchmark-dashboard/components/ui/input.tsx +22 -0
  81. data/docs/benchmark-dashboard/components/ui/label.tsx +26 -0
  82. data/docs/benchmark-dashboard/components/ui/loading-spinner.tsx +12 -0
  83. data/docs/benchmark-dashboard/components/ui/menubar.tsx +236 -0
  84. data/docs/benchmark-dashboard/components/ui/navigation-menu.tsx +128 -0
  85. data/docs/benchmark-dashboard/components/ui/pagination.tsx +117 -0
  86. data/docs/benchmark-dashboard/components/ui/popover.tsx +31 -0
  87. data/docs/benchmark-dashboard/components/ui/progress.tsx +28 -0
  88. data/docs/benchmark-dashboard/components/ui/radio-group.tsx +44 -0
  89. data/docs/benchmark-dashboard/components/ui/resizable.tsx +45 -0
  90. data/docs/benchmark-dashboard/components/ui/scroll-area.tsx +48 -0
  91. data/docs/benchmark-dashboard/components/ui/select.tsx +160 -0
  92. data/docs/benchmark-dashboard/components/ui/separator.tsx +31 -0
  93. data/docs/benchmark-dashboard/components/ui/sheet.tsx +140 -0
  94. data/docs/benchmark-dashboard/components/ui/sidebar.tsx +763 -0
  95. data/docs/benchmark-dashboard/components/ui/skeleton.tsx +15 -0
  96. data/docs/benchmark-dashboard/components/ui/slider.tsx +28 -0
  97. data/docs/benchmark-dashboard/components/ui/sonner.tsx +31 -0
  98. data/docs/benchmark-dashboard/components/ui/switch.tsx +29 -0
  99. data/docs/benchmark-dashboard/components/ui/table.tsx +117 -0
  100. data/docs/benchmark-dashboard/components/ui/tabs.tsx +55 -0
  101. data/docs/benchmark-dashboard/components/ui/textarea.tsx +22 -0
  102. data/docs/benchmark-dashboard/components/ui/toast.tsx +129 -0
  103. data/docs/benchmark-dashboard/components/ui/toaster.tsx +35 -0
  104. data/docs/benchmark-dashboard/components/ui/toggle-group.tsx +61 -0
  105. data/docs/benchmark-dashboard/components/ui/toggle.tsx +45 -0
  106. data/docs/benchmark-dashboard/components/ui/tooltip.tsx +30 -0
  107. data/docs/benchmark-dashboard/components/ui/use-mobile.tsx +19 -0
  108. data/docs/benchmark-dashboard/components/ui/use-toast.ts +194 -0
  109. data/docs/benchmark-dashboard/components.json +21 -0
  110. data/docs/benchmark-dashboard/dist/benchmark-dashboard.css +1 -0
  111. data/docs/benchmark-dashboard/dist/benchmark-dashboard.iife.js +211 -0
  112. data/docs/benchmark-dashboard/dist/placeholder-logo.png +0 -0
  113. data/docs/benchmark-dashboard/dist/placeholder-logo.svg +1 -0
  114. data/docs/benchmark-dashboard/dist/placeholder-user.jpg +0 -0
  115. data/docs/benchmark-dashboard/dist/placeholder.jpg +0 -0
  116. data/docs/benchmark-dashboard/dist/placeholder.svg +1 -0
  117. data/docs/benchmark-dashboard/embed.tsx +13 -0
  118. data/docs/benchmark-dashboard/hooks/use-mobile.tsx +19 -0
  119. data/docs/benchmark-dashboard/hooks/use-toast.ts +194 -0
  120. data/docs/benchmark-dashboard/lib/benchmark-utils.ts +54 -0
  121. data/docs/benchmark-dashboard/lib/utils.ts +6 -0
  122. data/docs/benchmark-dashboard/next.config.mjs +14 -0
  123. data/docs/benchmark-dashboard/package-lock.json +5859 -0
  124. data/docs/benchmark-dashboard/package.json +72 -0
  125. data/docs/benchmark-dashboard/pnpm-lock.yaml +5 -0
  126. data/docs/benchmark-dashboard/postcss.config.mjs +8 -0
  127. data/docs/benchmark-dashboard/styles/globals.css +94 -0
  128. data/docs/benchmark-dashboard/tailwind.config.ts +96 -0
  129. data/docs/benchmark-dashboard/tsconfig.json +27 -0
  130. data/docs/benchmark-dashboard/vite.config.ts +24 -0
  131. data/docs/build.rb +52 -0
  132. data/docs/content/benchmarks/index.md +96 -0
  133. data/docs/content/features/_index.md +1 -1
  134. data/docs/content/getting_started/_index.md +76 -46
  135. data/docs/hugo.yaml +3 -0
  136. data/docs/static/results.json +1 -0
  137. data/docs/static/scripts/benchmark-dashboard.iife.js +211 -0
  138. data/docs/static/styles/benchmark-dashboard.css +1 -0
  139. data/examples/rails_with_static_assets/Gemfile.lock +1 -1
  140. data/examples/rails_with_static_assets/Itsi.rb +4 -1
  141. data/gems/scheduler/Cargo.lock +15 -15
  142. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  143. data/gems/server/Cargo.lock +75 -73
  144. data/gems/server/exe/itsi +6 -1
  145. data/gems/server/lib/itsi/http_request.rb +31 -39
  146. data/gems/server/lib/itsi/http_response.rb +5 -0
  147. data/gems/server/lib/itsi/rack_env_pool.rb +59 -0
  148. data/gems/server/lib/itsi/server/config/config_helpers.rb +1 -2
  149. data/gems/server/lib/itsi/server/config/dsl.rb +5 -4
  150. data/gems/server/lib/itsi/server/config/middleware/etag.md +3 -7
  151. data/gems/server/lib/itsi/server/config/middleware/etag.rb +2 -4
  152. data/gems/server/lib/itsi/server/config/middleware/proxy.rb +1 -1
  153. data/gems/server/lib/itsi/server/config/middleware/rackup_file.rb +2 -2
  154. data/gems/server/lib/itsi/server/config/options/auto_reload_config.rb +6 -2
  155. data/gems/server/lib/itsi/server/config/options/include.rb +5 -2
  156. data/gems/server/lib/itsi/server/config/options/listen_backlog.rb +1 -1
  157. data/gems/server/lib/itsi/server/config/options/pipeline_flush.md +16 -0
  158. data/gems/server/lib/itsi/server/config/options/pipeline_flush.rb +19 -0
  159. data/gems/server/lib/itsi/server/config/options/send_buffer_size.md +15 -0
  160. data/gems/server/lib/itsi/server/config/options/send_buffer_size.rb +19 -0
  161. data/gems/server/lib/itsi/server/config/options/writev.md +25 -0
  162. data/gems/server/lib/itsi/server/config/options/writev.rb +19 -0
  163. data/gems/server/lib/itsi/server/config.rb +43 -31
  164. data/gems/server/lib/itsi/server/default_config/Itsi.rb +1 -4
  165. data/gems/server/lib/itsi/server/grpc/grpc_call.rb +2 -0
  166. data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +2 -2
  167. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +3 -1
  168. data/gems/server/lib/itsi/server/rack_interface.rb +17 -12
  169. data/gems/server/lib/itsi/server/route_tester.rb +1 -1
  170. data/gems/server/lib/itsi/server/scheduler_interface.rb +2 -0
  171. data/gems/server/lib/itsi/server/version.rb +1 -1
  172. data/gems/server/lib/itsi/server.rb +1 -0
  173. data/gems/server/lib/ruby_lsp/itsi/addon.rb +12 -13
  174. data/gems/server/test/helpers/test_helper.rb +12 -13
  175. data/gems/server/test/middleware/etag.rb +3 -3
  176. data/gems/server/test/middleware/grpc/grpc.rb +13 -14
  177. data/gems/server/test/middleware/grpc/test_service_impl.rb +3 -3
  178. data/gems/server/test/middleware/proxy.rb +262 -268
  179. data/gems/server/test/options/ruby_thread_request_backlog_size.rb +2 -3
  180. data/lib/itsi/version.rb +1 -1
  181. metadata +99 -6
  182. data/tasks.txt +0 -27
@@ -1,16 +1,14 @@
1
1
  require_relative "../helpers/test_helper"
2
2
 
3
3
  class TestProxy < Minitest::Test
4
-
5
4
  def test_successful_forwarding
6
-
7
5
  backend_bind = free_bind
8
6
  server(
9
7
  itsi_rb: lambda do
10
- log_requests before: { format: "GET {path_and_query}", level: "INFO"}
11
- get("/foo") { |r|
8
+ log_requests before: { format: "GET {path_and_query}", level: "INFO" }
9
+ get("/foo") do |r|
12
10
  r.ok "backend success. #{r.query_params["bar"]}"
13
- }
11
+ end
14
12
  end,
15
13
  bind: backend_bind
16
14
  ) do
@@ -25,9 +23,9 @@ class TestProxy < Minitest::Test
25
23
  timeout: 30,
26
24
  tls_sni: false,
27
25
  error_response: "internal_server_error"
28
- get("/foo") { |r|
26
+ get("/foo") do |r|
29
27
  r.ok "should not get here"
30
- }
28
+ end
31
29
  end
32
30
  ) do
33
31
  res = get_resp("/foo?bar=baz")
@@ -60,11 +58,10 @@ class TestProxy < Minitest::Test
60
58
  end
61
59
 
62
60
  def test_overriding_headers
63
-
64
61
  backend_bind = free_bind
65
62
  server(
66
63
  itsi_rb: lambda do
67
- log_requests before: { format: "GET {path_and_query}", level: "INFO"}
64
+ log_requests before: { format: "GET {path_and_query}", level: "INFO" }
68
65
  get("/header-test") do |r|
69
66
  # Return the incoming header value.
70
67
  r.ok r.header("X-Forwarded-For").first
@@ -72,7 +69,6 @@ class TestProxy < Minitest::Test
72
69
  end,
73
70
  bind: backend_bind
74
71
  ) do
75
-
76
72
  # Start proxy server.
77
73
  server(
78
74
  itsi_rb: lambda do
@@ -96,278 +92,279 @@ class TestProxy < Minitest::Test
96
92
  end
97
93
 
98
94
  def test_proxy_with_static_to_only
99
- backend_bind = free_bind
100
- server(
101
- itsi_rb: lambda do
102
- get("/static") { |r| r.ok "static response" }
103
- end,
104
- bind: backend_bind
105
- ) do
106
- server(
107
- itsi_rb: lambda do
108
- proxy \
109
- to: "#{backend_bind}{path}{query}",
110
- backend_priority: "round_robin",
111
- headers: {},
112
- verify_ssl: false,
113
- timeout: 30,
114
- tls_sni: false,
115
- error_response: "internal_server_error"
116
- get("/static") { |r| r.ok "should not get here" }
117
- end
118
- ) do
119
- res = get_resp("/static")
120
- assert_equal "200", res.code, "Expected success status from static 'to' URL"
121
- assert_equal "static response", res.body
122
- end
123
- end
124
- end
95
+ backend_bind = free_bind
96
+ server(
97
+ itsi_rb: lambda do
98
+ get("/static") { |r| r.ok "static response" }
99
+ end,
100
+ bind: backend_bind
101
+ ) do
102
+ server(
103
+ itsi_rb: lambda do
104
+ proxy \
105
+ to: "#{backend_bind}{path}{query}",
106
+ backend_priority: "round_robin",
107
+ headers: {},
108
+ verify_ssl: false,
109
+ timeout: 30,
110
+ tls_sni: false,
111
+ error_response: "internal_server_error"
112
+ get("/static") { |r| r.ok "should not get here" }
113
+ end
114
+ ) do
115
+ res = get_resp("/static")
116
+ assert_equal "200", res.code, "Expected success status from static 'to' URL"
117
+ assert_equal "static response", res.body
118
+ end
119
+ end
120
+ end
125
121
 
126
- def test_proxy_with_backend_host_override
127
- backend_bind1 = free_bind
128
- backend_bind2 = free_bind
129
- # Start two dummy backends that respond with their Host header.
130
- thread1 = Thread.new do
131
- server(
132
- itsi_rb: lambda do
133
- get("/host-test") { |r| r.ok r.header("Host").first }
134
- end,
135
- bind: backend_bind1
136
- ){ sleep 1 }
137
- end
138
- thread2 = Thread.new do
139
- server(
140
- itsi_rb: lambda do
141
- get("/host-test") { |r| r.ok r.header("Host").first }
142
- end,
143
- bind: backend_bind2
144
- ){ sleep 1 }
145
- end
122
+ def test_proxy_with_backend_host_override
123
+ backend_bind1 = free_bind
124
+ backend_bind2 = free_bind
125
+ # Start two dummy backends that respond with their Host header.
126
+ thread1 = Thread.new do
127
+ server(
128
+ itsi_rb: lambda do
129
+ get("/host-test") { |r| r.ok r.header("Host").first }
130
+ end,
131
+ bind: backend_bind1
132
+ ) { sleep 1 }
133
+ end
134
+ thread2 = Thread.new do
135
+ server(
136
+ itsi_rb: lambda do
137
+ get("/host-test") { |r| r.ok r.header("Host").first }
138
+ end,
139
+ bind: backend_bind2
140
+ ) { sleep 1 }
141
+ end
146
142
 
147
- sleep 0.1
143
+ sleep 0.1
148
144
 
149
- server(
150
- itsi_rb: lambda do
151
- proxy \
152
- to: "#{backend_bind1}{path}{query}",
153
- backends: ["#{backend_bind1}", "#{backend_bind2}"],
154
- backend_priority: "round_robin",
155
- headers: { "Host" => "custom.backend.example.com" },
156
- verify_ssl: false,
157
- timeout: 30,
158
- tls_sni: true,
159
- error_response: "internal_server_error"
160
- get("/host-test") { |r| r.ok "should not get here" }
161
- end
162
- ) do
163
- res = get_resp("/host-test")
164
- assert_equal "200", res.code, "Expected successful response with host override"
165
- assert_equal "custom.backend.example.com", res.body, "Expected the Host header to be overridden"
166
- end
145
+ server(
146
+ itsi_rb: lambda do
147
+ proxy \
148
+ to: "#{backend_bind1}{path}{query}",
149
+ backends: ["#{backend_bind1}", "#{backend_bind2}"],
150
+ backend_priority: "round_robin",
151
+ headers: { "Host" => "custom.backend.example.com" },
152
+ verify_ssl: false,
153
+ timeout: 30,
154
+ tls_sni: true,
155
+ error_response: "internal_server_error"
156
+ get("/host-test") { |r| r.ok "should not get here" }
157
+ end
158
+ ) do
159
+ res = get_resp("/host-test")
160
+ assert_equal "200", res.code, "Expected successful response with host override"
161
+ assert_equal "custom.backend.example.com", res.body, "Expected the Host header to be overridden"
162
+ end
167
163
 
168
- thread1.kill
169
- thread2.kill
170
- end
164
+ thread1.kill
165
+ thread2.kill
166
+ end
171
167
 
172
- def test_proxy_timeout
173
- backend_bind = free_bind
174
- # Start a backend server that sleeps for 1 second before responding.
175
- server(
176
- itsi_rb: lambda do
177
- get("/slow") do |r|
178
- sleep 1
179
- r.ok "delayed response"
180
- end
181
- end,
182
- bind: backend_bind
183
- ) do
184
- server(
185
- itsi_rb: lambda do
186
- # Set a very short timeout (0 seconds) to force a timeout.
187
- proxy \
188
- to: "#{backend_bind}{path}{query}",
189
- backends: ["#{backend_bind}"],
190
- backend_priority: "round_robin",
191
- headers: {},
192
- verify_ssl: false,
193
- timeout: 0,
194
- tls_sni: false,
195
- error_response: "gateway_timeout"
196
- get("/slow") { |r| r.ok "should not get here" }
197
- end
198
- ) do
199
- res = get_resp("/slow")
200
- assert_equal "504", res.code, "Expected 504 Gateway Timeout when backend response exceeds timeout"
201
- end
202
- end
203
- end
168
+ def test_proxy_timeout
169
+ backend_bind = free_bind
170
+ # Start a backend server that sleeps for 1 second before responding.
171
+ server(
172
+ itsi_rb: lambda do
173
+ get("/slow") do |r|
174
+ sleep 1
175
+ r.ok "delayed response"
176
+ end
177
+ end,
178
+ bind: backend_bind
179
+ ) do
180
+ server(
181
+ itsi_rb: lambda do
182
+ # Set a very short timeout (0 seconds) to force a timeout.
183
+ proxy \
184
+ to: "#{backend_bind}{path}{query}",
185
+ backends: ["#{backend_bind}"],
186
+ backend_priority: "round_robin",
187
+ headers: {},
188
+ verify_ssl: false,
189
+ timeout: 0,
190
+ tls_sni: false,
191
+ error_response: "gateway_timeout"
192
+ get("/slow") { |r| r.ok "should not get here" }
193
+ end
194
+ ) do
195
+ res = get_resp("/slow")
196
+ assert_equal "504", res.code, "Expected 504 Gateway Timeout when backend response exceeds timeout"
197
+ end
198
+ end
199
+ end
204
200
 
205
- def test_error_response_internal_server_error
206
- server(
207
- itsi_rb: lambda do
208
- proxy \
209
- to: "invalid_url",
210
- backends: ["127.0.0.1:3001"],
211
- backend_priority: "round_robin",
212
- headers: {},
213
- verify_ssl: false,
214
- timeout: 30,
215
- tls_sni: false,
216
- error_response: "internal_server_error"
217
- get("/foo") { |r| r.ok "should not get here" }
218
- end
219
- ) do
220
- res = get_resp("/foo")
221
- assert_equal "500", res.code, "Expected error response code 500 for internal_server_error"
222
- end
223
- end
201
+ def test_error_response_internal_server_error
202
+ server(
203
+ itsi_rb: lambda do
204
+ proxy \
205
+ to: "invalid_url",
206
+ backends: ["127.0.0.1:3001"],
207
+ backend_priority: "round_robin",
208
+ headers: {},
209
+ verify_ssl: false,
210
+ timeout: 30,
211
+ tls_sni: false,
212
+ error_response: "internal_server_error"
213
+ get("/foo") { |r| r.ok "should not get here" }
214
+ end
215
+ ) do
216
+ res = get_resp("/foo")
217
+ assert_equal "500", res.code, "Expected error response code 500 for internal_server_error"
218
+ end
219
+ end
224
220
 
225
- def test_error_response_not_found
226
- server(
227
- itsi_rb: lambda do
228
- proxy \
229
- to: "invalid_url",
230
- backends: ["127.0.0.1:3001"],
231
- backend_priority: "round_robin",
232
- headers: {},
233
- verify_ssl: false,
234
- timeout: 30,
235
- tls_sni: false,
236
- error_response: "not_found"
237
- get("/foo") { |r| r.ok "should not get here" }
238
- end
239
- ) do
240
- res = get_resp("/foo")
241
- assert_equal "404", res.code, "Expected error response code 404 for not_found"
242
- end
243
- end
221
+ def test_error_response_not_found
222
+ server(
223
+ itsi_rb: lambda do
224
+ proxy \
225
+ to: "invalid_url",
226
+ backends: ["127.0.0.1:3001"],
227
+ backend_priority: "round_robin",
228
+ headers: {},
229
+ verify_ssl: false,
230
+ timeout: 30,
231
+ tls_sni: false,
232
+ error_response: "not_found"
233
+ get("/foo") { |r| r.ok "should not get here" }
234
+ end
235
+ ) do
236
+ res = get_resp("/foo")
237
+ assert_equal "404", res.code, "Expected error response code 404 for not_found"
238
+ end
239
+ end
244
240
 
245
- def test_error_response_unauthorized
246
- server(
247
- itsi_rb: lambda do
248
- proxy \
249
- to: "invalid_url",
250
- backends: ["127.0.0.1:3001"],
251
- backend_priority: "round_robin",
252
- headers: {},
253
- verify_ssl: false,
254
- timeout: 30,
255
- tls_sni: false,
256
- error_response: "unauthorized"
257
- get("/foo") { |r| r.ok "should not get here" }
258
- end
259
- ) do
260
- res = get_resp("/foo")
261
- assert_equal "401", res.code, "Expected error response code 401 for unauthorized"
262
- end
263
- end
241
+ def test_error_response_unauthorized
242
+ server(
243
+ itsi_rb: lambda do
244
+ proxy \
245
+ to: "invalid_url",
246
+ backends: ["127.0.0.1:3001"],
247
+ backend_priority: "round_robin",
248
+ headers: {},
249
+ verify_ssl: false,
250
+ timeout: 30,
251
+ tls_sni: false,
252
+ error_response: "unauthorized"
253
+ get("/foo") { |r| r.ok "should not get here" }
254
+ end
255
+ ) do
256
+ res = get_resp("/foo")
257
+ assert_equal "401", res.code, "Expected error response code 401 for unauthorized"
258
+ end
259
+ end
264
260
 
265
- def test_error_response_forbidden
266
- server(
267
- itsi_rb: lambda do
268
- proxy \
269
- to: "invalid_url",
270
- backends: ["127.0.0.1:3001"],
271
- backend_priority: "round_robin",
272
- headers: {},
273
- verify_ssl: false,
274
- timeout: 30,
275
- tls_sni: false,
276
- error_response: "forbidden"
277
- get("/foo") { |r| r.ok "should not get here" }
278
- end
279
- ) do
280
- res = get_resp("/foo")
281
- assert_equal "403", res.code, "Expected error response code 403 for forbidden"
282
- end
283
- end
261
+ def test_error_response_forbidden
262
+ server(
263
+ itsi_rb: lambda do
264
+ proxy \
265
+ to: "invalid_url",
266
+ backends: ["127.0.0.1:3001"],
267
+ backend_priority: "round_robin",
268
+ headers: {},
269
+ verify_ssl: false,
270
+ timeout: 30,
271
+ tls_sni: false,
272
+ error_response: "forbidden"
273
+ get("/foo") { |r| r.ok "should not get here" }
274
+ end
275
+ ) do
276
+ res = get_resp("/foo")
277
+ assert_equal "403", res.code, "Expected error response code 403 for forbidden"
278
+ end
279
+ end
284
280
 
285
- def test_error_response_payload_too_large
286
- server(
287
- itsi_rb: lambda do
288
- proxy \
289
- to: "invalid_url",
290
- backends: ["127.0.0.1:3001"],
291
- backend_priority: "round_robin",
292
- headers: {},
293
- verify_ssl: false,
294
- timeout: 30,
295
- tls_sni: false,
296
- error_response: "payload_too_large"
297
- get("/foo") { |r| r.ok "should not get here" }
298
- end
299
- ) do
300
- res = get_resp("/foo")
301
- assert_equal "413", res.code, "Expected error response code 413 for payload_too_large"
302
- end
303
- end
281
+ def test_error_response_payload_too_large
282
+ server(
283
+ itsi_rb: lambda do
284
+ proxy \
285
+ to: "invalid_url",
286
+ backends: ["127.0.0.1:3001"],
287
+ backend_priority: "round_robin",
288
+ headers: {},
289
+ verify_ssl: false,
290
+ timeout: 30,
291
+ tls_sni: false,
292
+ error_response: "payload_too_large"
293
+ get("/foo") { |r| r.ok "should not get here" }
294
+ end
295
+ ) do
296
+ res = get_resp("/foo")
297
+ assert_equal "413", res.code, "Expected error response code 413 for payload_too_large"
298
+ end
299
+ end
304
300
 
305
- def test_error_response_too_many_requests
306
- server(
307
- itsi_rb: lambda do
308
- proxy \
309
- to: "invalid_url",
310
- backends: ["127.0.0.1:3001"],
311
- backend_priority: "round_robin",
312
- headers: {},
313
- verify_ssl: false,
314
- timeout: 30,
315
- tls_sni: false,
316
- error_response: "too_many_requests"
317
- get("/foo") { |r| r.ok "should not get here" }
318
- end
319
- ) do
320
- res = get_resp("/foo")
321
- assert_equal "429", res.code, "Expected error response code 429 for too_many_requests"
322
- end
323
- end
301
+ def test_error_response_too_many_requests
302
+ server(
303
+ itsi_rb: lambda do
304
+ proxy \
305
+ to: "invalid_url",
306
+ backends: ["127.0.0.1:3001"],
307
+ backend_priority: "round_robin",
308
+ headers: {},
309
+ verify_ssl: false,
310
+ timeout: 30,
311
+ tls_sni: false,
312
+ error_response: "too_many_requests"
313
+ get("/foo") { |r| r.ok "should not get here" }
314
+ end
315
+ ) do
316
+ res = get_resp("/foo")
317
+ assert_equal "429", res.code, "Expected error response code 429 for too_many_requests"
318
+ end
319
+ end
324
320
 
325
- def test_error_response_service_unavailable
326
- server(
327
- itsi_rb: lambda do
328
- proxy \
329
- to: "invalid_url",
330
- backends: ["127.0.0.1:3001"],
331
- backend_priority: "round_robin",
332
- headers: {},
333
- verify_ssl: false,
334
- timeout: 30,
335
- tls_sni: false,
336
- error_response: "service_unavailable"
337
- get("/foo") { |r| r.ok "should not get here" }
338
- end
339
- ) do
340
- res = get_resp("/foo")
341
- assert_equal "503", res.code, "Expected error response code 503 for service_unavailable"
342
- end
343
- end
321
+ def test_error_response_service_unavailable
322
+ server(
323
+ itsi_rb: lambda do
324
+ proxy \
325
+ to: "invalid_url",
326
+ backends: ["127.0.0.1:3001"],
327
+ backend_priority: "round_robin",
328
+ headers: {},
329
+ verify_ssl: false,
330
+ timeout: 30,
331
+ tls_sni: false,
332
+ error_response: "service_unavailable"
333
+ get("/foo") { |r| r.ok "should not get here" }
334
+ end
335
+ ) do
336
+ res = get_resp("/foo")
337
+ assert_equal "503", res.code, "Expected error response code 503 for service_unavailable"
338
+ end
339
+ end
344
340
 
345
- def test_error_response_gateway_timeout
346
- server(
347
- itsi_rb: lambda do
348
- proxy \
349
- to: "invalid_url",
350
- backends: ["127.0.0.1:3001"],
351
- backend_priority: "round_robin",
352
- headers: {},
353
- verify_ssl: false,
354
- timeout: 30,
355
- tls_sni: false,
356
- error_response: "gateway_timeout"
357
- get("/foo") { |r| r.ok "should not get here" }
358
- end
359
- ) do
360
- res = get_resp("/foo")
361
- assert_equal "504", res.code, "Expected error response code 504 for gateway_timeout"
341
+ def test_error_response_gateway_timeout
342
+ server(
343
+ itsi_rb: lambda do
344
+ proxy \
345
+ to: "invalid_url",
346
+ backends: ["127.0.0.1:3001"],
347
+ backend_priority: "round_robin",
348
+ headers: {},
349
+ verify_ssl: false,
350
+ timeout: 30,
351
+ tls_sni: false,
352
+ error_response: "gateway_timeout"
353
+ get("/foo") { |r| r.ok "should not get here" }
354
+ end
355
+ ) do
356
+ res = get_resp("/foo")
357
+ assert_equal "504", res.code, "Expected error response code 504 for gateway_timeout"
362
358
  end
363
359
  end
364
360
 
365
- def test_failover_behavior
361
+ def test_failover_behavior # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
366
362
  # Obtain two free bind addresses for backend servers.
367
363
  backend1_bind = free_bind
368
364
  backend2_bind = free_bind
369
365
 
370
- backend2_server = Itsi::Server.start_in_background_thread(binds: [backend2_bind]) do
366
+ Itsi::Server.start_in_background_thread(binds: [backend2_bind]) do
367
+ workers 1
371
368
  get("/failover") { |r| r.ok "backend2" }
372
369
  end
373
370
 
@@ -376,14 +373,13 @@ class TestProxy < Minitest::Test
376
373
  # # Allow the backend servers to start.
377
374
  sleep 0.2
378
375
 
379
-
380
376
  # Start the proxy server with an ordered backend selection.
381
377
  server(
382
378
  cleanup: false,
383
379
  itsi_rb: lambda do
384
380
  proxy \
385
381
  to: "http://proxied_host.com{path}{query}",
386
- backends: [backend1_bind[/\/\/(.*)/,1], backend2_bind[/\/\/(.*)/,1]],
382
+ backends: [backend1_bind[%r{//(.*)}, 1], backend2_bind[%r{//(.*)}, 1]],
387
383
  backend_priority: "ordered",
388
384
  headers: {},
389
385
  verify_ssl: false,
@@ -393,18 +389,16 @@ class TestProxy < Minitest::Test
393
389
  get("/failover") { |r| r.ok "should not get here" }
394
390
  end
395
391
  ) do
396
-
397
-
398
392
  res = get_resp("/failover")
399
393
  assert_equal "200", res.code, "Expected success when fallback backend is available"
400
394
  assert_equal "backend2", res.body, "Expected response from backend2"
401
395
 
402
- backend1_server = Itsi::Server.start_in_background_thread(binds: [backend1_bind]) do
396
+ Itsi::Server.start_in_background_thread(binds: [backend1_bind]) do
397
+ workers 1
403
398
  get("/failover") { |r| r.ok "backend1" }
404
399
  end
405
400
 
406
401
  sleep 1
407
-
408
402
  res = get_resp("/failover")
409
403
  assert_equal "200", res.code, "Expected reversion when primary becomes available"
410
404
  assert_equal "backend1", res.body, "Expected response from backend1 with ordered priority"
@@ -12,9 +12,8 @@ class TestRubyThreadRequestBacklogSize < Minitest::Test
12
12
  end) do
13
13
  responses = 10.times.map{ Thread.new{ get_resp("/foo") } }.map(&:value)
14
14
 
15
- assert_equal "ok", responses.first.body
16
- assert_equal "200", responses.first.code
17
- assert_equal "503", responses.last.code
15
+ assert responses.map(&:code).include?("200")
16
+ assert responses.map(&:code).include?("503")
18
17
  end
19
18
  end
20
19
 
data/lib/itsi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Itsi
2
- VERSION = '0.2.15'
2
+ VERSION = '0.2.17'
3
3
  end