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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +124 -109
  3. data/Cargo.toml +6 -0
  4. data/crates/itsi_error/Cargo.toml +1 -0
  5. data/crates/itsi_error/src/lib.rs +100 -10
  6. data/crates/itsi_scheduler/src/itsi_scheduler.rs +1 -1
  7. data/crates/itsi_server/Cargo.toml +8 -10
  8. data/crates/itsi_server/src/default_responses/html/401.html +68 -0
  9. data/crates/itsi_server/src/default_responses/html/403.html +68 -0
  10. data/crates/itsi_server/src/default_responses/html/404.html +68 -0
  11. data/crates/itsi_server/src/default_responses/html/413.html +71 -0
  12. data/crates/itsi_server/src/default_responses/html/429.html +68 -0
  13. data/crates/itsi_server/src/default_responses/html/500.html +71 -0
  14. data/crates/itsi_server/src/default_responses/html/502.html +71 -0
  15. data/crates/itsi_server/src/default_responses/html/503.html +68 -0
  16. data/crates/itsi_server/src/default_responses/html/504.html +69 -0
  17. data/crates/itsi_server/src/default_responses/html/index.html +238 -0
  18. data/crates/itsi_server/src/default_responses/json/401.json +6 -0
  19. data/crates/itsi_server/src/default_responses/json/403.json +6 -0
  20. data/crates/itsi_server/src/default_responses/json/404.json +6 -0
  21. data/crates/itsi_server/src/default_responses/json/413.json +6 -0
  22. data/crates/itsi_server/src/default_responses/json/429.json +6 -0
  23. data/crates/itsi_server/src/default_responses/json/500.json +6 -0
  24. data/crates/itsi_server/src/default_responses/json/502.json +6 -0
  25. data/crates/itsi_server/src/default_responses/json/503.json +6 -0
  26. data/crates/itsi_server/src/default_responses/json/504.json +6 -0
  27. data/crates/itsi_server/src/default_responses/mod.rs +11 -0
  28. data/crates/itsi_server/src/lib.rs +58 -26
  29. data/crates/itsi_server/src/prelude.rs +2 -0
  30. data/crates/itsi_server/src/ruby_types/README.md +21 -0
  31. data/crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +8 -6
  32. data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  33. data/crates/itsi_server/src/ruby_types/{itsi_grpc_stream → itsi_grpc_response_stream}/mod.rs +121 -73
  34. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +103 -40
  35. data/crates/itsi_server/src/ruby_types/itsi_http_response.rs +8 -5
  36. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +4 -4
  37. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +37 -17
  38. data/crates/itsi_server/src/ruby_types/itsi_server.rs +4 -3
  39. data/crates/itsi_server/src/ruby_types/mod.rs +6 -13
  40. data/crates/itsi_server/src/server/{bind.rs → binds/bind.rs} +23 -4
  41. data/crates/itsi_server/src/server/{listener.rs → binds/listener.rs} +24 -10
  42. data/crates/itsi_server/src/server/binds/mod.rs +4 -0
  43. data/crates/itsi_server/src/server/{tls.rs → binds/tls.rs} +9 -4
  44. data/crates/itsi_server/src/server/http_message_types.rs +97 -0
  45. data/crates/itsi_server/src/server/io_stream.rs +2 -1
  46. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +28 -16
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +17 -8
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +47 -18
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +13 -9
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +50 -29
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +5 -2
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +37 -48
  53. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +25 -20
  54. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +14 -7
  55. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  56. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +125 -95
  57. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +9 -5
  58. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +1 -4
  59. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +25 -19
  60. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +4 -4
  61. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  62. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +9 -4
  63. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +260 -62
  64. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +29 -22
  65. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +6 -6
  66. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +6 -5
  67. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +4 -2
  68. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +51 -18
  69. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +31 -13
  70. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  71. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +13 -8
  72. data/crates/itsi_server/src/server/middleware_stack/mod.rs +101 -69
  73. data/crates/itsi_server/src/server/mod.rs +3 -9
  74. data/crates/itsi_server/src/server/process_worker.rs +21 -3
  75. data/crates/itsi_server/src/server/request_job.rs +2 -2
  76. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +8 -3
  77. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +26 -26
  78. data/crates/itsi_server/src/server/signal.rs +24 -41
  79. data/crates/itsi_server/src/server/size_limited_incoming.rs +101 -0
  80. data/crates/itsi_server/src/server/thread_worker.rs +59 -28
  81. data/crates/itsi_server/src/services/itsi_http_service.rs +239 -0
  82. data/crates/itsi_server/src/services/mime_types.rs +1416 -0
  83. data/crates/itsi_server/src/services/mod.rs +6 -0
  84. data/crates/itsi_server/src/services/password_hasher.rs +83 -0
  85. data/crates/itsi_server/src/{server → services}/rate_limiter.rs +35 -31
  86. data/crates/itsi_server/src/{server → services}/static_file_server.rs +521 -181
  87. data/crates/itsi_tracing/src/lib.rs +145 -55
  88. data/{Itsi.rb → foo/Itsi.rb} +6 -9
  89. data/gems/scheduler/Cargo.lock +7 -0
  90. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  91. data/gems/scheduler/test/helpers/test_helper.rb +0 -1
  92. data/gems/scheduler/test/test_address_resolve.rb +0 -1
  93. data/gems/scheduler/test/test_network_io.rb +1 -1
  94. data/gems/scheduler/test/test_process_wait.rb +0 -1
  95. data/gems/server/Cargo.lock +124 -109
  96. data/gems/server/exe/itsi +65 -19
  97. data/gems/server/itsi-server.gemspec +4 -3
  98. data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +74 -0
  99. data/gems/server/lib/itsi/http_request.rb +116 -17
  100. data/gems/server/lib/itsi/http_response.rb +2 -0
  101. data/gems/server/lib/itsi/passfile.rb +109 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +160 -101
  103. data/gems/server/lib/itsi/server/config.rb +58 -23
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +25 -29
  105. data/gems/server/lib/itsi/server/default_app/index.html +113 -89
  106. data/gems/server/lib/itsi/server/{Itsi.rb → default_config/Itsi-rackup.rb} +1 -1
  107. data/gems/server/lib/itsi/server/default_config/Itsi.rb +107 -0
  108. data/gems/server/lib/itsi/server/grpc/grpc_call.rb +246 -0
  109. data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +100 -0
  110. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  111. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  112. data/gems/server/lib/itsi/server/route_tester.rb +107 -0
  113. data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +200 -0
  114. data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +55 -0
  115. data/gems/server/lib/itsi/server/typed_handlers.rb +17 -0
  116. data/gems/server/lib/itsi/server/version.rb +1 -1
  117. data/gems/server/lib/itsi/server.rb +82 -12
  118. data/gems/server/lib/ruby_lsp/itsi/addon.rb +111 -0
  119. data/gems/server/lib/shell_completions/completions.rb +26 -0
  120. data/gems/server/test/helpers/test_helper.rb +2 -1
  121. data/lib/itsi/version.rb +1 -1
  122. data/sandbox/README.md +5 -0
  123. data/sandbox/itsi_file/Gemfile +4 -2
  124. data/sandbox/itsi_file/Gemfile.lock +48 -6
  125. data/sandbox/itsi_file/Itsi.rb +326 -129
  126. data/sandbox/itsi_file/call.json +1 -0
  127. data/sandbox/itsi_file/echo_client/Gemfile +10 -0
  128. data/sandbox/itsi_file/echo_client/Gemfile.lock +27 -0
  129. data/sandbox/itsi_file/echo_client/README.md +95 -0
  130. data/sandbox/itsi_file/echo_client/echo_client.rb +164 -0
  131. data/sandbox/itsi_file/echo_client/gen_proto.sh +17 -0
  132. data/sandbox/itsi_file/echo_client/lib/echo_pb.rb +16 -0
  133. data/sandbox/itsi_file/echo_client/lib/echo_services_pb.rb +29 -0
  134. data/sandbox/itsi_file/echo_client/run_client.rb +64 -0
  135. data/sandbox/itsi_file/echo_client/test_compressions.sh +20 -0
  136. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile +10 -0
  137. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile.lock +79 -0
  138. data/sandbox/itsi_file/echo_service_nonitsi/echo.proto +26 -0
  139. data/sandbox/itsi_file/echo_service_nonitsi/echo_pb.rb +16 -0
  140. data/sandbox/itsi_file/echo_service_nonitsi/echo_services_pb.rb +29 -0
  141. data/sandbox/itsi_file/echo_service_nonitsi/server.rb +52 -0
  142. data/sandbox/itsi_sandbox_async/config.ru +0 -1
  143. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  144. data/sandbox/itsi_sandbox_rails/Gemfile +2 -2
  145. data/sandbox/itsi_sandbox_rails/Gemfile.lock +76 -2
  146. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +15 -0
  147. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +1 -0
  148. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +1 -0
  149. data/sandbox/itsi_sandbox_rails/config/routes.rb +2 -0
  150. data/sandbox/itsi_sinatra/app.rb +0 -1
  151. data/sandbox/static_files/.env +1 -0
  152. data/sandbox/static_files/404.html +25 -0
  153. data/sandbox/static_files/_DSC0102.NEF.jpg +0 -0
  154. data/sandbox/static_files/about.html +68 -0
  155. data/sandbox/static_files/tiny.html +1 -0
  156. data/sandbox/static_files/writebook.zip +0 -0
  157. data/tasks.txt +28 -33
  158. metadata +87 -26
  159. data/crates/itsi_error/src/from.rs +0 -68
  160. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +0 -147
  161. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +0 -19
  162. data/crates/itsi_server/src/server/itsi_service.rs +0 -172
  163. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +0 -72
  164. data/crates/itsi_server/src/server/types.rs +0 -43
  165. data/gems/server/lib/itsi/server/grpc_interface.rb +0 -213
  166. data/sandbox/itsi_file/public/assets/index.html +0 -1
  167. /data/crates/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
  168. /data/crates/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +0 -0
  169. /data/crates/itsi_server/src/{server → services}/cache_store.rs +0 -0
@@ -0,0 +1,238 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{title}}</title>
7
+ <style>
8
+ :root {
9
+ --bg-color: #f0f2f5;
10
+ --text-color: #333;
11
+ --link-color: #0052cc;
12
+ --accent-color: #0052cc;
13
+ }
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+ body {
18
+ margin: 0;
19
+ font-family: "Helvetica Neue", Arial, sans-serif;
20
+ background: var(--bg-color);
21
+ color: var(--text-color);
22
+ padding: 2rem;
23
+ }
24
+ h1 {
25
+ font-size: 2.5rem;
26
+ margin-bottom: 1rem;
27
+ text-align: center;
28
+ }
29
+ table {
30
+ width: 100%;
31
+ border-collapse: collapse;
32
+ margin-top: 1rem;
33
+ }
34
+ th,
35
+ td {
36
+ padding: 0.5rem;
37
+ text-align: left;
38
+ }
39
+ tr:nth-child(even) {
40
+ background-color: #e9ecef;
41
+ }
42
+ th {
43
+ border-bottom: 2px solid #ccc;
44
+ position: relative;
45
+ cursor: pointer;
46
+ }
47
+ /* Sorted header arrow */
48
+ th .sort-arrow {
49
+ font-size: 0.8rem;
50
+ display: none;
51
+ }
52
+ th.sorted .sort-arrow {
53
+ display: inline;
54
+ }
55
+ a {
56
+ color: var(--link-color);
57
+ text-decoration: none;
58
+ }
59
+ a:hover {
60
+ text-decoration: underline;
61
+ }
62
+ .size {
63
+ text-align: right;
64
+ }
65
+ .date {
66
+ white-space: nowrap;
67
+ }
68
+ footer {
69
+ margin-top: 2rem;
70
+ text-align: center;
71
+ font-size: 0.9rem;
72
+ color: #555;
73
+ }
74
+ th.name-header > span {
75
+ display: inline-block;
76
+ width: 100%;
77
+ }
78
+ th.name-header input {
79
+ margin-top: 0.3rem;
80
+ font-size: 0.8rem;
81
+ width: 100%;
82
+ max-width: 200px;
83
+ border: 1px solid #ccc;
84
+ background: none;
85
+ border-radius: 12px;
86
+ padding: 5px 15px;
87
+ }
88
+ /* Responsive adjustments */
89
+ @media (max-width: 480px) {
90
+ h1 {
91
+ font-size: 2.5rem;
92
+ }
93
+ th,
94
+ td {
95
+ padding: 0.4rem;
96
+ }
97
+ th {
98
+ vertical-align: top;
99
+ }
100
+ th.name-header input {
101
+ max-width: 150px;
102
+ font-size: 0.75rem;
103
+ }
104
+ }
105
+ </style>
106
+ </head>
107
+ <body>
108
+ <h1>Directory listing for {{directory}}</h1>
109
+ <table data-sort-asc="true" data-sorted-column="0">
110
+ <thead>
111
+ <tr>
112
+ <th data-type="text" data-column="0" class="name-header">
113
+ <span>Name <span class="sort-arrow">▲</span></span>
114
+ <input type="text" id="nameFilter" placeholder="Filter names" />
115
+ </th>
116
+ <th data-type="size" data-column="1">
117
+ Size <span class="sort-arrow"></span>
118
+ </th>
119
+ <th data-type="text" data-column="2">
120
+ Last Modified <span class="sort-arrow"></span>
121
+ </th>
122
+ </tr>
123
+ </thead>
124
+ <tbody>
125
+ {{rows}}
126
+ </tbody>
127
+ </table>
128
+ <footer>
129
+ <p>Served by Itsi Static Assets</p>
130
+ </footer>
131
+ <script>
132
+ document.addEventListener("DOMContentLoaded", function () {
133
+ const table = document.querySelector("table");
134
+ const headers = table.querySelectorAll("th");
135
+ const nameFilter = document.getElementById("nameFilter");
136
+ let currentSortedColumn = 0;
137
+ let ascending = true;
138
+
139
+ // Add sorting listeners
140
+ headers.forEach((header, index) => {
141
+ header.addEventListener("click", function (e) {
142
+ // Prevent clicks on the filter input from triggering a sort.
143
+ if (e.target.tagName.toLowerCase() === "input") return;
144
+ sortTable(index);
145
+ updateSortArrows(index, ascending);
146
+ });
147
+ });
148
+
149
+ // Filter rows as the user types.
150
+ nameFilter.addEventListener("input", function () {
151
+ filterTable(this.value);
152
+ });
153
+
154
+ function sortTable(columnIndex) {
155
+ const tbody = table.querySelector("tbody");
156
+ let rows = Array.from(tbody.querySelectorAll("tr"));
157
+
158
+ // If sorting on a new column, default to ascending.
159
+ if (currentSortedColumn !== columnIndex) {
160
+ ascending = true;
161
+ currentSortedColumn = columnIndex;
162
+ } else {
163
+ ascending = !ascending;
164
+ }
165
+
166
+ rows.sort((a, b) => {
167
+ let aText = a.cells[columnIndex].textContent.trim().toLowerCase();
168
+ let bText = b.cells[columnIndex].textContent.trim().toLowerCase();
169
+
170
+ // If sorting the file size column, convert sizes to bytes.
171
+ if (headers[columnIndex].getAttribute("data-type") === "size") {
172
+ aText = parseSize(aText);
173
+ bText = parseSize(bText);
174
+ }
175
+
176
+ if (aText < bText) return ascending ? -1 : 1;
177
+ if (aText > bText) return ascending ? 1 : -1;
178
+ return 0;
179
+ });
180
+
181
+ rows.forEach((row) => tbody.appendChild(row));
182
+ table.setAttribute("data-sort-asc", ascending.toString());
183
+ table.setAttribute("data-sorted-column", columnIndex.toString());
184
+ }
185
+
186
+ function updateSortArrows(sortedIndex, ascending) {
187
+ headers.forEach((header, index) => {
188
+ header.classList.remove("sorted");
189
+ const arrow = header.querySelector(".sort-arrow");
190
+ if (index === sortedIndex) {
191
+ header.classList.add("sorted");
192
+ arrow.textContent = ascending ? "▲" : "▼";
193
+ } else {
194
+ arrow.textContent = "";
195
+ }
196
+ });
197
+ }
198
+
199
+ function filterTable(filterValue) {
200
+ const tbody = table.querySelector("tbody");
201
+ const rows = Array.from(tbody.querySelectorAll("tr"));
202
+ const lowerFilter = filterValue.toLowerCase();
203
+
204
+ rows.forEach((row) => {
205
+ const nameCell = row.cells[0];
206
+ row.style.display = nameCell.textContent
207
+ .toLowerCase()
208
+ .includes(lowerFilter)
209
+ ? ""
210
+ : "none";
211
+ });
212
+ }
213
+
214
+ // Parse file size string (e.g., "12.3 KB") into a number (bytes)
215
+ function parseSize(sizeStr) {
216
+ sizeStr = sizeStr.trim();
217
+ if (sizeStr === "-" || sizeStr === "") return 0;
218
+ const parts = sizeStr.split(" ");
219
+ if (parts.length < 2) return parseFloat(parts[0]);
220
+ const value = parseFloat(parts[0]);
221
+ const unit = parts[1].toLowerCase();
222
+ switch (unit) {
223
+ case "b":
224
+ return value;
225
+ case "kb":
226
+ return value * 1024;
227
+ case "mb":
228
+ return value * 1024 * 1024;
229
+ case "gb":
230
+ return value * 1024 * 1024 * 1024;
231
+ default:
232
+ return value;
233
+ }
234
+ }
235
+ });
236
+ </script>
237
+ </body>
238
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Unauthorized",
3
+ "message": "You are not authorized to access this resource.",
4
+ "code": 401,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Forbidden",
3
+ "message": "You are forbidden to access this resource.",
4
+ "code": 403,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Not Found",
3
+ "message": "The requested resource could not be found.",
4
+ "code": 404,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Payload Too Large",
3
+ "message": "The request entity is larger than the server is willing or able to process.",
4
+ "code": 413,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Too Many Requests",
3
+ "message": "Too many requests within a limited time frame.",
4
+ "code": 429,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Internal Server Error",
3
+ "message": "The server encountered an unexpected condition that prevented it from fulfilling the request.",
4
+ "code": 500,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Bad Gateway",
3
+ "message": "The server was acting as a gateway or proxy and received an invalid response from the upstream server.",
4
+ "code": 502,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Service Unavailable",
3
+ "message": "The server is currently unable to handle the request.",
4
+ "code": 503,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "error": "Gateway Timeout",
3
+ "message": "The server did not respond in time.",
4
+ "code": 504,
5
+ "status": "error"
6
+ }
@@ -0,0 +1,11 @@
1
+ use std::sync::LazyLock;
2
+
3
+ use crate::server::middleware_stack::ErrorResponse;
4
+
5
+ pub static TIMEOUT_RESPONSE: LazyLock<ErrorResponse> =
6
+ LazyLock::new(ErrorResponse::gateway_timeout);
7
+
8
+ pub static NOT_FOUND_RESPONSE: LazyLock<ErrorResponse> = LazyLock::new(ErrorResponse::not_found);
9
+
10
+ pub static INTERNAL_SERVER_ERROR_RESPONSE: LazyLock<ErrorResponse> =
11
+ LazyLock::new(ErrorResponse::internal_server_error);
@@ -1,16 +1,21 @@
1
+ #![deny(unused_crate_dependencies)]
2
+ pub mod default_responses;
3
+ pub mod env;
4
+ pub mod prelude;
5
+ pub mod ruby_types;
6
+ pub mod server;
7
+ pub mod services;
8
+
1
9
  use magnus::{error::Result, function, method, Module, Object, Ruby};
10
+ use prelude::*;
2
11
  use ruby_types::{
3
- itsi_body_proxy::ItsiBodyProxy, itsi_grpc_request::ItsiGrpcRequest,
4
- itsi_grpc_stream::ItsiGrpcStream, itsi_http_request::ItsiHttpRequest,
5
- itsi_http_response::ItsiHttpResponse, itsi_server::ItsiServer, ITSI_BODY_PROXY,
6
- ITSI_GRPC_REQUEST, ITSI_GRPC_RESPONSE, ITSI_GRPC_STREAM, ITSI_MODULE, ITSI_REQUEST,
7
- ITSI_RESPONSE, ITSI_SERVER,
12
+ itsi_body_proxy::ItsiBodyProxy, itsi_grpc_call::ItsiGrpcCall,
13
+ itsi_grpc_response_stream::ItsiGrpcResponseStream, itsi_http_request::ItsiHttpRequest,
14
+ itsi_http_response::ItsiHttpResponse, itsi_server::ItsiServer, ITSI_BODY_PROXY, ITSI_GRPC_CALL,
15
+ ITSI_GRPC_RESPONSE_STREAM, ITSI_MODULE, ITSI_REQUEST, ITSI_RESPONSE, ITSI_SERVER,
8
16
  };
9
17
  use server::signal::reset_signal_handlers;
10
- use tracing::*;
11
- pub mod env;
12
- pub mod ruby_types;
13
- pub mod server;
18
+ use services::password_hasher;
14
19
 
15
20
  #[magnus::init]
16
21
  fn init(ruby: &Ruby) -> Result<()> {
@@ -24,6 +29,10 @@ fn init(ruby: &Ruby) -> Result<()> {
24
29
  itsi.define_singleton_method("log_info", function!(log_info, 1))?;
25
30
  itsi.define_singleton_method("log_warn", function!(log_warn, 1))?;
26
31
  itsi.define_singleton_method("log_error", function!(log_error, 1))?;
32
+ itsi.define_singleton_method(
33
+ "create_password_hash",
34
+ function!(password_hasher::create_password_hash, 2),
35
+ )?;
27
36
 
28
37
  let server = ruby.get_inner(&ITSI_SERVER);
29
38
  server.define_singleton_method("new", function!(ItsiServer::new, 3))?;
@@ -35,7 +44,15 @@ fn init(ruby: &Ruby) -> Result<()> {
35
44
  request.define_method("path", method!(ItsiHttpRequest::path, 0))?;
36
45
  request.define_method("script_name", method!(ItsiHttpRequest::script_name, 0))?;
37
46
  request.define_method("query_string", method!(ItsiHttpRequest::query_string, 0))?;
38
- request.define_method("method", method!(ItsiHttpRequest::method, 0))?;
47
+ request.define_method(
48
+ "content_type",
49
+ method!(ItsiHttpRequest::content_type_str, 0),
50
+ )?;
51
+ request.define_method(
52
+ "content_length",
53
+ method!(ItsiHttpRequest::content_length, 0),
54
+ )?;
55
+ request.define_method("request_method", method!(ItsiHttpRequest::method, 0))?;
39
56
  request.define_method("version", method!(ItsiHttpRequest::version, 0))?;
40
57
  request.define_method("rack_protocol", method!(ItsiHttpRequest::rack_protocol, 0))?;
41
58
  request.define_method("host", method!(ItsiHttpRequest::host, 0))?;
@@ -49,6 +66,9 @@ fn init(ruby: &Ruby) -> Result<()> {
49
66
  request.define_method("response", method!(ItsiHttpRequest::response, 0))?;
50
67
  request.define_method("json?", method!(ItsiHttpRequest::is_json, 0))?;
51
68
  request.define_method("html?", method!(ItsiHttpRequest::is_html, 0))?;
69
+ request.define_method("url_encoded?", method!(ItsiHttpRequest::is_url_encoded, 0))?;
70
+ request.define_method("multipart?", method!(ItsiHttpRequest::is_multipart, 0))?;
71
+ request.define_method("url_params", method!(ItsiHttpRequest::url_params, 0))?;
52
72
 
53
73
  let body_proxy = ruby.get_inner(&ITSI_BODY_PROXY);
54
74
  body_proxy.define_method("gets", method!(ItsiBodyProxy::gets, 0))?;
@@ -73,27 +93,39 @@ fn init(ruby: &Ruby) -> Result<()> {
73
93
  response.define_method("close_read", method!(ItsiHttpResponse::close_read, 0))?;
74
94
  response.define_method("close", method!(ItsiHttpResponse::close, 0))?;
75
95
  response.define_method("hijack", method!(ItsiHttpResponse::hijack, 1))?;
96
+ response.define_method("accept", method!(ItsiHttpResponse::accept_str, 0))?;
76
97
  response.define_method("json?", method!(ItsiHttpResponse::is_json, 0))?;
77
98
  response.define_method("html?", method!(ItsiHttpResponse::is_html, 0))?;
78
99
 
79
- let grpc_request = ruby.get_inner(&ITSI_GRPC_REQUEST);
80
-
81
- grpc_request.define_method("service_name", method!(ItsiGrpcRequest::service_name, 0))?;
82
- grpc_request.define_method("method_name", method!(ItsiGrpcRequest::method_name, 0))?;
83
- grpc_request.define_method("stream", method!(ItsiGrpcRequest::stream, 0))?;
84
- grpc_request.define_method("json?", method!(ItsiGrpcRequest::is_json, 0))?;
85
- grpc_request.define_method(
86
- "content_type",
87
- method!(ItsiGrpcRequest::content_type_str, 0),
100
+ let grpc_call = ruby.get_inner(&ITSI_GRPC_CALL);
101
+ grpc_call.define_method("service_name", method!(ItsiGrpcCall::service_name, 0))?;
102
+ grpc_call.define_method("method_name", method!(ItsiGrpcCall::method_name, 0))?;
103
+ grpc_call.define_method("stream", method!(ItsiGrpcCall::stream, 0))?;
104
+ grpc_call.define_method("json?", method!(ItsiGrpcCall::is_json, 0))?;
105
+ grpc_call.define_method("content_type", method!(ItsiGrpcCall::content_type_str, 0))?;
106
+ grpc_call.define_method("timeout", method!(ItsiGrpcCall::timeout, 0))?;
107
+ grpc_call.define_method("cancelled?", method!(ItsiGrpcCall::is_cancelled, 0))?;
108
+ grpc_call.define_method("add_headers", method!(ItsiGrpcCall::add_headers, 1))?;
109
+ grpc_call.define_method("compress_output", method!(ItsiGrpcCall::compress_output, 1))?;
110
+ grpc_call.define_method(
111
+ "decompress_input",
112
+ method!(ItsiGrpcCall::decompress_input, 1),
113
+ )?;
114
+ grpc_call.define_method(
115
+ "should_compress_output?",
116
+ method!(ItsiGrpcCall::should_compress_output, 1),
88
117
  )?;
89
118
 
90
- let grpc_stream = ruby.get_inner(&ITSI_GRPC_STREAM);
91
- grpc_stream.define_method("read", method!(ItsiGrpcStream::read, 1))?;
92
- grpc_stream.define_method("write", method!(ItsiGrpcStream::write, 1))?;
93
- grpc_stream.define_method("flush", method!(ItsiGrpcStream::flush, 0))?;
94
- grpc_stream.define_method("send_trailers", method!(ItsiGrpcStream::send_trailers, 1))?;
95
-
96
- let _grpc_response = ruby.get_inner(&ITSI_GRPC_RESPONSE);
119
+ let grpc_response_stream = ruby.get_inner(&ITSI_GRPC_RESPONSE_STREAM);
120
+ grpc_response_stream
121
+ .define_method("reader_fileno", method!(ItsiGrpcResponseStream::reader, 0))?;
122
+ grpc_response_stream.define_method("write", method!(ItsiGrpcResponseStream::write, 1))?;
123
+ grpc_response_stream.define_method("flush", method!(ItsiGrpcResponseStream::flush, 0))?;
124
+ grpc_response_stream.define_method(
125
+ "send_trailers",
126
+ method!(ItsiGrpcResponseStream::send_trailers, 1),
127
+ )?;
128
+ grpc_response_stream.define_method("close", method!(ItsiGrpcResponseStream::close, 0))?;
97
129
 
98
130
  Ok(())
99
131
  }
@@ -0,0 +1,2 @@
1
+ pub use itsi_error::*;
2
+ pub use itsi_tracing::{debug, error, info, trace, warn};
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Itsi Server Twp
3
+ type: docs
4
+ prev: /crates/itsi_server/test
5
+ next: docs/folder/
6
+ ---
7
+ # Deep nested Foo
8
+
9
+ This is a demo of the theme's documentation layout.
10
+
11
+ ## Hello, World!
12
+
13
+ ```go {filename="main.go"}
14
+ package main
15
+
16
+ import "fmt"
17
+
18
+ func main() {
19
+ fmt.Println("Hello, World!")
20
+ }
21
+ ```
@@ -12,10 +12,12 @@ use std::sync::{
12
12
  };
13
13
  use tokio_stream::StreamExt;
14
14
 
15
+ use crate::server::size_limited_incoming::SizeLimitedIncoming;
16
+
15
17
  #[magnus::wrap(class = "Itsi::BodyProxy", free_immediately, size)]
16
18
  #[derive(Debug, Clone)]
17
19
  pub struct ItsiBodyProxy {
18
- pub incoming: Arc<Mutex<BodyDataStream<Incoming>>>,
20
+ pub incoming: Arc<Mutex<BodyDataStream<SizeLimitedIncoming<Incoming>>>>,
19
21
  pub closed: Arc<AtomicBool>,
20
22
  pub buf: Arc<Mutex<Vec<u8>>>,
21
23
  }
@@ -34,7 +36,7 @@ impl ItsiBody {
34
36
  }
35
37
  }
36
38
  impl ItsiBodyProxy {
37
- pub fn new(incoming: Incoming) -> Self {
39
+ pub fn new(incoming: SizeLimitedIncoming<Incoming>) -> Self {
38
40
  ItsiBodyProxy {
39
41
  incoming: Arc::new(Mutex::new(incoming.into_data_stream())),
40
42
  closed: Arc::new(AtomicBool::new(false)),
@@ -50,7 +52,7 @@ impl ItsiBodyProxy {
50
52
  if let Some(chunk) = block_on(stream.next()) {
51
53
  let chunk = chunk.map_err(|err| {
52
54
  magnus::Error::new(
53
- magnus::exception::exception(),
55
+ magnus::exception::standard_error(),
54
56
  format!("Error reading body {:?}", err),
55
57
  )
56
58
  })?;
@@ -82,7 +84,7 @@ impl ItsiBodyProxy {
82
84
  if let Some(chunk) = block_on(stream.next()) {
83
85
  let chunk = chunk.map_err(|err| {
84
86
  magnus::Error::new(
85
- magnus::exception::exception(),
87
+ magnus::exception::standard_error(),
86
88
  format!("Error reading body {:?}", err),
87
89
  )
88
90
  })?;
@@ -107,7 +109,7 @@ impl ItsiBodyProxy {
107
109
  while let Some(chunk) = block_on(stream.next()) {
108
110
  let chunk = chunk.map_err(|err| {
109
111
  magnus::Error::new(
110
- magnus::exception::exception(),
112
+ magnus::exception::standard_error(),
111
113
  format!("Error reading body {:?}", err),
112
114
  )
113
115
  })?;
@@ -129,7 +131,7 @@ impl ItsiBodyProxy {
129
131
  fn verify_open(&self) -> MagnusResult<()> {
130
132
  if self.closed.load(atomic::Ordering::SeqCst) {
131
133
  return Err(magnus::Error::new(
132
- magnus::exception::exception(),
134
+ magnus::exception::standard_error(),
133
135
  "Body stream is closed",
134
136
  ));
135
137
  }