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.
- checksums.yaml +4 -4
- data/Cargo.lock +15 -15
- data/ext/itsi_scheduler/Cargo.toml +1 -1
- data/ext/itsi_scheduler/extconf.rb +3 -1
- data/ext/itsi_server/Cargo.lock +1 -1
- data/ext/itsi_server/Cargo.toml +1 -1
- data/ext/itsi_server/src/lib.rs +1 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +2 -2
- data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +9 -11
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +6 -1
- data/ext/itsi_server/src/server/binds/listener.rs +4 -1
- data/ext/itsi_server/src/server/http_message_types.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +32 -34
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +3 -4
- data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +23 -38
- data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
- data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +12 -3
- data/ext/itsi_server/src/server/process_worker.rs +2 -1
- data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +96 -0
- data/ext/itsi_server/src/server/serve_strategy/mod.rs +1 -0
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +80 -136
- data/ext/itsi_server/src/server/thread_worker.rs +10 -3
- data/ext/itsi_server/src/services/itsi_http_service.rs +26 -21
- data/ext/itsi_server/src/services/mime_types.rs +185 -183
- data/ext/itsi_server/src/services/rate_limiter.rs +16 -34
- data/ext/itsi_server/src/services/static_file_server.rs +7 -13
- data/lib/itsi/scheduler/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5caaaee4ce54ed5b10274bf22f26b2b232ea414844609419b8cd54dbb67cd4b1
|
4
|
+
data.tar.gz: 8ab4bc34382d142d421e401aa6155a16a8e9684d1129cc29ea286f4f94d6a8c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
77
|
+
version = "1.2.20"
|
78
78
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
79
|
-
checksum = "
|
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.
|
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.
|
169
|
+
version = "0.2.16"
|
170
170
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
171
|
-
checksum = "
|
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.
|
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.
|
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.
|
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.
|
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.
|
701
|
+
version = "2.0.101"
|
702
702
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
703
|
-
checksum = "
|
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.
|
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.
|
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.
|
822
|
+
"syn 2.0.101",
|
823
823
|
]
|
824
824
|
|
825
825
|
[[package]]
|
data/ext/itsi_server/Cargo.lock
CHANGED
@@ -111,7 +111,7 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
|
111
111
|
|
112
112
|
[[package]]
|
113
113
|
name = "atty"
|
114
|
-
version = "0.2.
|
114
|
+
version = "0.2.16"
|
115
115
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
116
116
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
117
117
|
dependencies = [
|
data/ext/itsi_server/Cargo.toml
CHANGED
data/ext/itsi_server/src/lib.rs
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
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
|
-
|
194
|
-
|
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
|
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.
|
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.
|
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.
|
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
|
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();
|
data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs
CHANGED
@@ -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::
|
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(
|
12
|
-
404 => ContentSource::Static(
|
13
|
-
401 => ContentSource::Static(
|
14
|
-
403 => ContentSource::Static(
|
15
|
-
413 => ContentSource::Static(
|
16
|
-
429 => ContentSource::Static(
|
17
|
-
502 => ContentSource::Static(
|
18
|
-
503 => ContentSource::Static(
|
19
|
-
504 => ContentSource::Static(
|
20
|
-
_ => ContentSource::Static(
|
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(
|
23
|
+
500 => ContentSource::Static(Full::new(
|
24
24
|
include_str!("../../../../default_responses/html/500.html").into(),
|
25
25
|
)),
|
26
|
-
404 => ContentSource::Static(
|
26
|
+
404 => ContentSource::Static(Full::new(
|
27
27
|
include_str!("../../../../default_responses/html/404.html").into(),
|
28
28
|
)),
|
29
|
-
401 => ContentSource::Static(
|
29
|
+
401 => ContentSource::Static(Full::new(
|
30
30
|
include_str!("../../../../default_responses/html/401.html").into(),
|
31
31
|
)),
|
32
|
-
403 => ContentSource::Static(
|
32
|
+
403 => ContentSource::Static(Full::new(
|
33
33
|
include_str!("../../../../default_responses/html/403.html").into(),
|
34
34
|
)),
|
35
|
-
413 => ContentSource::Static(
|
35
|
+
413 => ContentSource::Static(Full::new(
|
36
36
|
include_str!("../../../../default_responses/html/413.html").into(),
|
37
37
|
)),
|
38
|
-
429 => ContentSource::Static(
|
38
|
+
429 => ContentSource::Static(Full::new(
|
39
39
|
include_str!("../../../../default_responses/html/429.html").into(),
|
40
40
|
)),
|
41
|
-
502 => ContentSource::Static(
|
41
|
+
502 => ContentSource::Static(Full::new(
|
42
42
|
include_str!("../../../../default_responses/html/502.html").into(),
|
43
43
|
)),
|
44
|
-
503 => ContentSource::Static(
|
44
|
+
503 => ContentSource::Static(Full::new(
|
45
45
|
include_str!("../../../../default_responses/html/503.html").into(),
|
46
46
|
)),
|
47
|
-
504 => ContentSource::Static(
|
47
|
+
504 => ContentSource::Static(Full::new(
|
48
48
|
include_str!("../../../../default_responses/html/504.html").into(),
|
49
49
|
)),
|
50
|
-
_ => ContentSource::Static(
|
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(
|
55
|
+
500 => ContentSource::Static(Full::new(
|
56
56
|
include_str!("../../../../default_responses/json/500.json").into(),
|
57
57
|
)),
|
58
|
-
404 => ContentSource::Static(
|
58
|
+
404 => ContentSource::Static(Full::new(
|
59
59
|
include_str!("../../../../default_responses/json/404.json").into(),
|
60
60
|
)),
|
61
|
-
401 => ContentSource::Static(
|
61
|
+
401 => ContentSource::Static(Full::new(
|
62
62
|
include_str!("../../../../default_responses/json/401.json").into(),
|
63
63
|
)),
|
64
|
-
403 => ContentSource::Static(
|
64
|
+
403 => ContentSource::Static(Full::new(
|
65
65
|
include_str!("../../../../default_responses/json/403.json").into(),
|
66
66
|
)),
|
67
|
-
413 => ContentSource::Static(
|
67
|
+
413 => ContentSource::Static(Full::new(
|
68
68
|
include_str!("../../../../default_responses/json/413.json").into(),
|
69
69
|
)),
|
70
|
-
429 => ContentSource::Static(
|
70
|
+
429 => ContentSource::Static(Full::new(
|
71
71
|
include_str!("../../../../default_responses/json/429.json").into(),
|
72
72
|
)),
|
73
|
-
502 => ContentSource::Static(
|
73
|
+
502 => ContentSource::Static(Full::new(
|
74
74
|
include_str!("../../../../default_responses/json/502.json").into(),
|
75
75
|
)),
|
76
|
-
503 => ContentSource::Static(
|
76
|
+
503 => ContentSource::Static(Full::new(
|
77
77
|
include_str!("../../../../default_responses/json/503.json").into(),
|
78
78
|
)),
|
79
|
-
504 => ContentSource::Static(
|
79
|
+
504 => ContentSource::Static(Full::new(
|
80
80
|
include_str!("../../../../default_responses/json/504.json").into(),
|
81
81
|
)),
|
82
|
-
_ => ContentSource::Static(
|
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(
|
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(
|
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(
|
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
|
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
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
159
|
-
if
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
&header::
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
}
|