itsi-scheduler 0.2.16 → 0.2.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.
- checksums.yaml +4 -4
- data/Cargo.lock +1 -1
- data/ext/itsi_acme/Cargo.toml +1 -1
- data/ext/itsi_scheduler/Cargo.toml +1 -1
- data/ext/itsi_server/Cargo.toml +3 -1
- data/ext/itsi_server/src/lib.rs +6 -1
- data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +2 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +4 -4
- data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +14 -13
- data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +64 -33
- data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +151 -152
- data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +422 -110
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +62 -15
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +1 -1
- data/ext/itsi_server/src/server/binds/listener.rs +45 -7
- data/ext/itsi_server/src/server/frame_stream.rs +142 -0
- data/ext/itsi_server/src/server/http_message_types.rs +142 -9
- data/ext/itsi_server/src/server/io_stream.rs +28 -5
- data/ext/itsi_server/src/server/lifecycle_event.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +8 -10
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +3 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +54 -56
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +5 -7
- data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +5 -5
- data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +7 -10
- data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +1 -2
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +4 -6
- data/ext/itsi_server/src/server/mod.rs +1 -0
- data/ext/itsi_server/src/server/process_worker.rs +3 -4
- data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +16 -12
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +83 -31
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +166 -142
- data/ext/itsi_server/src/server/signal.rs +37 -9
- data/ext/itsi_server/src/server/thread_worker.rs +84 -69
- data/ext/itsi_server/src/services/itsi_http_service.rs +43 -43
- data/ext/itsi_server/src/services/static_file_server.rs +28 -47
- data/lib/itsi/scheduler/version.rb +1 -1
- metadata +2 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
use crate::{
|
2
|
-
server::http_message_types::{HttpRequest, HttpResponse},
|
2
|
+
server::http_message_types::{HttpBody, HttpRequest, HttpResponse},
|
3
3
|
services::itsi_http_service::HttpRequestContext,
|
4
4
|
};
|
5
5
|
|
@@ -20,8 +20,8 @@ use http::{
|
|
20
20
|
header::{GetAll, CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TYPE},
|
21
21
|
HeaderValue, Response,
|
22
22
|
};
|
23
|
-
use http_body_util::{
|
24
|
-
use hyper::body::
|
23
|
+
use http_body_util::{BodyExt, StreamBody};
|
24
|
+
use hyper::body::Body;
|
25
25
|
use magnus::error::Result;
|
26
26
|
use serde::{Deserialize, Serialize};
|
27
27
|
use std::convert::Infallible;
|
@@ -126,15 +126,13 @@ impl MimeType {
|
|
126
126
|
}
|
127
127
|
}
|
128
128
|
|
129
|
-
fn stream_encode<R>(encoder: R) ->
|
129
|
+
fn stream_encode<R>(encoder: R) -> HttpBody
|
130
130
|
where
|
131
131
|
R: AsyncRead + Unpin + Sync + Send + 'static,
|
132
132
|
{
|
133
|
-
let encoded_stream = ReaderStream::new(encoder)
|
134
|
-
|
135
|
-
|
136
|
-
});
|
137
|
-
BoxBody::new(StreamBody::new(encoded_stream))
|
133
|
+
let encoded_stream = ReaderStream::new(encoder)
|
134
|
+
.map(|res| res.map_err(|_| -> Infallible { unreachable!("We handle IO errors above") }));
|
135
|
+
HttpBody::stream(StreamBody::new(encoded_stream))
|
138
136
|
}
|
139
137
|
|
140
138
|
fn update_content_encoding(parts: &mut http::response::Parts, new_encoding: HeaderValue) {
|
@@ -293,7 +291,7 @@ impl MiddlewareLayer for Compression {
|
|
293
291
|
}
|
294
292
|
CompressionAlgorithm::Identity => unreachable!(),
|
295
293
|
};
|
296
|
-
|
294
|
+
HttpBody::full(Bytes::from(compressed_bytes))
|
297
295
|
} else {
|
298
296
|
let stream = body
|
299
297
|
.into_data_stream()
|
@@ -1,12 +1,11 @@
|
|
1
1
|
use super::{FromValue, MiddlewareLayer};
|
2
2
|
use crate::{
|
3
|
-
server::http_message_types::{HttpRequest, HttpResponse, RequestExt},
|
3
|
+
server::http_message_types::{HttpBody, HttpRequest, HttpResponse, RequestExt},
|
4
4
|
services::itsi_http_service::HttpRequestContext,
|
5
5
|
};
|
6
6
|
|
7
7
|
use async_trait::async_trait;
|
8
8
|
use http::{HeaderMap, Method, Response};
|
9
|
-
use http_body_util::{combinators::BoxBody, Empty};
|
10
9
|
use itsi_error::ItsiError;
|
11
10
|
use magnus::error::Result;
|
12
11
|
use serde::Deserialize;
|
@@ -273,7 +272,7 @@ impl MiddlewareLayer for Cors {
|
|
273
272
|
let mut response_builder = Response::builder().status(204);
|
274
273
|
*response_builder.headers_mut().unwrap() = headers;
|
275
274
|
let response = response_builder
|
276
|
-
.body(
|
275
|
+
.body(HttpBody::empty())
|
277
276
|
.map_err(ItsiError::new)?;
|
278
277
|
return Ok(either::Either::Right(response));
|
279
278
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
use super::FromValue;
|
2
2
|
use crate::{
|
3
|
-
server::http_message_types::{HttpRequest, HttpResponse},
|
3
|
+
server::http_message_types::{HttpBody, HttpRequest, HttpResponse},
|
4
4
|
services::itsi_http_service::HttpRequestContext,
|
5
5
|
};
|
6
6
|
use async_trait::async_trait;
|
@@ -8,7 +8,7 @@ use bytes::{Bytes, BytesMut};
|
|
8
8
|
use either::Either;
|
9
9
|
use futures::TryStreamExt;
|
10
10
|
use http::{HeaderValue, StatusCode};
|
11
|
-
use http_body_util::
|
11
|
+
use http_body_util::BodyExt;
|
12
12
|
use itsi_error::ItsiError;
|
13
13
|
use serde::{Deserialize, Serialize};
|
14
14
|
use std::sync::Arc;
|
@@ -164,7 +164,7 @@ impl super::MiddlewareLayer for Csp {
|
|
164
164
|
}
|
165
165
|
}
|
166
166
|
|
167
|
-
let mut resp = HttpResponse::new(
|
167
|
+
let mut resp = HttpResponse::new(HttpBody::empty());
|
168
168
|
*resp.status_mut() = StatusCode::NO_CONTENT;
|
169
169
|
return Ok(Either::Right(resp));
|
170
170
|
}
|
data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs
CHANGED
@@ -1,91 +1,89 @@
|
|
1
1
|
use super::{ContentSource, DefaultFormat, ErrorResponse};
|
2
|
-
use crate::server::http_message_types::ResponseFormat;
|
2
|
+
use crate::server::http_message_types::{HttpBody, ResponseFormat};
|
3
3
|
use bytes::Bytes;
|
4
|
-
use http_body_util::{combinators::BoxBody, Full};
|
5
|
-
use std::convert::Infallible;
|
6
4
|
|
7
5
|
impl DefaultFormat {
|
8
6
|
pub fn response_for_code(&self, code: u16) -> ContentSource {
|
9
7
|
match self {
|
10
8
|
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(
|
9
|
+
500 => ContentSource::Static("500 Internal Error".into()),
|
10
|
+
404 => ContentSource::Static("404 Not Found".into()),
|
11
|
+
401 => ContentSource::Static("401 Unauthorized".into()),
|
12
|
+
403 => ContentSource::Static("403 Forbidden".into()),
|
13
|
+
413 => ContentSource::Static("413 Payload Too Large".into()),
|
14
|
+
429 => ContentSource::Static("429 Too Many Requests".into()),
|
15
|
+
502 => ContentSource::Static("502 Bad Gateway".into()),
|
16
|
+
503 => ContentSource::Static("503 Service Unavailable".into()),
|
17
|
+
504 => ContentSource::Static("504 Gateway Timeout".into()),
|
18
|
+
_ => ContentSource::Static("Unexpected Error".into()),
|
21
19
|
},
|
22
20
|
DefaultFormat::Html => match code {
|
23
|
-
500 => ContentSource::Static(
|
21
|
+
500 => ContentSource::Static(
|
24
22
|
include_str!("../../../../default_responses/html/500.html").into(),
|
25
|
-
)
|
26
|
-
404 => ContentSource::Static(
|
23
|
+
),
|
24
|
+
404 => ContentSource::Static(
|
27
25
|
include_str!("../../../../default_responses/html/404.html").into(),
|
28
|
-
)
|
29
|
-
401 => ContentSource::Static(
|
26
|
+
),
|
27
|
+
401 => ContentSource::Static(
|
30
28
|
include_str!("../../../../default_responses/html/401.html").into(),
|
31
|
-
)
|
32
|
-
403 => ContentSource::Static(
|
29
|
+
),
|
30
|
+
403 => ContentSource::Static(
|
33
31
|
include_str!("../../../../default_responses/html/403.html").into(),
|
34
|
-
)
|
35
|
-
413 => ContentSource::Static(
|
32
|
+
),
|
33
|
+
413 => ContentSource::Static(
|
36
34
|
include_str!("../../../../default_responses/html/413.html").into(),
|
37
|
-
)
|
38
|
-
429 => ContentSource::Static(
|
35
|
+
),
|
36
|
+
429 => ContentSource::Static(
|
39
37
|
include_str!("../../../../default_responses/html/429.html").into(),
|
40
|
-
)
|
41
|
-
502 => ContentSource::Static(
|
38
|
+
),
|
39
|
+
502 => ContentSource::Static(
|
42
40
|
include_str!("../../../../default_responses/html/502.html").into(),
|
43
|
-
)
|
44
|
-
503 => ContentSource::Static(
|
41
|
+
),
|
42
|
+
503 => ContentSource::Static(
|
45
43
|
include_str!("../../../../default_responses/html/503.html").into(),
|
46
|
-
)
|
47
|
-
504 => ContentSource::Static(
|
44
|
+
),
|
45
|
+
504 => ContentSource::Static(
|
48
46
|
include_str!("../../../../default_responses/html/504.html").into(),
|
49
|
-
)
|
50
|
-
_ => ContentSource::Static(
|
47
|
+
),
|
48
|
+
_ => ContentSource::Static(
|
51
49
|
include_str!("../../../../default_responses/html/500.html").into(),
|
52
|
-
)
|
50
|
+
),
|
53
51
|
},
|
54
52
|
DefaultFormat::Json => match code {
|
55
|
-
500 => ContentSource::Static(
|
53
|
+
500 => ContentSource::Static(
|
56
54
|
include_str!("../../../../default_responses/json/500.json").into(),
|
57
|
-
)
|
58
|
-
404 => ContentSource::Static(
|
55
|
+
),
|
56
|
+
404 => ContentSource::Static(
|
59
57
|
include_str!("../../../../default_responses/json/404.json").into(),
|
60
|
-
)
|
61
|
-
401 => ContentSource::Static(
|
58
|
+
),
|
59
|
+
401 => ContentSource::Static(
|
62
60
|
include_str!("../../../../default_responses/json/401.json").into(),
|
63
|
-
)
|
64
|
-
403 => ContentSource::Static(
|
61
|
+
),
|
62
|
+
403 => ContentSource::Static(
|
65
63
|
include_str!("../../../../default_responses/json/403.json").into(),
|
66
|
-
)
|
67
|
-
413 => ContentSource::Static(
|
64
|
+
),
|
65
|
+
413 => ContentSource::Static(
|
68
66
|
include_str!("../../../../default_responses/json/413.json").into(),
|
69
|
-
)
|
70
|
-
429 => ContentSource::Static(
|
67
|
+
),
|
68
|
+
429 => ContentSource::Static(
|
71
69
|
include_str!("../../../../default_responses/json/429.json").into(),
|
72
|
-
)
|
73
|
-
502 => ContentSource::Static(
|
70
|
+
),
|
71
|
+
502 => ContentSource::Static(
|
74
72
|
include_str!("../../../../default_responses/json/502.json").into(),
|
75
|
-
)
|
76
|
-
503 => ContentSource::Static(
|
73
|
+
),
|
74
|
+
503 => ContentSource::Static(
|
77
75
|
include_str!("../../../../default_responses/json/503.json").into(),
|
78
|
-
)
|
79
|
-
504 => ContentSource::Static(
|
76
|
+
),
|
77
|
+
504 => ContentSource::Static(
|
80
78
|
include_str!("../../../../default_responses/json/504.json").into(),
|
81
|
-
)
|
82
|
-
_ => ContentSource::Static(
|
79
|
+
),
|
80
|
+
_ => ContentSource::Static("Unexpected Error".into()),
|
83
81
|
},
|
84
82
|
}
|
85
83
|
}
|
86
84
|
}
|
87
85
|
impl ErrorResponse {
|
88
|
-
pub fn fallback_body_for(code: u16, accept: ResponseFormat) ->
|
86
|
+
pub fn fallback_body_for(code: u16, accept: ResponseFormat) -> HttpBody {
|
89
87
|
let source = match accept {
|
90
88
|
ResponseFormat::TEXT => DefaultFormat::Plaintext.response_for_code(code),
|
91
89
|
ResponseFormat::HTML => DefaultFormat::Html.response_for_code(code),
|
@@ -93,9 +91,9 @@ impl ErrorResponse {
|
|
93
91
|
ResponseFormat::UNKNOWN => ContentSource::Inline("Unexpected Error".to_owned()),
|
94
92
|
};
|
95
93
|
match source {
|
96
|
-
ContentSource::Inline(bytes) =>
|
97
|
-
ContentSource::Static(bytes) =>
|
98
|
-
ContentSource::File(_) =>
|
94
|
+
ContentSource::Inline(bytes) => HttpBody::full(Bytes::from(bytes)),
|
95
|
+
ContentSource::Static(bytes) => HttpBody::full(bytes),
|
96
|
+
ContentSource::File(_) => HttpBody::full(Bytes::from("Unexpected error")),
|
99
97
|
}
|
100
98
|
}
|
101
99
|
pub fn internal_server_error() -> Self {
|
@@ -1,13 +1,11 @@
|
|
1
1
|
use bytes::Bytes;
|
2
2
|
use http::header::CONTENT_TYPE;
|
3
3
|
use http::Response;
|
4
|
-
use http_body_util::{combinators::BoxBody, Full};
|
5
4
|
use serde::{Deserialize, Deserializer};
|
6
|
-
use std::convert::Infallible;
|
7
5
|
use std::path::PathBuf;
|
8
6
|
use tracing::warn;
|
9
7
|
|
10
|
-
use crate::server::http_message_types::{HttpResponse, ResponseFormat};
|
8
|
+
use crate::server::http_message_types::{HttpBody, HttpResponse, ResponseFormat};
|
11
9
|
use crate::services::static_file_server::ROOT_STATIC_FILE_SERVER;
|
12
10
|
mod default_responses;
|
13
11
|
|
@@ -19,7 +17,7 @@ pub enum ContentSource {
|
|
19
17
|
File(PathBuf),
|
20
18
|
#[serde(rename(deserialize = "static"))]
|
21
19
|
#[serde(skip_deserializing)]
|
22
|
-
Static(
|
20
|
+
Static(Bytes),
|
23
21
|
}
|
24
22
|
|
25
23
|
#[derive(Debug, Clone, Deserialize, Default)]
|
@@ -144,13 +142,13 @@ impl ErrorResponse {
|
|
144
142
|
code: u16,
|
145
143
|
source: &Option<ContentSource>,
|
146
144
|
accept: ResponseFormat,
|
147
|
-
) ->
|
145
|
+
) -> HttpBody {
|
148
146
|
match source {
|
149
147
|
Some(ContentSource::Inline(text)) => {
|
150
|
-
return
|
148
|
+
return HttpBody::full(Bytes::from(text.clone()));
|
151
149
|
}
|
152
150
|
Some(ContentSource::Static(text)) => {
|
153
|
-
return
|
151
|
+
return HttpBody::full(text.clone());
|
154
152
|
}
|
155
153
|
Some(ContentSource::File(path)) => {
|
156
154
|
// Convert the PathBuf to a &str (assumes valid UTF-8).
|
@@ -1,5 +1,5 @@
|
|
1
1
|
use crate::{
|
2
|
-
server::http_message_types::{HttpRequest, HttpResponse},
|
2
|
+
server::http_message_types::{HttpBody, HttpRequest, HttpResponse},
|
3
3
|
services::itsi_http_service::HttpRequestContext,
|
4
4
|
};
|
5
5
|
|
@@ -10,7 +10,7 @@ use bytes::{Bytes, BytesMut};
|
|
10
10
|
use either::Either;
|
11
11
|
use futures::TryStreamExt;
|
12
12
|
use http::{header, HeaderValue, Response, StatusCode};
|
13
|
-
use http_body_util::
|
13
|
+
use http_body_util::BodyExt;
|
14
14
|
use hyper::body::Body;
|
15
15
|
use magnus::error::Result;
|
16
16
|
use serde::Deserialize;
|
@@ -113,7 +113,7 @@ impl MiddlewareLayer for ETag {
|
|
113
113
|
.await
|
114
114
|
{
|
115
115
|
Ok(bytes_mut) => bytes_mut.freeze(),
|
116
|
-
Err(_) => return Response::from_parts(parts,
|
116
|
+
Err(_) => return Response::from_parts(parts, HttpBody::empty()),
|
117
117
|
};
|
118
118
|
|
119
119
|
let computed_etag = match self.algorithm {
|
@@ -139,14 +139,14 @@ impl MiddlewareLayer for ETag {
|
|
139
139
|
parts.headers.insert(header::ETAG, value);
|
140
140
|
}
|
141
141
|
|
142
|
-
body =
|
142
|
+
body = HttpBody::full(full_bytes);
|
143
143
|
formatted_etag
|
144
144
|
};
|
145
145
|
|
146
146
|
if let Some(if_none_match) = context.get_if_none_match() {
|
147
147
|
if if_none_match == etag_value || if_none_match == "*" {
|
148
148
|
// Return 304 Not Modified without the body
|
149
|
-
let mut not_modified = Response::new(
|
149
|
+
let mut not_modified = Response::new(HttpBody::empty());
|
150
150
|
*not_modified.status_mut() = StatusCode::NOT_MODIFIED;
|
151
151
|
// Copy headers we want to preserve
|
152
152
|
for (name, value) in parts.headers.iter() {
|
@@ -14,7 +14,7 @@ use super::{string_rewrite::StringRewrite, ErrorResponse, FromValue, MiddlewareL
|
|
14
14
|
use crate::{
|
15
15
|
server::{
|
16
16
|
binds::bind::{Bind, BindAddress},
|
17
|
-
http_message_types::{HttpRequest, HttpResponse, RequestExt, ResponseFormat},
|
17
|
+
http_message_types::{HttpBody, HttpRequest, HttpResponse, RequestExt, ResponseFormat},
|
18
18
|
size_limited_incoming::MaxBodySizeReached,
|
19
19
|
},
|
20
20
|
services::itsi_http_service::HttpRequestContext,
|
@@ -24,8 +24,7 @@ use bytes::{Bytes, BytesMut};
|
|
24
24
|
use either::Either;
|
25
25
|
use futures::TryStreamExt;
|
26
26
|
use http::{HeaderMap, Method, Response, StatusCode};
|
27
|
-
use http_body_util::
|
28
|
-
use hyper::body::Frame;
|
27
|
+
use http_body_util::BodyExt;
|
29
28
|
use magnus::error::Result;
|
30
29
|
use rand::Rng;
|
31
30
|
use reqwest::{
|
@@ -373,19 +372,17 @@ impl MiddlewareLayer for Proxy {
|
|
373
372
|
for (hn, hv) in response.headers() {
|
374
373
|
builder = builder.header(hn, hv);
|
375
374
|
}
|
376
|
-
let response =
|
377
|
-
response
|
378
|
-
|
379
|
-
|
380
|
-
.map_err(|_| -> Infallible { unreachable!("We handle IO errors above") }),
|
381
|
-
)));
|
375
|
+
let response =
|
376
|
+
builder.body(HttpBody::stream(response.bytes_stream().map_err(
|
377
|
+
|_| -> Infallible { unreachable!("We handle IO errors above") },
|
378
|
+
)));
|
382
379
|
response.unwrap_or(error_response)
|
383
380
|
}
|
384
381
|
Err(e) => {
|
385
382
|
debug!(target: "middleware::proxy", "Error {:?} received", e);
|
386
383
|
if let Some(inner) = e.source() {
|
387
384
|
if inner.downcast_ref::<MaxBodySizeReached>().is_some() {
|
388
|
-
let mut max_body_response = Response::new(
|
385
|
+
let mut max_body_response = Response::new(HttpBody::empty());
|
389
386
|
*max_body_response.status_mut() = StatusCode::PAYLOAD_TOO_LARGE;
|
390
387
|
return Ok(Either::Right(max_body_response));
|
391
388
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
use super::{string_rewrite::StringRewrite, FromValue, MiddlewareLayer};
|
2
2
|
use crate::{
|
3
3
|
server::{
|
4
|
-
http_message_types::{HttpRequest, HttpResponse},
|
4
|
+
http_message_types::{HttpBody, HttpRequest, HttpResponse},
|
5
5
|
redirect_type::RedirectType,
|
6
6
|
},
|
7
7
|
services::itsi_http_service::HttpRequestContext,
|
@@ -9,7 +9,6 @@ use crate::{
|
|
9
9
|
use async_trait::async_trait;
|
10
10
|
use either::Either;
|
11
11
|
use http::Response;
|
12
|
-
use http_body_util::{combinators::BoxBody, Empty};
|
13
12
|
use magnus::error::Result;
|
14
13
|
use serde::Deserialize;
|
15
14
|
use tracing::debug;
|
@@ -39,7 +38,7 @@ impl Redirect {
|
|
39
38
|
req: &HttpRequest,
|
40
39
|
context: &mut HttpRequestContext,
|
41
40
|
) -> Result<HttpResponse> {
|
42
|
-
let mut response = Response::new(
|
41
|
+
let mut response = Response::new(HttpBody::empty());
|
43
42
|
*response.status_mut() = self.redirect_type.status_code();
|
44
43
|
let destination = self.to.rewrite_request(req, context).parse().map_err(|e| {
|
45
44
|
magnus::Error::new(
|
@@ -134,8 +134,7 @@ impl MiddlewareLayer for StaticAssets {
|
|
134
134
|
let file_server = self.file_server.get().unwrap();
|
135
135
|
let encodings: &[HeaderValue] = context
|
136
136
|
.supported_encoding_set()
|
137
|
-
.
|
138
|
-
.unwrap_or(&[] as &[HeaderValue]);
|
137
|
+
.map_or(&[], |set| set.as_slice());
|
139
138
|
let response = file_server
|
140
139
|
.serve(
|
141
140
|
&req,
|
@@ -1,15 +1,13 @@
|
|
1
1
|
use std::sync::OnceLock;
|
2
2
|
|
3
3
|
use super::{FromValue, MiddlewareLayer};
|
4
|
-
use crate::server::http_message_types::{HttpRequest, HttpResponse};
|
4
|
+
use crate::server::http_message_types::{HttpBody, HttpRequest, HttpResponse};
|
5
5
|
use crate::services::itsi_http_service::HttpRequestContext;
|
6
6
|
use async_trait::async_trait;
|
7
7
|
use bytes::Bytes;
|
8
8
|
use derive_more::Debug;
|
9
9
|
use either::Either;
|
10
10
|
use http::{HeaderMap, HeaderName, HeaderValue, Response, StatusCode};
|
11
|
-
use http_body_util::combinators::BoxBody;
|
12
|
-
use http_body_util::Full;
|
13
11
|
use itsi_error::ItsiError;
|
14
12
|
use magnus::error::Result;
|
15
13
|
use serde::Deserialize;
|
@@ -22,7 +20,7 @@ pub struct StaticResponse {
|
|
22
20
|
#[serde(skip)]
|
23
21
|
header_map: OnceLock<HeaderMap>,
|
24
22
|
#[serde(skip)]
|
25
|
-
body_bytes: OnceLock<
|
23
|
+
body_bytes: OnceLock<Bytes>,
|
26
24
|
#[serde(skip)]
|
27
25
|
status_code: OnceLock<StatusCode>,
|
28
26
|
}
|
@@ -40,7 +38,7 @@ impl MiddlewareLayer for StaticResponse {
|
|
40
38
|
.set(header_map)
|
41
39
|
.map_err(|_| ItsiError::new("Failed to set headers"))?;
|
42
40
|
self.body_bytes
|
43
|
-
.set(
|
41
|
+
.set(Bytes::from(self.body.clone()))
|
44
42
|
.map_err(|_| ItsiError::new("Failed to set body bytes"))?;
|
45
43
|
self.status_code
|
46
44
|
.set(StatusCode::from_u16(self.code).unwrap_or(StatusCode::OK))
|
@@ -53,7 +51,7 @@ impl MiddlewareLayer for StaticResponse {
|
|
53
51
|
_req: HttpRequest,
|
54
52
|
_context: &mut HttpRequestContext,
|
55
53
|
) -> Result<Either<HttpRequest, HttpResponse>> {
|
56
|
-
let mut resp = Response::new(
|
54
|
+
let mut resp = Response::new(HttpBody::full(self.body_bytes.get().unwrap().clone()));
|
57
55
|
*resp.status_mut() = *self.status_code.get().unwrap();
|
58
56
|
*resp.headers_mut() = self.header_map.get().unwrap().clone();
|
59
57
|
|
@@ -79,7 +79,7 @@ impl ProcessWorker {
|
|
79
79
|
) {
|
80
80
|
error!("Failed to set process group ID: {}", e);
|
81
81
|
}
|
82
|
-
match SingleMode::new(cluster_template.server_config.clone()) {
|
82
|
+
match SingleMode::new(cluster_template.server_config.clone(), self.worker_id) {
|
83
83
|
Ok(single_mode) => {
|
84
84
|
if cluster_template
|
85
85
|
.server_config
|
@@ -88,7 +88,7 @@ impl ProcessWorker {
|
|
88
88
|
.pin_worker_cores
|
89
89
|
{
|
90
90
|
core_affinity::set_for_current(
|
91
|
-
CORE_IDS[self.worker_id % CORE_IDS.len()],
|
91
|
+
CORE_IDS[(2 * self.worker_id) % CORE_IDS.len()],
|
92
92
|
);
|
93
93
|
}
|
94
94
|
Arc::new(single_mode).run().ok();
|
@@ -166,7 +166,7 @@ impl ProcessWorker {
|
|
166
166
|
}
|
167
167
|
|
168
168
|
pub(crate) fn boot_if_dead(&self, cluster_template: Arc<ClusterMode>) -> bool {
|
169
|
-
if !self.is_alive() {
|
169
|
+
if !self.is_alive() && self.child_pid.lock().is_some() {
|
170
170
|
if self.just_started() {
|
171
171
|
error!(
|
172
172
|
"Worker in crash loop {:?}. Refusing to restart",
|
@@ -202,7 +202,6 @@ impl ProcessWorker {
|
|
202
202
|
let child_pid = *self.child_pid.lock();
|
203
203
|
if let Some(pid) = child_pid {
|
204
204
|
if self.is_alive() {
|
205
|
-
info!("Worker still alive, sending SIGKILL {}", pid);
|
206
205
|
if let Err(e) = kill(pid, SIGKILL) {
|
207
206
|
error!("Failed to force kill process {}: {}", pid, e);
|
208
207
|
}
|
@@ -1,6 +1,5 @@
|
|
1
|
-
use std::{ops::Deref, pin::Pin, sync::Arc, time::Duration};
|
2
|
-
|
3
1
|
use hyper_util::rt::TokioIo;
|
2
|
+
use std::{ops::Deref, pin::Pin, sync::Arc, time::Duration};
|
4
3
|
use tokio::task::JoinSet;
|
5
4
|
use tracing::debug;
|
6
5
|
|
@@ -40,17 +39,21 @@ impl Acceptor {
|
|
40
39
|
let io: TokioIo<Pin<Box<IoStream>>> = TokioIo::new(Box::pin(stream));
|
41
40
|
let mut shutdown_channel = self.shutdown_receiver.clone();
|
42
41
|
let acceptor_args = self.acceptor_args.clone();
|
42
|
+
let service = ItsiHttpService {
|
43
|
+
inner: Arc::new(ItsiHttpServiceInner {
|
44
|
+
acceptor_args: acceptor_args.clone(),
|
45
|
+
addr,
|
46
|
+
}),
|
47
|
+
};
|
48
|
+
|
43
49
|
self.join_set.spawn(async move {
|
44
50
|
let executor = &acceptor_args.strategy.executor;
|
45
|
-
let
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
}),
|
52
|
-
},
|
53
|
-
));
|
51
|
+
let svc = hyper::service::service_fn(move |req| {
|
52
|
+
let service = service.clone();
|
53
|
+
async move { service.handle_request(req).await }
|
54
|
+
});
|
55
|
+
|
56
|
+
let mut serve = Box::pin(executor.serve_connection_with_upgrades(io, svc));
|
54
57
|
|
55
58
|
tokio::select! {
|
56
59
|
// Await the connection finishing naturally.
|
@@ -63,7 +66,6 @@ impl Acceptor {
|
|
63
66
|
debug!("Connection closed abruptly: {:?}", res);
|
64
67
|
}
|
65
68
|
}
|
66
|
-
serve.as_mut().graceful_shutdown();
|
67
69
|
},
|
68
70
|
// A lifecycle event triggers shutdown.
|
69
71
|
_ = shutdown_channel.changed() => {
|
@@ -81,6 +83,7 @@ impl Acceptor {
|
|
81
83
|
|
82
84
|
pub async fn join(&mut self) {
|
83
85
|
// Join all acceptor tasks with timeout
|
86
|
+
|
84
87
|
let deadline = tokio::time::Instant::now()
|
85
88
|
+ Duration::from_secs_f64(self.server_params.shutdown_timeout);
|
86
89
|
let sleep_until = tokio::time::sleep_until(deadline);
|
@@ -89,6 +92,7 @@ impl Acceptor {
|
|
89
92
|
while (self.join_set.join_next().await).is_some() {}
|
90
93
|
} => {},
|
91
94
|
_ = sleep_until => {
|
95
|
+
self.join_set.abort_all();
|
92
96
|
debug!("Shutdown timeout reached; abandoning remaining acceptor tasks.");
|
93
97
|
}
|
94
98
|
}
|