itsi 0.2.4 → 0.2.6

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +2 -2
  3. data/crates/itsi_rb_helpers/src/lib.rs +0 -1
  4. data/crates/itsi_scheduler/Cargo.toml +1 -1
  5. data/crates/itsi_server/Cargo.toml +1 -1
  6. data/crates/itsi_server/src/services/static_file_server.rs +2 -2
  7. data/docs/content/getting_started/signals.md +0 -1
  8. data/docs/static/android-chrome-192x192.png +0 -0
  9. data/docs/static/android-chrome-310x310.png +0 -0
  10. data/docs/static/apple-touch-icon.png +0 -0
  11. data/docs/static/browserconfig.xml +12 -0
  12. data/docs/static/favicon-114x114.png +0 -0
  13. data/docs/static/favicon-120x120.png +0 -0
  14. data/docs/static/favicon-144x144.png +0 -0
  15. data/docs/static/favicon-150x150.png +0 -0
  16. data/docs/static/favicon-152x152.png +0 -0
  17. data/docs/static/favicon-16x16.png +0 -0
  18. data/docs/static/favicon-180x180.png +0 -0
  19. data/docs/static/favicon-192x192.png +0 -0
  20. data/docs/static/favicon-310x310.png +0 -0
  21. data/docs/static/favicon-32x32.png +0 -0
  22. data/docs/static/favicon-57x57.png +0 -0
  23. data/docs/static/favicon-60x60.png +0 -0
  24. data/docs/static/favicon-70x70.png +0 -0
  25. data/docs/static/favicon-72x72.png +0 -0
  26. data/docs/static/favicon-76x76.png +0 -0
  27. data/docs/static/favicon-96x96.png +0 -0
  28. data/docs/static/favicon-dark.svg +40 -0
  29. data/docs/static/favicon.ico +0 -0
  30. data/docs/static/favicon.svg +40 -0
  31. data/docs/static/site.webmanifest +20 -0
  32. data/gems/scheduler/Cargo.lock +1 -1
  33. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  34. data/gems/server/Cargo.lock +1 -1
  35. data/gems/server/lib/itsi/http_request.rb +62 -45
  36. data/gems/server/lib/itsi/server/config/middleware/auth_api_key.rb +4 -4
  37. data/gems/server/lib/itsi/server/config/middleware/auth_basic.rb +6 -4
  38. data/gems/server/lib/itsi/server/config/middleware/grpc.md +1 -3
  39. data/gems/server/lib/itsi/server/config/middleware/location.md +2 -2
  40. data/gems/server/lib/itsi/server/config/middleware/log_requests.md +3 -1
  41. data/gems/server/lib/itsi/server/config/middleware/proxy.md +7 -7
  42. data/gems/server/lib/itsi/server/config/middleware/static_assets.rb +2 -2
  43. data/gems/server/lib/itsi/server/config/options/_index.md +9 -5
  44. data/gems/server/lib/itsi/server/config/options/reuse_address.md +2 -0
  45. data/gems/server/lib/itsi/server/config/options/reuse_address.rb +1 -1
  46. data/gems/server/lib/itsi/server/config/options/reuse_port.md +2 -0
  47. data/gems/server/lib/itsi/server/config/options/reuse_port.rb +1 -1
  48. data/gems/server/lib/itsi/server/version.rb +1 -1
  49. data/gems/server/test/middleware/grpc/test_service.proto +0 -1
  50. data/gems/server/test/middleware/grpc/test_service_impl.rb +0 -4
  51. data/gems/server/test/middleware/grpc/test_service_services_pb.rb +1 -1
  52. data/lib/itsi/version.rb +1 -1
  53. data/tasks.txt +4 -2
  54. metadata +29 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0f48a4cf96ec2afd196a828cd9b264a019673ce1cb690229c57a4f113f47e52
4
- data.tar.gz: 6119bc422b0ec00e7d4d9c52314d725c441e2117275402c838f1ee47166b000a
3
+ metadata.gz: 149fcb6ea7294774f71e351c52ae1caa173c66e5b3de4d9c949795a435a7f01b
4
+ data.tar.gz: f691a13139c6a5a43334b9f33da2896d173b48169f76cf206b4cf2f8d8c7da40
5
5
  SHA512:
6
- metadata.gz: 7d572b3bad1e3156eb2e0c5da02d9ac5b988f37b19d33fdac7f475cd6161563c4d5befaae7d5776fc30e1089fe8f2d025e9557978f618980260e6d1715f2783c
7
- data.tar.gz: 3913fb88decca4a0fc83e2c0136056d5eff6b703c498cb0d160c9bf2accadbe50a01c23d6380eb0a87a41e7901f2dbac6cf1050c566f2250a91fc51991a4749d
6
+ metadata.gz: 1abb41219076c668b01f6db8b5d7ec8577bc7b7d8573fd6e3ec9f707af16940aefd1c0003a414b5a9c3a409b7b6329d2f3cbc66853a618d0569ce5fd0f4be4e1
7
+ data.tar.gz: ed79a245af6a26cb5aaa3112c092de25ab6b47cdd1551178820e84ab617760e55ee25ab05bded85062dd13eacaa6026cca055f7dbf13096c679704c21ecf2868
data/Cargo.lock CHANGED
@@ -1644,7 +1644,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
1644
1644
 
1645
1645
  [[package]]
1646
1646
  name = "itsi-scheduler"
1647
- version = "0.2.4"
1647
+ version = "0.2.6"
1648
1648
  dependencies = [
1649
1649
  "bytes",
1650
1650
  "derive_more",
@@ -1662,7 +1662,7 @@ dependencies = [
1662
1662
 
1663
1663
  [[package]]
1664
1664
  name = "itsi-server"
1665
- version = "0.2.4"
1665
+ version = "0.2.6"
1666
1666
  dependencies = [
1667
1667
  "argon2",
1668
1668
  "async-channel",
@@ -159,7 +159,6 @@ where
159
159
  eprintln!("Thread killed");
160
160
  break;
161
161
  }
162
- eprintln!("Killing thread {:?}", thr.as_value());
163
162
  thr.funcall::<_, _, Value>("terminate", ())
164
163
  .expect("Failed to kill thread");
165
164
  }
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-scheduler"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-server"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -662,7 +662,7 @@ impl StaticFileServer {
662
662
  let range_length = end - start + 1;
663
663
  let limited_reader = tokio::io::AsyncReadExt::take(file, range_length);
664
664
  let path_clone = path.clone();
665
- let stream = ReaderStream::new(limited_reader)
665
+ let stream = ReaderStream::with_capacity(limited_reader, 64 * 1024)
666
666
  .map_ok(Frame::data)
667
667
  .map_err(move |e| {
668
668
  warn!("Error streaming file {}: {}", path_clone.display(), e);
@@ -681,7 +681,7 @@ impl StaticFileServer {
681
681
  match File::open(&path).await {
682
682
  Ok(file) => {
683
683
  let path_clone = path.clone();
684
- let stream = ReaderStream::new(file)
684
+ let stream = ReaderStream::with_capacity(file, 64 * 1024)
685
685
  .map_ok(Frame::data)
686
686
  .map_err(move |e| {
687
687
  warn!("Error streaming file {}: {}", path_clone.display(), e);
@@ -8,7 +8,6 @@ next: /configuration
8
8
 
9
9
  Itsi responds to several Unix signals for process control. These signals are used to gracefully shut down, reload configuration, adjust worker pools, or emit internal lifecycle events.
10
10
 
11
- ---
12
11
 
13
12
  ## Signal Types
14
13
 
Binary file
@@ -0,0 +1,12 @@
1
+
2
+ <?xml version="1.0" encoding="utf-8"?>
3
+ <browserconfig>
4
+ <msapplication>
5
+ <tile>
6
+ <square70x70logo src="/favicon-70x70.png"/>
7
+ <square150x150logo src="/favicon-150x150.png"/>
8
+ <square310x310logo src="/favicon-310x310.png"/>
9
+ <TileColor>#ffffff</TileColor>
10
+ </tile>
11
+ </msapplication>
12
+ </browserconfig>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="152.000000pt" height="152.000000pt" viewBox="0 0 152.000000 152.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+
8
+ <g transform="translate(0.000000,152.000000) scale(0.100000,-0.100000)"
9
+ fill="#000000" stroke="none">
10
+ <path d="M390 1358 c-11 -12 -20 -31 -20 -43 0 -15 -12 -24 -49 -38 -100 -35
11
+ -194 -150 -208 -253 -5 -36 -11 -48 -29 -55 -18 -6 -24 -16 -24 -37 0 -45 15
12
+ -52 121 -52 l96 0 7 -42 c15 -94 78 -185 163 -235 34 -20 43 -31 43 -52 0 -45
13
+ 28 -125 59 -168 23 -31 31 -58 40 -128 7 -49 17 -97 22 -107 14 -27 51 -38
14
+ 120 -38 75 0 104 24 114 94 l7 46 58 0 58 0 13 -57 c17 -69 37 -83 121 -83 81
15
+ 0 91 13 106 129 9 77 16 98 39 126 28 34 31 35 90 19 17 -4 31 2 54 26 31 31
16
+ 32 32 26 105 -4 53 -15 98 -40 157 -23 53 -38 108 -42 153 -14 138 -59 239
17
+ -140 314 -113 105 -298 138 -447 81 l-50 -19 -50 34 c-27 19 -67 40 -89 46
18
+ -30 9 -39 17 -39 34 0 34 -36 65 -75 65 -22 0 -41 -8 -55 -22z m90 -43 c0 -10
19
+ -11 -15 -35 -15 -38 0 -48 22 -18 39 21 11 53 -3 53 -24z m104 -89 c30 -15 67
20
+ -41 82 -59 33 -39 71 -121 76 -162 l3 -30 -300 0 -300 0 3 30 c5 49 64 156
21
+ 104 188 89 72 225 85 332 33z m408 -27 c153 -33 256 -138 292 -301 8 -35 18
22
+ -110 21 -168 11 -166 -15 -268 -89 -350 -28 -31 -33 -47 -44 -130 -7 -52 -15
23
+ -96 -18 -99 -10 -10 -113 -6 -124 5 -6 6 -14 30 -17 53 -5 37 -3 41 21 51 49
24
+ 18 19 26 -96 24 l-113 -3 -11 -53 c-6 -30 -14 -59 -18 -66 -10 -17 -71 -25
25
+ -113 -15 -34 8 -39 13 -50 53 -6 25 -12 68 -12 96 -1 37 -7 59 -27 85 -38 51
26
+ -54 84 -63 136 -8 39 -6 49 7 59 14 10 9 15 -36 38 -28 14 -67 40 -86 57 -41
27
+ 35 -96 140 -96 181 l0 28 69 0 69 0 37 -50 c34 -47 53 -59 68 -44 3 4 0 16 -8
28
+ 28 -8 12 -12 31 -9 43 6 21 12 23 137 25 106 2 132 6 140 19 14 22 1 66 -21
29
+ 71 -13 4 -21 18 -24 45 -5 32 -30 98 -55 144 -5 8 40 26 92 38 57 13 116 13
30
+ 177 0z m-202 -274 c0 -13 -45 -15 -344 -15 -313 0 -369 4 -349 24 3 3 161 6
31
+ 350 6 298 0 343 -2 343 -15z m580 -340 c26 -91 12 -165 -29 -165 -32 0 -40 19
32
+ -25 57 8 19 18 63 21 98 3 36 9 62 13 60 4 -2 13 -25 20 -50z"/>
33
+ <path d="M1107 953 c-11 -11 -8 -58 5 -71 34 -34 82 13 59 57 -11 20 -50 29
34
+ -64 14z"/>
35
+ <path d="M865 934 c-8 -9 -15 -24 -15 -34 0 -19 25 -50 40 -50 12 0 40 29 40
36
+ 41 0 18 -19 46 -34 52 -9 4 -22 -1 -31 -9z"/>
37
+ <path d="M952 844 c4 -24 52 -48 81 -40 12 3 31 12 42 20 16 11 17 17 8 27
38
+ -10 10 -15 9 -27 -1 -16 -12 -54 -10 -90 5 -14 6 -17 4 -14 -11z"/>
39
+ </g>
40
+ </svg>
Binary file
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="152.000000pt" height="152.000000pt" viewBox="0 0 152.000000 152.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+
8
+ <g transform="translate(0.000000,152.000000) scale(0.100000,-0.100000)"
9
+ fill="#000000" stroke="none">
10
+ <path d="M390 1358 c-11 -12 -20 -31 -20 -43 0 -15 -12 -24 -49 -38 -100 -35
11
+ -194 -150 -208 -253 -5 -36 -11 -48 -29 -55 -18 -6 -24 -16 -24 -37 0 -45 15
12
+ -52 121 -52 l96 0 7 -42 c15 -94 78 -185 163 -235 34 -20 43 -31 43 -52 0 -45
13
+ 28 -125 59 -168 23 -31 31 -58 40 -128 7 -49 17 -97 22 -107 14 -27 51 -38
14
+ 120 -38 75 0 104 24 114 94 l7 46 58 0 58 0 13 -57 c17 -69 37 -83 121 -83 81
15
+ 0 91 13 106 129 9 77 16 98 39 126 28 34 31 35 90 19 17 -4 31 2 54 26 31 31
16
+ 32 32 26 105 -4 53 -15 98 -40 157 -23 53 -38 108 -42 153 -14 138 -59 239
17
+ -140 314 -113 105 -298 138 -447 81 l-50 -19 -50 34 c-27 19 -67 40 -89 46
18
+ -30 9 -39 17 -39 34 0 34 -36 65 -75 65 -22 0 -41 -8 -55 -22z m90 -43 c0 -10
19
+ -11 -15 -35 -15 -38 0 -48 22 -18 39 21 11 53 -3 53 -24z m104 -89 c30 -15 67
20
+ -41 82 -59 33 -39 71 -121 76 -162 l3 -30 -300 0 -300 0 3 30 c5 49 64 156
21
+ 104 188 89 72 225 85 332 33z m408 -27 c153 -33 256 -138 292 -301 8 -35 18
22
+ -110 21 -168 11 -166 -15 -268 -89 -350 -28 -31 -33 -47 -44 -130 -7 -52 -15
23
+ -96 -18 -99 -10 -10 -113 -6 -124 5 -6 6 -14 30 -17 53 -5 37 -3 41 21 51 49
24
+ 18 19 26 -96 24 l-113 -3 -11 -53 c-6 -30 -14 -59 -18 -66 -10 -17 -71 -25
25
+ -113 -15 -34 8 -39 13 -50 53 -6 25 -12 68 -12 96 -1 37 -7 59 -27 85 -38 51
26
+ -54 84 -63 136 -8 39 -6 49 7 59 14 10 9 15 -36 38 -28 14 -67 40 -86 57 -41
27
+ 35 -96 140 -96 181 l0 28 69 0 69 0 37 -50 c34 -47 53 -59 68 -44 3 4 0 16 -8
28
+ 28 -8 12 -12 31 -9 43 6 21 12 23 137 25 106 2 132 6 140 19 14 22 1 66 -21
29
+ 71 -13 4 -21 18 -24 45 -5 32 -30 98 -55 144 -5 8 40 26 92 38 57 13 116 13
30
+ 177 0z m-202 -274 c0 -13 -45 -15 -344 -15 -313 0 -369 4 -349 24 3 3 161 6
31
+ 350 6 298 0 343 -2 343 -15z m580 -340 c26 -91 12 -165 -29 -165 -32 0 -40 19
32
+ -25 57 8 19 18 63 21 98 3 36 9 62 13 60 4 -2 13 -25 20 -50z"/>
33
+ <path d="M1107 953 c-11 -11 -8 -58 5 -71 34 -34 82 13 59 57 -11 20 -50 29
34
+ -64 14z"/>
35
+ <path d="M865 934 c-8 -9 -15 -24 -15 -34 0 -19 25 -50 40 -50 12 0 40 29 40
36
+ 41 0 18 -19 46 -34 52 -9 4 -22 -1 -31 -9z"/>
37
+ <path d="M952 844 c4 -24 52 -48 81 -40 12 3 31 12 42 20 16 11 17 17 8 27
38
+ -10 10 -15 9 -27 -1 -16 -12 -54 -10 -90 5 -14 6 -17 4 -14 -11z"/>
39
+ </g>
40
+ </svg>
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "Itsi",
3
+ "short_name": "Itsi",
4
+ "start_url": "index.html",
5
+ "icons": [
6
+ {
7
+ "src": "android-chrome-192x192.png",
8
+ "sizes": "192x192",
9
+ "type": "image/png"
10
+ },
11
+ {
12
+ "src": "android-chrome-310x310.png",
13
+ "sizes": "310x310",
14
+ "type": "image/png"
15
+ }
16
+ ],
17
+ "theme_color": "#000000",
18
+ "background_color": "#000000",
19
+ "display": "standalone"
20
+ }
@@ -213,7 +213,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
213
213
 
214
214
  [[package]]
215
215
  name = "itsi-scheduler"
216
- version = "0.2.4"
216
+ version = "0.2.6"
217
217
  dependencies = [
218
218
  "bytes",
219
219
  "derive_more",
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Scheduler
5
- VERSION = "0.2.4"
5
+ VERSION = "0.2.6"
6
6
  end
7
7
  end
@@ -1644,7 +1644,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
1644
1644
 
1645
1645
  [[package]]
1646
1646
  name = "itsi-server"
1647
- version = "0.2.4"
1647
+ version = "0.2.6"
1648
1648
  dependencies = [
1649
1649
  "argon2",
1650
1650
  "async-channel",
@@ -25,56 +25,73 @@ module Itsi
25
25
  hm.default_proc = proc { |_, key| "HTTP_#{key.upcase.gsub(/-/, "_")}" }
26
26
  end
27
27
 
28
+ RACK_ENV_TEMPLATE = {
29
+ "SERVER_SOFTWARE" => "Itsi",
30
+ "rack.errors" => $stderr,
31
+ "rack.multithread" => true,
32
+ "rack.multiprocess" => true,
33
+ "rack.run_once" => false,
34
+ "rack.hijack?" => true,
35
+ "rack.multipart.buffer_size" => 16_384,
36
+ "SCRIPT_NAME" => "",
37
+ "REQUEST_METHOD" => "",
38
+ "PATH_INFO" => "",
39
+ "REQUEST_PATH" => "",
40
+ "QUERY_STRING" => "",
41
+ "REMOTE_ADDR" => "",
42
+ "SERVER_PORT" => "",
43
+ "SERVER_NAME" => "",
44
+ "SERVER_PROTOCOL" => "",
45
+ "HTTP_HOST" => "",
46
+ "HTTP_VERSION" => "",
47
+ "itsi.request" => "",
48
+ "itsi.response" => "",
49
+ "rack.version" => [nil],
50
+ "rack.url_scheme" => "",
51
+ "rack.input" => "",
52
+ "rack.hijack" => "",
53
+ "CONTENT_TYPE" => nil,
54
+ "CONTENT_LENGTH" => nil
55
+ }.freeze
56
+
28
57
  def to_rack_env
29
58
  path = self.path
30
59
  host = self.host
31
60
  version = self.version
32
-
33
- {
34
- "SERVER_SOFTWARE" => "Itsi",
35
- "SCRIPT_NAME" => script_name,
36
- "REQUEST_METHOD" => request_method,
37
- "PATH_INFO" => path,
38
- "REQUEST_PATH" => path,
39
- "QUERY_STRING" => query_string,
40
- "REMOTE_ADDR" => remote_addr,
41
- "SERVER_PORT" => port.to_s,
42
- "SERVER_NAME" => host,
43
- "SERVER_PROTOCOL" => version,
44
- "HTTP_HOST" => host,
45
- "HTTP_VERSION" => version,
46
- "itsi.request" => self,
47
- "itsi.response" => response,
48
- "rack.version" => [version],
49
- "rack.url_scheme" => scheme,
50
- "rack.input" => build_input_io,
51
- "rack.errors" => $stderr,
52
- "rack.multithread" => true,
53
- "rack.multiprocess" => true,
54
- "rack.run_once" => false,
55
- "rack.hijack?" => true,
56
- "rack.multipart.buffer_size" => 16_384,
57
- "rack.hijack" => method(:hijack)
58
- }.tap do |r|
59
- headers.each do |(k, v)|
60
- r[case k
61
- when "content-type" then "CONTENT_TYPE"
62
- when "content-length" then "CONTENT_LENGTH"
63
- when "accept" then "HTTP_ACCEPT"
64
- when "accept-encoding" then "HTTP_ACCEPT_ENCODING"
65
- when "accept-language" then "HTTP_ACCEPT_LANGUAGE"
66
- when "user-agent" then "HTTP_USER_AGENT"
67
- when "referer" then "HTTP_REFERER"
68
- when "origin" then "HTTP_ORIGIN"
69
- when "cookie" then "HTTP_COOKIE"
70
- when "authorization" then "HTTP_AUTHORIZATION"
71
- when "x-forwarded-for" then "HTTP_X_FORWARDED_FOR"
72
- when "x-forwarded-proto" then "HTTP_X_FORWARDED_PROTO"
73
- else RACK_HEADER_MAP[k]
74
- end
75
- ] = v
76
- end
61
+ env = RACK_ENV_TEMPLATE.dup
62
+ env["SCRIPT_NAME"] = script_name
63
+ env["REQUEST_METHOD"] = request_method
64
+ env["REQUEST_PATH"] = env["PATH_INFO"] = path
65
+ env["QUERY_STRING"] = query_string
66
+ env["REMOTE_ADDR"] = remote_addr
67
+ env["SERVER_PORT"] = port.to_s
68
+ env["HTTP_HOST"] = env["SERVER_NAME"] = host
69
+ env["HTTP_VERSION"] = env["SERVER_PROTOCOL"] = version
70
+ env["itsi.request"] = self
71
+ env["itsi.response"] = response
72
+ env["rack.version"][0] = version
73
+ env["rack.url_scheme"] = scheme
74
+ env["rack.input"] = build_input_io
75
+ env["rack.hijack"] = method(:hijack)
76
+ headers.each do |(k, v)|
77
+ env[case k
78
+ when "content-type" then "CONTENT_TYPE"
79
+ when "content-length" then "CONTENT_LENGTH"
80
+ when "accept" then "HTTP_ACCEPT"
81
+ when "accept-encoding" then "HTTP_ACCEPT_ENCODING"
82
+ when "accept-language" then "HTTP_ACCEPT_LANGUAGE"
83
+ when "user-agent" then "HTTP_USER_AGENT"
84
+ when "referer" then "HTTP_REFERER"
85
+ when "origin" then "HTTP_ORIGIN"
86
+ when "cookie" then "HTTP_COOKIE"
87
+ when "authorization" then "HTTP_AUTHORIZATION"
88
+ when "x-forwarded-for" then "HTTP_X_FORWARDED_FOR"
89
+ when "x-forwarded-proto" then "HTTP_X_FORWARDED_PROTO"
90
+ else RACK_HEADER_MAP[k]
91
+ end
92
+ ] = v
77
93
  end
94
+ env
78
95
  end
79
96
 
80
97
  def respond(
@@ -33,12 +33,12 @@ module Itsi
33
33
  @params[:key_id_source] = nil
34
34
  end
35
35
 
36
- if File.exist?(".itsi-credentials") && !@params[:credential_file]
37
- @params[:credential_file] = ".itsi-credentials"
36
+ if File.exist?(".itsi-credentials") && !@params[:credentials_file]
37
+ @params[:credentials_file] = ".itsi-credentials"
38
38
  end
39
39
 
40
- if @params[:credential_file] && File.exist?(@params[:credential_file])
41
- @params[:valid_keys] = Passfile.load(@params[:credential_file])
40
+ if @params[:credentials_file] && File.exist?(@params[:credentials_file])
41
+ @params[:valid_keys] = Passfile.load(@params[:credentials_file])
42
42
  end
43
43
 
44
44
  unless @params[:valid_keys]&.any?
@@ -21,16 +21,18 @@ module Itsi
21
21
 
22
22
  def initialize(location, params={})
23
23
  super
24
+
24
25
  unless @params[:credential_pairs]&.any?
25
- if File.exist?(".itsi-credentials") && !@params[:credential_file]
26
- @params[:credential_file] = ".itsi-credentials"
26
+ if File.exist?(".itsi-credentials") && !@params[:credentials_file]
27
+ @params[:credentials_file] = ".itsi-credentials"
27
28
  end
28
29
 
29
- if @params[:credential_file] && File.exist?(@params[:credential_file])
30
- @params[:credential_pairs] = Passfile.load(@params[:credential_file])
30
+ if @params[:credentials_file] && File.exist?(@params[:credentials_file])
31
+ @params[:credential_pairs] = Passfile.load(@params[:credentials_file])
31
32
  end
32
33
  end
33
34
 
35
+ raise "No credentials provided" unless @params[:credential_pairs]
34
36
  @params[:credential_pairs].compact!
35
37
 
36
38
  unless @params[:credential_pairs]&.any?
@@ -13,7 +13,6 @@ Under the covers it:
13
13
  3. Automatically enables `gRPC` reflection (so client like `evans`, `grpcurl` or `Postman` can discover your service endpoints without needing access to raw `.proto` files).
14
14
  4. Supports optional per‑call compression (`none`, `deflate`, `gzip`) and a non‑blocking execution mode.
15
15
 
16
- ---
17
16
 
18
17
  ## Usage
19
18
 
@@ -97,8 +96,7 @@ require_relative 'echo_service_impl'
97
96
 
98
97
  bind "https://localhost:3000"
99
98
  grpc EchoServiceImpl.new,
100
- nonblocking: false,
101
- compression: 'gzip' do
99
+ nonblocking: false do
102
100
  # Nested middleware still works:
103
101
  response_headers additions: { 'X-Service' => ['Echo'] }
104
102
  end
@@ -48,7 +48,7 @@ end
48
48
  ```ruby {filename="Itsi.rb"}
49
49
  # Match on non-route options.
50
50
  # Redirect http requests to https requests
51
- location protocols: ["http"]
51
+ location schemes: ["http"]
52
52
  redirect type: :permanent, to: "https://{host}{path_and_query}"
53
53
  end
54
54
  ```
@@ -101,7 +101,7 @@ Pass these to the location block using keyword arguments, e.g.
101
101
 
102
102
  ```ruby
103
103
  # Redirect all http JSON requests to use https exclusively.
104
- location protocols: ["http"], content_types: ["application/json"]
104
+ location schemes: ["http"], content_types: ["application/json"]
105
105
  redirect type: :permanent, to: "https://{host}{path_and_query}"
106
106
  end
107
107
  ```
@@ -21,7 +21,7 @@ log_requests \
21
21
  ```
22
22
 
23
23
 
24
- The log statement can populated with several different placeholders.
24
+ The log statement can populated with several different placeholders, using [String Rewrite](/middleware/string_rewrite) functionality.
25
25
  Available values are:
26
26
 
27
27
  ### `before` Format String
@@ -46,6 +46,8 @@ Available values are:
46
46
  * `response_time` - The response time in milliseconds
47
47
  * `<Header-Name>`: Any existing response header. For example `{Content-Type}` or `{Set-Cookie}` will be replaced with its current value.
48
48
 
49
+ See [String Rewrite](/middleware/string_rewrite) for more advanced string manipulation options.
50
+
49
51
 
50
52
  ### Path Attributes
51
53
  In addition to this, any capture groups referenced by container location blocks
@@ -9,13 +9,13 @@ The Reverse Proxy middleware enables reverse proxying by forwarding incoming HTT
9
9
 
10
10
  ```ruby
11
11
  proxy \
12
- to: "http://backend.example.com/api{path}{query}", \
13
- backends: ["127.0.0.1:3001", "127.0.0.1:3002"], \
14
- backend_priority: "round_robin", \
15
- headers: { "X-Forwarded-For" => { rewrite: "{addr}" } }, \
16
- verify_ssl: false, \
17
- timeout: 30, \
18
- tls_sni: true, \
12
+ to: "http://backend.example.com/api{path}{query}",
13
+ backends: ["127.0.0.1:3001", "127.0.0.1:3002"],
14
+ backend_priority: "round_robin",
15
+ headers: { "X-Forwarded-For" => { rewrite: "{addr}" } },
16
+ verify_ssl: false,
17
+ timeout: 30,
18
+ tls_sni: true,
19
19
  error_response: "bad_gateway"
20
20
  ```
21
21
  ## Options
@@ -63,9 +63,9 @@ module Itsi
63
63
  root_dir = @params[:root_dir] || "."
64
64
 
65
65
  if !File.exist?(root_dir)
66
- warn "Warning: static_assets root_dir '#{root_dir}' does not exist!"
66
+ raise "Warning: static_assets root_dir '#{root_dir}' does not exist!"
67
67
  elsif !File.directory?(root_dir)
68
- warn "Warning: static_assets root_dir '#{root_dir}' is not a directory!"
68
+ raise "Warning: static_assets root_dir '#{root_dir}' is not a directory!"
69
69
  end
70
70
 
71
71
  @params[:relative_path] = true unless @params.key?(:relative_path)
@@ -18,20 +18,24 @@ For the best development experience, be sure to use [RubyLSP](https://shopify.gi
18
18
 
19
19
  ```ruby {filename="Itsi.rb"}
20
20
  workers 2
21
+
21
22
  threads 2
22
- scheduler_threads 3
23
23
 
24
24
  fiber_scheduler true
25
25
 
26
- rate_limiter requests: 100, seconds: 10
26
+ auth_basic realm: "Restricted Area", credentials_file: "./credentials.txt"
27
+
28
+ auto_reload_config! # Auto-reload the server configuration each time it changes.
27
29
 
28
- auth_basic realm: "Restricted Area", credentials_file: "credentials.txt"
30
+ location "/app*" do
31
+ rate_limit requests: 3, seconds: 5
32
+ rackup_file "config.ru"
33
+ end
29
34
 
30
- location "/app" do
35
+ location "/inline*" do
31
36
  get "/" do |req|
32
37
  req.ok "Hello, World!"
33
38
  end
34
39
  end
35
-
36
40
  ```
37
41
  {{< /details >}}
@@ -6,6 +6,8 @@ url: /options/reuse_address
6
6
  Configures whether the server should bind to the underlying socket using the `SO_REUSEADDR` option.
7
7
  This option determines whether the server allows the reuse of local addresses during binding. This can be useful in scenarios where a socket needs to be quickly rebound without waiting for the operating system to release the address.
8
8
 
9
+ The default value is `false`.
10
+
9
11
  ## Configuration
10
12
  ```ruby {filename=Itsi.rb}
11
13
  reuse_address true
@@ -10,7 +10,7 @@ module Itsi
10
10
  detail "Configures whether the server should set the reuse_address option on the underlying socket."
11
11
 
12
12
  schema do
13
- (Bool() & Required()).default(true)
13
+ (Bool() & Required()).default(false)
14
14
  end
15
15
 
16
16
  end
@@ -6,6 +6,8 @@ url: /options/reuse_port
6
6
  Configures whether the server should bind to the underlying socket using the `SO_REUSEPORT` option.
7
7
  This option determines whether multiple sockets can listen on the same IP and port combination, which can improve load balancing and fault tolerance in multi-threaded or multi-process server applications.
8
8
 
9
+ The default value is `false`.
10
+
9
11
  ## Configuration
10
12
  ```ruby {filename=Itsi.rb}
11
13
  reuse_port true
@@ -10,7 +10,7 @@ module Itsi
10
10
  detail "Configures whether the server should set the reuse_port option on the underlying socket."
11
11
 
12
12
  schema do
13
- (Bool() & Required()).default(true)
13
+ (Bool() & Required()).default(false)
14
14
  end
15
15
 
16
16
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Server
5
- VERSION = "0.2.4"
5
+ VERSION = "0.2.6"
6
6
  end
7
7
  end
@@ -2,7 +2,6 @@ syntax = "proto3";
2
2
 
3
3
  package test;
4
4
 
5
- // A service with one of each RPC type [oai_citation_attribution:0‡Википедия — свободная энциклопедия](https://ru.wikipedia.org/wiki/GRPC?utm_source=chatgpt.com)
6
5
  service TestService {
7
6
  // Unary RPC
8
7
  rpc UnaryEcho (EchoRequest) returns (EchoResponse) {}
@@ -1,25 +1,21 @@
1
1
  require_relative 'test_service_services_pb' # generated by grpc_tools_ruby_protoc
2
2
 
3
3
  class TestServiceImpl < Test::TestService::Service
4
- # Unary: echo back the message [oai_citation_attribution:2‡Gustavo Caso](https://gustavocaso.dev/posts/grpc-tutorial-with-ruby/)
5
4
  def unary_echo(req, _unused_call)
6
5
  Test::EchoResponse.new(message: req.message)
7
6
  end
8
7
 
9
- # Client‑streaming: collect all incoming messages into one response [oai_citation_attribution:3‡Medium](https://alessiobussolari.medium.com/integrating-grpc-with-ruby-on-rails-2b2a203107d5?utm_source=chatgpt.com)
10
8
  def client_stream(stream, _call)
11
9
  msgs = stream.map(&:message)
12
10
  Test::StreamResponse.new(messages: msgs)
13
11
  end
14
12
 
15
- # Server‑streaming: send back one StreamResponse per incoming request, with each char [oai_citation_attribution:4‡Medium](https://alessiobussolari.medium.com/integrating-grpc-with-ruby-on-rails-2b2a203107d5?utm_source=chatgpt.com)
16
13
  def server_stream(req, _call)
17
14
  Enumerator.new do |y|
18
15
  req.message.each_char { |c| y << Test::StreamResponse.new(messages: [c]) }
19
16
  end
20
17
  end
21
18
 
22
- # Bidirectional: for each incoming EchoRequest, immediately echo it back [oai_citation_attribution:5‡Medium](https://alessiobussolari.medium.com/integrating-grpc-with-ruby-on-rails-2b2a203107d5?utm_source=chatgpt.com)
23
19
  def bidi_stream(stream, _call)
24
20
  Enumerator.new do |y|
25
21
  stream.each { |req| y << Test::EchoResponse.new(message: req.message.upcase) }
@@ -6,7 +6,7 @@ require_relative 'test_service_pb'
6
6
 
7
7
  module Test
8
8
  module TestService
9
- # A service with one of each RPC type [oai_citation_attribution:0‡Википедия — свободная энциклопедия](https://ru.wikipedia.org/wiki/GRPC?utm_source=chatgpt.com)
9
+
10
10
  class Service
11
11
 
12
12
  include ::GRPC::GenericService
data/lib/itsi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Itsi
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.6"
3
3
  end
data/tasks.txt CHANGED
@@ -1,6 +1,8 @@
1
- Tasks:
1
+ 0.2.6:
2
+ - Opt in to gRPC compression override, per endpoint or per service
3
+
2
4
  - Static ruby build
3
- - Add way to opt non Itsi.rb files into LSP
5
+ - Add hook to opt non Itsi.rb files into LSP
4
6
  - OTel
5
7
  - Even faster Hash creation for Rack
6
8
  - Image resizer
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itsi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wouter Coppieters
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.4
18
+ version: 0.2.6
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.2.4
25
+ version: 0.2.6
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: itsi-server
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.2.4
32
+ version: 0.2.6
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.2.4
39
+ version: 0.2.6
40
40
  description: Wrapper Gem for both the Itsi server and the Itsi Fiber scheduler
41
41
  email:
42
42
  - wc@pico.net.nz
@@ -217,6 +217,30 @@ files:
217
217
  - docs/go.mod
218
218
  - docs/go.sum
219
219
  - docs/hugo.yaml
220
+ - docs/static/android-chrome-192x192.png
221
+ - docs/static/android-chrome-310x310.png
222
+ - docs/static/apple-touch-icon.png
223
+ - docs/static/browserconfig.xml
224
+ - docs/static/favicon-114x114.png
225
+ - docs/static/favicon-120x120.png
226
+ - docs/static/favicon-144x144.png
227
+ - docs/static/favicon-150x150.png
228
+ - docs/static/favicon-152x152.png
229
+ - docs/static/favicon-16x16.png
230
+ - docs/static/favicon-180x180.png
231
+ - docs/static/favicon-192x192.png
232
+ - docs/static/favicon-310x310.png
233
+ - docs/static/favicon-32x32.png
234
+ - docs/static/favicon-57x57.png
235
+ - docs/static/favicon-60x60.png
236
+ - docs/static/favicon-70x70.png
237
+ - docs/static/favicon-72x72.png
238
+ - docs/static/favicon-76x76.png
239
+ - docs/static/favicon-96x96.png
240
+ - docs/static/favicon-dark.svg
241
+ - docs/static/favicon.ico
242
+ - docs/static/favicon.svg
243
+ - docs/static/site.webmanifest
220
244
  - examples/api_with_schema_and_controllers/Itsi.rb
221
245
  - examples/api_with_schema_and_controllers/README.md
222
246
  - examples/api_with_schema_and_controllers/controllers.rb