itsi-scheduler 0.2.15 → 0.2.16

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +15 -15
  3. data/ext/itsi_scheduler/Cargo.toml +1 -1
  4. data/ext/itsi_scheduler/extconf.rb +3 -1
  5. data/ext/itsi_server/Cargo.lock +1 -1
  6. data/ext/itsi_server/Cargo.toml +1 -1
  7. data/ext/itsi_server/src/lib.rs +1 -0
  8. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +2 -2
  9. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +9 -11
  10. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +6 -1
  11. data/ext/itsi_server/src/server/binds/listener.rs +4 -1
  12. data/ext/itsi_server/src/server/http_message_types.rs +1 -1
  13. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +32 -34
  14. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +3 -4
  15. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +23 -38
  16. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
  17. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
  18. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +1 -1
  19. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
  20. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
  21. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +12 -3
  22. data/ext/itsi_server/src/server/process_worker.rs +2 -1
  23. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +96 -0
  24. data/ext/itsi_server/src/server/serve_strategy/mod.rs +1 -0
  25. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +80 -136
  26. data/ext/itsi_server/src/server/thread_worker.rs +10 -3
  27. data/ext/itsi_server/src/services/itsi_http_service.rs +26 -21
  28. data/ext/itsi_server/src/services/mime_types.rs +185 -183
  29. data/ext/itsi_server/src/services/rate_limiter.rs +16 -34
  30. data/ext/itsi_server/src/services/static_file_server.rs +7 -13
  31. data/lib/itsi/scheduler/version.rb +1 -1
  32. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24a6d189fe27eca28e684fa4093434a9970585fb51c3a80084153f10fbc62713
4
- data.tar.gz: deba83cb54b75bacae1a0ebefa7dd12ec7b74385934fd72be6cdabae8093b96d
3
+ metadata.gz: 5caaaee4ce54ed5b10274bf22f26b2b232ea414844609419b8cd54dbb67cd4b1
4
+ data.tar.gz: 8ab4bc34382d142d421e401aa6155a16a8e9684d1129cc29ea286f4f94d6a8c8
5
5
  SHA512:
6
- metadata.gz: 6da8425690bfe5e5afa008a9a717abe2cd25ceb0729c916913eb2e4f84419ba83b72768d7021f909c43261fa5031d4d837c718e04eac1f8513a76f74f756d181
7
- data.tar.gz: 14c2bcccf5f5b73590454b20ab2412064cf5b603d9fc10cdc32383a7693b2889a7bc46f62566cc694cee432ccf422287fa245d0dda629eeae80da10904e55038
6
+ metadata.gz: b51bccdd42078f880c2bcdc58826b1162499604b02d96eef3ea94c152e2f70628188d99575481ed20a82201ffa73a6dfc19b25ac6cc11f94dc9a573135010bee
7
+ data.tar.gz: acb1db014fefa155ab42204965641e6f02e91e7b5e4ba58de435694812109248ef2435753f923a2bef68104e71ad72b08020fce4eedc140f6e623e054ae830ee
data/Cargo.lock CHANGED
@@ -57,7 +57,7 @@ dependencies = [
57
57
  "regex",
58
58
  "rustc-hash",
59
59
  "shlex",
60
- "syn 2.0.100",
60
+ "syn 2.0.101",
61
61
  ]
62
62
 
63
63
  [[package]]
@@ -74,9 +74,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
74
74
 
75
75
  [[package]]
76
76
  name = "cc"
77
- version = "1.2.19"
77
+ version = "1.2.20"
78
78
  source = "registry+https://github.com/rust-lang/crates.io-index"
79
- checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
79
+ checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
80
80
  dependencies = [
81
81
  "shlex",
82
82
  ]
@@ -154,7 +154,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
154
154
  dependencies = [
155
155
  "proc-macro2",
156
156
  "quote",
157
- "syn 2.0.100",
157
+ "syn 2.0.101",
158
158
  "unicode-xid",
159
159
  ]
160
160
 
@@ -166,9 +166,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
166
166
 
167
167
  [[package]]
168
168
  name = "getrandom"
169
- version = "0.2.15"
169
+ version = "0.2.16"
170
170
  source = "registry+https://github.com/rust-lang/crates.io-index"
171
- checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
171
+ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
172
172
  dependencies = [
173
173
  "cfg-if",
174
174
  "libc",
@@ -213,7 +213,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
213
213
 
214
214
  [[package]]
215
215
  name = "itsi-scheduler"
216
- version = "0.2.15"
216
+ version = "0.2.16"
217
217
  dependencies = [
218
218
  "bytes",
219
219
  "derive_more",
@@ -337,7 +337,7 @@ checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3"
337
337
  dependencies = [
338
338
  "proc-macro2",
339
339
  "quote",
340
- "syn 2.0.100",
340
+ "syn 2.0.101",
341
341
  ]
342
342
 
343
343
  [[package]]
@@ -507,7 +507,7 @@ dependencies = [
507
507
  "quote",
508
508
  "regex",
509
509
  "shell-words",
510
- "syn 2.0.100",
510
+ "syn 2.0.101",
511
511
  ]
512
512
 
513
513
  [[package]]
@@ -643,7 +643,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
643
643
  dependencies = [
644
644
  "proc-macro2",
645
645
  "quote",
646
- "syn 2.0.100",
646
+ "syn 2.0.101",
647
647
  ]
648
648
 
649
649
  [[package]]
@@ -698,9 +698,9 @@ dependencies = [
698
698
 
699
699
  [[package]]
700
700
  name = "syn"
701
- version = "2.0.100"
701
+ version = "2.0.101"
702
702
  source = "registry+https://github.com/rust-lang/crates.io-index"
703
- checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
703
+ checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
704
704
  dependencies = [
705
705
  "proc-macro2",
706
706
  "quote",
@@ -733,7 +733,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
733
733
  dependencies = [
734
734
  "proc-macro2",
735
735
  "quote",
736
- "syn 2.0.100",
736
+ "syn 2.0.101",
737
737
  ]
738
738
 
739
739
  [[package]]
@@ -744,7 +744,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
744
744
  dependencies = [
745
745
  "proc-macro2",
746
746
  "quote",
747
- "syn 2.0.100",
747
+ "syn 2.0.101",
748
748
  ]
749
749
 
750
750
  [[package]]
@@ -819,7 +819,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
819
819
  dependencies = [
820
820
  "proc-macro2",
821
821
  "quote",
822
- "syn 2.0.100",
822
+ "syn 2.0.101",
823
823
  ]
824
824
 
825
825
  [[package]]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-scheduler"
3
- version = "0.2.15"
3
+ version = "0.2.16"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -3,4 +3,6 @@
3
3
  require "mkmf"
4
4
  require "rb_sys/mkmf"
5
5
 
6
- create_rust_makefile("itsi/scheduler/itsi_scheduler")
6
+ create_rust_makefile("itsi/scheduler/itsi_scheduler") do |r|
7
+ r.extra_rustflags = ["-C target-cpu=native"]
8
+ end
@@ -111,7 +111,7 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
111
111
 
112
112
  [[package]]
113
113
  name = "atty"
114
- version = "0.2.15"
114
+ version = "0.2.16"
115
115
  source = "registry+https://github.com/rust-lang/crates.io-index"
116
116
  checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
117
117
  dependencies = [
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-server"
3
- version = "0.2.15"
3
+ version = "0.2.16"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -1,4 +1,5 @@
1
1
  #![deny(unused_crate_dependencies)]
2
+
2
3
  pub mod default_responses;
3
4
  pub mod env;
4
5
  pub mod prelude;
@@ -126,12 +126,12 @@ impl ItsiGrpcCall {
126
126
  nonblocking: bool,
127
127
  ) -> itsi_error::Result<HttpResponse> {
128
128
  let (request, mut receiver) = ItsiGrpcCall::new(hyper_request, context).await;
129
- let shutdown_channel = context.service.shutdown_channel.clone();
129
+ let shutdown_channel = context.service.shutdown_receiver.clone();
130
130
  let response_stream = request.stream.clone();
131
131
  let sender = if nonblocking {
132
132
  &context.nonblocking_sender
133
133
  } else {
134
- &context.sender
134
+ &context.job_sender
135
135
  };
136
136
  match sender
137
137
  .send(RequestJob::ProcessGrpcRequest(request, app))
@@ -180,24 +180,22 @@ impl ItsiHttpRequest {
180
180
  ) -> itsi_error::Result<HttpResponse> {
181
181
  match ItsiHttpRequest::new(hyper_request, context, script_name).await {
182
182
  Ok((request, mut receiver)) => {
183
- let shutdown_channel = context.service.shutdown_channel.clone();
183
+ let shutdown_channel = context.service.shutdown_receiver.clone();
184
184
  let response = request.response.clone();
185
185
  let sender = if nonblocking {
186
186
  &context.nonblocking_sender
187
187
  } else {
188
- &context.sender
188
+ &context.job_sender
189
189
  };
190
190
  match sender.try_send(RequestJob::ProcessHttpRequest(request, app)) {
191
191
  Err(err) => match err {
192
- async_channel::TrySendError::Full(_) => {
193
- Ok(SERVICE_UNAVAILABLE_RESPONSE
194
- .to_http_response(context.accept.clone())
195
- .await)
196
- }
192
+ async_channel::TrySendError::Full(_) => Ok(SERVICE_UNAVAILABLE_RESPONSE
193
+ .to_http_response(context.accept)
194
+ .await),
197
195
  async_channel::TrySendError::Closed(err) => {
198
196
  error!("Error occurred: {:?}", err);
199
197
  Ok(INTERNAL_SERVER_ERROR_RESPONSE
200
- .to_http_response(context.accept.clone())
198
+ .to_http_response(context.accept)
201
199
  .await)
202
200
  }
203
201
  },
@@ -309,7 +307,7 @@ impl ItsiHttpRequest {
309
307
  .parts
310
308
  .uri
311
309
  .host()
312
- .unwrap_or_else(|| &self.context.listener.host))
310
+ .unwrap_or_else(|| &self.context.listener_info.host))
313
311
  }
314
312
 
315
313
  pub(crate) fn scheme(&self) -> MagnusResult<&str> {
@@ -318,7 +316,7 @@ impl ItsiHttpRequest {
318
316
  .uri
319
317
  .scheme()
320
318
  .map(|scheme| scheme.as_str())
321
- .unwrap_or_else(|| &self.context.listener.scheme))
319
+ .unwrap_or_else(|| &self.context.listener_info.scheme))
322
320
  }
323
321
 
324
322
  pub(crate) fn headers(&self) -> MagnusResult<Vec<(&str, &str)>> {
@@ -354,7 +352,7 @@ impl ItsiHttpRequest {
354
352
  .parts
355
353
  .uri
356
354
  .port_u16()
357
- .unwrap_or(self.context.listener.port))
355
+ .unwrap_or(self.context.listener_info.port))
358
356
  }
359
357
 
360
358
  pub(crate) fn body(&self) -> MagnusResult<Option<Value>> {
@@ -82,7 +82,7 @@ pub struct ServerParams {
82
82
  preexisting_listeners: Option<String>,
83
83
  }
84
84
 
85
- #[derive(Debug, Clone)]
85
+ #[derive(Debug, Clone, Copy)]
86
86
  pub enum ItsiServerTokenPreference {
87
87
  Version,
88
88
  Name,
@@ -109,6 +109,7 @@ pub struct SocketOpts {
109
109
  pub listen_backlog: usize,
110
110
  pub nodelay: bool,
111
111
  pub recv_buffer_size: usize,
112
+ pub send_buffer_size: usize,
112
113
  }
113
114
 
114
115
  impl ServerParams {
@@ -248,6 +249,9 @@ impl ServerParams {
248
249
  let recv_buffer_size: usize = rb_param_hash
249
250
  .fetch::<_, Option<usize>>("recv_buffer_size")?
250
251
  .unwrap_or(262_144);
252
+ let send_buffer_size: usize = rb_param_hash
253
+ .fetch::<_, Option<usize>>("send_buffer_size")?
254
+ .unwrap_or(262_144);
251
255
 
252
256
  if let Some(level) = log_level {
253
257
  set_level(&level);
@@ -296,6 +300,7 @@ impl ServerParams {
296
300
  listen_backlog,
297
301
  nodelay,
298
302
  recv_buffer_size,
303
+ send_buffer_size,
299
304
  };
300
305
  let preexisting_listeners = rb_param_hash.delete::<_, Option<String>>("listeners")?;
301
306
 
@@ -111,7 +111,7 @@ impl TokioListener {
111
111
  Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
112
112
  }
113
113
 
114
- pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
114
+ pub async fn spawn_acme_event_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
115
115
  if let TokioListener::TcpTls(
116
116
  _,
117
117
  ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
@@ -414,6 +414,9 @@ fn connect_tcp_socket(addr: IpAddr, port: u16, socket_opts: &SocketOpts) -> Resu
414
414
  socket.set_reuse_port(socket_opts.reuse_port).ok();
415
415
  socket.set_nonblocking(true).ok();
416
416
  socket.set_nodelay(socket_opts.nodelay).ok();
417
+ socket
418
+ .set_send_buffer_size(socket_opts.send_buffer_size)
419
+ .ok();
417
420
  socket
418
421
  .set_recv_buffer_size(socket_opts.recv_buffer_size)
419
422
  .ok();
@@ -32,7 +32,7 @@ pub trait PathExt {
32
32
  fn no_trailing_slash(&self) -> &str;
33
33
  }
34
34
 
35
- #[derive(Debug, Clone)]
35
+ #[derive(Debug, Clone, Copy)]
36
36
  pub enum ResponseFormat {
37
37
  JSON,
38
38
  HTML,
@@ -2,84 +2,84 @@ use super::{ContentSource, DefaultFormat, ErrorResponse};
2
2
  use crate::server::http_message_types::ResponseFormat;
3
3
  use bytes::Bytes;
4
4
  use http_body_util::{combinators::BoxBody, Full};
5
- use std::{convert::Infallible, sync::Arc};
5
+ use std::convert::Infallible;
6
6
 
7
7
  impl DefaultFormat {
8
8
  pub fn response_for_code(&self, code: u16) -> ContentSource {
9
9
  match self {
10
10
  DefaultFormat::Plaintext => match code {
11
- 500 => ContentSource::Static(Arc::new("500 Internal Error".into())),
12
- 404 => ContentSource::Static(Arc::new("404 Not Found".into())),
13
- 401 => ContentSource::Static(Arc::new("401 Unauthorized".into())),
14
- 403 => ContentSource::Static(Arc::new("403 Forbidden".into())),
15
- 413 => ContentSource::Static(Arc::new("413 Payload Too Large".into())),
16
- 429 => ContentSource::Static(Arc::new("429 Too Many Requests".into())),
17
- 502 => ContentSource::Static(Arc::new("502 Bad Gateway".into())),
18
- 503 => ContentSource::Static(Arc::new("503 Service Unavailable".into())),
19
- 504 => ContentSource::Static(Arc::new("504 Gateway Timeout".into())),
20
- _ => ContentSource::Static(Arc::new("Unexpected Error".into())),
11
+ 500 => ContentSource::Static(Full::new("500 Internal Error".into())),
12
+ 404 => ContentSource::Static(Full::new("404 Not Found".into())),
13
+ 401 => ContentSource::Static(Full::new("401 Unauthorized".into())),
14
+ 403 => ContentSource::Static(Full::new("403 Forbidden".into())),
15
+ 413 => ContentSource::Static(Full::new("413 Payload Too Large".into())),
16
+ 429 => ContentSource::Static(Full::new("429 Too Many Requests".into())),
17
+ 502 => ContentSource::Static(Full::new("502 Bad Gateway".into())),
18
+ 503 => ContentSource::Static(Full::new("503 Service Unavailable".into())),
19
+ 504 => ContentSource::Static(Full::new("504 Gateway Timeout".into())),
20
+ _ => ContentSource::Static(Full::new("Unexpected Error".into())),
21
21
  },
22
22
  DefaultFormat::Html => match code {
23
- 500 => ContentSource::Static(Arc::new(
23
+ 500 => ContentSource::Static(Full::new(
24
24
  include_str!("../../../../default_responses/html/500.html").into(),
25
25
  )),
26
- 404 => ContentSource::Static(Arc::new(
26
+ 404 => ContentSource::Static(Full::new(
27
27
  include_str!("../../../../default_responses/html/404.html").into(),
28
28
  )),
29
- 401 => ContentSource::Static(Arc::new(
29
+ 401 => ContentSource::Static(Full::new(
30
30
  include_str!("../../../../default_responses/html/401.html").into(),
31
31
  )),
32
- 403 => ContentSource::Static(Arc::new(
32
+ 403 => ContentSource::Static(Full::new(
33
33
  include_str!("../../../../default_responses/html/403.html").into(),
34
34
  )),
35
- 413 => ContentSource::Static(Arc::new(
35
+ 413 => ContentSource::Static(Full::new(
36
36
  include_str!("../../../../default_responses/html/413.html").into(),
37
37
  )),
38
- 429 => ContentSource::Static(Arc::new(
38
+ 429 => ContentSource::Static(Full::new(
39
39
  include_str!("../../../../default_responses/html/429.html").into(),
40
40
  )),
41
- 502 => ContentSource::Static(Arc::new(
41
+ 502 => ContentSource::Static(Full::new(
42
42
  include_str!("../../../../default_responses/html/502.html").into(),
43
43
  )),
44
- 503 => ContentSource::Static(Arc::new(
44
+ 503 => ContentSource::Static(Full::new(
45
45
  include_str!("../../../../default_responses/html/503.html").into(),
46
46
  )),
47
- 504 => ContentSource::Static(Arc::new(
47
+ 504 => ContentSource::Static(Full::new(
48
48
  include_str!("../../../../default_responses/html/504.html").into(),
49
49
  )),
50
- _ => ContentSource::Static(Arc::new(
50
+ _ => ContentSource::Static(Full::new(
51
51
  include_str!("../../../../default_responses/html/500.html").into(),
52
52
  )),
53
53
  },
54
54
  DefaultFormat::Json => match code {
55
- 500 => ContentSource::Static(Arc::new(
55
+ 500 => ContentSource::Static(Full::new(
56
56
  include_str!("../../../../default_responses/json/500.json").into(),
57
57
  )),
58
- 404 => ContentSource::Static(Arc::new(
58
+ 404 => ContentSource::Static(Full::new(
59
59
  include_str!("../../../../default_responses/json/404.json").into(),
60
60
  )),
61
- 401 => ContentSource::Static(Arc::new(
61
+ 401 => ContentSource::Static(Full::new(
62
62
  include_str!("../../../../default_responses/json/401.json").into(),
63
63
  )),
64
- 403 => ContentSource::Static(Arc::new(
64
+ 403 => ContentSource::Static(Full::new(
65
65
  include_str!("../../../../default_responses/json/403.json").into(),
66
66
  )),
67
- 413 => ContentSource::Static(Arc::new(
67
+ 413 => ContentSource::Static(Full::new(
68
68
  include_str!("../../../../default_responses/json/413.json").into(),
69
69
  )),
70
- 429 => ContentSource::Static(Arc::new(
70
+ 429 => ContentSource::Static(Full::new(
71
71
  include_str!("../../../../default_responses/json/429.json").into(),
72
72
  )),
73
- 502 => ContentSource::Static(Arc::new(
73
+ 502 => ContentSource::Static(Full::new(
74
74
  include_str!("../../../../default_responses/json/502.json").into(),
75
75
  )),
76
- 503 => ContentSource::Static(Arc::new(
76
+ 503 => ContentSource::Static(Full::new(
77
77
  include_str!("../../../../default_responses/json/503.json").into(),
78
78
  )),
79
- 504 => ContentSource::Static(Arc::new(
79
+ 504 => ContentSource::Static(Full::new(
80
80
  include_str!("../../../../default_responses/json/504.json").into(),
81
81
  )),
82
- _ => ContentSource::Static(Arc::new("Unexpected Error".into())),
82
+ _ => ContentSource::Static(Full::new("Unexpected Error".into())),
83
83
  },
84
84
  }
85
85
  }
@@ -94,9 +94,7 @@ impl ErrorResponse {
94
94
  };
95
95
  match source {
96
96
  ContentSource::Inline(bytes) => BoxBody::new(Full::new(Bytes::from(bytes))),
97
- ContentSource::Static(text) => {
98
- BoxBody::new(Full::new(Bytes::from(String::from(text.as_str()))))
99
- }
97
+ ContentSource::Static(bytes) => BoxBody::new(bytes),
100
98
  ContentSource::File(_) => BoxBody::new(Full::new(Bytes::from("Unexpected error"))),
101
99
  }
102
100
  }
@@ -5,7 +5,6 @@ use http_body_util::{combinators::BoxBody, Full};
5
5
  use serde::{Deserialize, Deserializer};
6
6
  use std::convert::Infallible;
7
7
  use std::path::PathBuf;
8
- use std::sync::Arc;
9
8
  use tracing::warn;
10
9
 
11
10
  use crate::server::http_message_types::{HttpResponse, ResponseFormat};
@@ -20,7 +19,7 @@ pub enum ContentSource {
20
19
  File(PathBuf),
21
20
  #[serde(rename(deserialize = "static"))]
22
21
  #[serde(skip_deserializing)]
23
- Static(Arc<String>),
22
+ Static(Full<Bytes>),
24
23
  }
25
24
 
26
25
  #[derive(Debug, Clone, Deserialize, Default)]
@@ -151,13 +150,13 @@ impl ErrorResponse {
151
150
  return BoxBody::new(Full::new(Bytes::from(text.clone())));
152
151
  }
153
152
  Some(ContentSource::Static(text)) => {
154
- return BoxBody::new(Full::new(Bytes::from(String::from(text.as_str()))));
153
+ return BoxBody::new(text.clone());
155
154
  }
156
155
  Some(ContentSource::File(path)) => {
157
156
  // Convert the PathBuf to a &str (assumes valid UTF-8).
158
157
  if let Some(path_str) = path.to_str() {
159
158
  let response = ROOT_STATIC_FILE_SERVER
160
- .serve_single(path_str, accept.clone(), &[])
159
+ .serve_single(path_str, accept, &[])
161
160
  .await;
162
161
  if response.status().is_success() {
163
162
  return response.into_body();
@@ -43,12 +43,6 @@ pub struct ETag {
43
43
  pub algorithm: HashAlgorithm,
44
44
  #[serde(default)]
45
45
  pub min_body_size: usize,
46
- #[serde(default = "default_true")]
47
- pub handle_if_none_match: bool,
48
- }
49
-
50
- fn default_true() -> bool {
51
- true
52
46
  }
53
47
 
54
48
  #[async_trait]
@@ -59,14 +53,13 @@ impl MiddlewareLayer for ETag {
59
53
  context: &mut HttpRequestContext,
60
54
  ) -> Result<Either<HttpRequest, HttpResponse>> {
61
55
  // Store if-none-match header in context if present for later use in after hook
62
- if self.handle_if_none_match {
63
- if let Some(if_none_match) = req.headers().get(header::IF_NONE_MATCH) {
64
- debug!(target: "middleware::etag", "Received If-None-Match header: {:?}", if_none_match);
65
- if let Ok(etag_value) = if_none_match.to_str() {
66
- context.set_if_none_match(Some(etag_value.to_string()));
67
- }
56
+ if let Some(if_none_match) = req.headers().get(header::IF_NONE_MATCH) {
57
+ debug!(target: "middleware::etag", "Received If-None-Match header: {:?}", if_none_match);
58
+ if let Ok(etag_value) = if_none_match.to_str() {
59
+ context.set_if_none_match(Some(etag_value.to_string()));
68
60
  }
69
61
  }
62
+
70
63
  Ok(Either::Left(req))
71
64
  }
72
65
 
@@ -85,11 +78,6 @@ impl MiddlewareLayer for ETag {
85
78
  }
86
79
  }
87
80
 
88
- if resp.headers().contains_key(header::ETAG) {
89
- debug!(target: "middleware::etag", "Forwarding response with existing ETag");
90
- return resp;
91
- }
92
-
93
81
  if let Some(cache_control) = resp.headers().get(header::CACHE_CONTROL) {
94
82
  if let Ok(cache_control_str) = cache_control.to_str() {
95
83
  if cache_control_str.contains("no-store") {
@@ -155,28 +143,26 @@ impl MiddlewareLayer for ETag {
155
143
  formatted_etag
156
144
  };
157
145
 
158
- if self.handle_if_none_match {
159
- if let Some(if_none_match) = context.get_if_none_match() {
160
- if if_none_match == etag_value || if_none_match == "*" {
161
- // Return 304 Not Modified without the body
162
- let mut not_modified = Response::new(BoxBody::new(Empty::new()));
163
- *not_modified.status_mut() = StatusCode::NOT_MODIFIED;
164
- // Copy headers we want to preserve
165
- for (name, value) in parts.headers.iter() {
166
- if matches!(
167
- name,
168
- &header::CACHE_CONTROL
169
- | &header::CONTENT_LOCATION
170
- | &header::DATE
171
- | &header::ETAG
172
- | &header::EXPIRES
173
- | &header::VARY
174
- ) {
175
- not_modified.headers_mut().insert(name, value.clone());
176
- }
146
+ if let Some(if_none_match) = context.get_if_none_match() {
147
+ if if_none_match == etag_value || if_none_match == "*" {
148
+ // Return 304 Not Modified without the body
149
+ let mut not_modified = Response::new(BoxBody::new(Empty::new()));
150
+ *not_modified.status_mut() = StatusCode::NOT_MODIFIED;
151
+ // Copy headers we want to preserve
152
+ for (name, value) in parts.headers.iter() {
153
+ if matches!(
154
+ name,
155
+ &header::CACHE_CONTROL
156
+ | &header::CONTENT_LOCATION
157
+ | &header::DATE
158
+ | &header::ETAG
159
+ | &header::EXPIRES
160
+ | &header::VARY
161
+ ) {
162
+ not_modified.headers_mut().insert(name, value.clone());
177
163
  }
178
- return not_modified;
179
164
  }
165
+ return not_modified;
180
166
  }
181
167
  }
182
168
 
@@ -190,7 +176,6 @@ impl Default for ETag {
190
176
  r#type: ETagType::Strong,
191
177
  algorithm: HashAlgorithm::Sha256,
192
178
  min_body_size: 0,
193
- handle_if_none_match: true,
194
179
  }
195
180
  }
196
181
  }