itsi-server 0.1.7 → 0.1.8
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 +2917 -0
- data/Cargo.toml +7 -0
- data/ext/itsi_error/src/from.rs +26 -29
- data/ext/itsi_server/Cargo.lock +2956 -0
- data/ext/itsi_server/Cargo.toml +1 -1
- data/ext/itsi_server/src/request/itsi_request.rs +7 -7
- data/ext/itsi_server/src/server/bind.rs +4 -3
- data/ext/itsi_server/src/server/itsi_server.rs +1 -8
- data/ext/itsi_server/src/server/listener.rs +98 -107
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
- data/ext/itsi_server/src/server/tls.rs +9 -5
- data/lib/itsi/index.html.erb +91 -0
- data/lib/itsi/server/scheduler_mode.rb +1 -1
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +22 -2
- metadata +5 -1
data/ext/itsi_server/Cargo.toml
CHANGED
@@ -19,6 +19,7 @@ parking_lot = "0.12.3"
|
|
19
19
|
rustls-pemfile = "2.2.0"
|
20
20
|
tokio-rustls = "0.26.2"
|
21
21
|
bytes = "1.3"
|
22
|
+
tokio-rustls-acme = "0.6.0"
|
22
23
|
rcgen = { version = "0.13.2", features = ["x509-parser", "pem"] }
|
23
24
|
base64 = "0.22.1"
|
24
25
|
http-body-util = "0.1.2"
|
@@ -39,7 +40,6 @@ httparse = "1.10.1"
|
|
39
40
|
async-channel = "2.3.1"
|
40
41
|
tempfile = "3.18.0"
|
41
42
|
sysinfo = "0.33.1"
|
42
|
-
tokio-rustls-acme = "0.6.0"
|
43
43
|
rustls = "0.23.23"
|
44
44
|
fs2 = "0.4.3"
|
45
45
|
ring = "0.17.14"
|
@@ -6,7 +6,7 @@ use crate::{
|
|
6
6
|
response::itsi_response::ItsiResponse,
|
7
7
|
server::{
|
8
8
|
itsi_server::{RequestJob, Server},
|
9
|
-
listener::{
|
9
|
+
listener::{ListenerInfo, SockAddr},
|
10
10
|
serve_strategy::single_mode::RunningPhase,
|
11
11
|
},
|
12
12
|
};
|
@@ -44,7 +44,7 @@ pub struct ItsiRequest {
|
|
44
44
|
pub remote_addr: String,
|
45
45
|
pub version: String,
|
46
46
|
#[debug(skip)]
|
47
|
-
pub(crate) listener: Arc<
|
47
|
+
pub(crate) listener: Arc<ListenerInfo>,
|
48
48
|
#[debug(skip)]
|
49
49
|
pub server: Arc<Server>,
|
50
50
|
pub response: ItsiResponse,
|
@@ -128,7 +128,7 @@ impl ItsiRequest {
|
|
128
128
|
hyper_request: Request<Incoming>,
|
129
129
|
sender: async_channel::Sender<RequestJob>,
|
130
130
|
server: Arc<Server>,
|
131
|
-
listener: Arc<
|
131
|
+
listener: Arc<ListenerInfo>,
|
132
132
|
addr: SockAddr,
|
133
133
|
shutdown_rx: watch::Receiver<RunningPhase>,
|
134
134
|
) -> itsi_error::Result<Response<BoxBody<Bytes, Infallible>>> {
|
@@ -153,7 +153,7 @@ impl ItsiRequest {
|
|
153
153
|
request: Request<Incoming>,
|
154
154
|
sock_addr: SockAddr,
|
155
155
|
server: Arc<Server>,
|
156
|
-
listener: Arc<
|
156
|
+
listener: Arc<ListenerInfo>,
|
157
157
|
) -> (ItsiRequest, mpsc::Receiver<Option<Bytes>>) {
|
158
158
|
let (parts, body) = request.into_parts();
|
159
159
|
let body = if server.stream_body.is_some_and(|f| f) {
|
@@ -231,7 +231,7 @@ impl ItsiRequest {
|
|
231
231
|
.uri
|
232
232
|
.host()
|
233
233
|
.map(|host| host.to_string())
|
234
|
-
.unwrap_or_else(|| self.listener.host()))
|
234
|
+
.unwrap_or_else(|| self.listener.host.clone()))
|
235
235
|
}
|
236
236
|
|
237
237
|
pub(crate) fn scheme(&self) -> MagnusResult<String> {
|
@@ -240,7 +240,7 @@ impl ItsiRequest {
|
|
240
240
|
.uri
|
241
241
|
.scheme()
|
242
242
|
.map(|scheme| scheme.to_string())
|
243
|
-
.unwrap_or_else(|| self.listener.scheme()))
|
243
|
+
.unwrap_or_else(|| self.listener.scheme.clone()))
|
244
244
|
}
|
245
245
|
|
246
246
|
pub(crate) fn headers(&self) -> MagnusResult<Vec<(String, &str)>> {
|
@@ -264,7 +264,7 @@ impl ItsiRequest {
|
|
264
264
|
}
|
265
265
|
|
266
266
|
pub(crate) fn port(&self) -> MagnusResult<u16> {
|
267
|
-
Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port
|
267
|
+
Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port))
|
268
268
|
}
|
269
269
|
|
270
270
|
pub(crate) fn body(&self) -> MagnusResult<Value> {
|
@@ -9,6 +9,7 @@ use std::{
|
|
9
9
|
path::PathBuf,
|
10
10
|
str::FromStr,
|
11
11
|
};
|
12
|
+
|
12
13
|
#[derive(Debug, Clone)]
|
13
14
|
pub enum BindAddress {
|
14
15
|
Ip(IpAddr),
|
@@ -129,13 +130,13 @@ impl FromStr for Bind {
|
|
129
130
|
BindProtocol::Unix => None,
|
130
131
|
BindProtocol::Unixs => Some(configure_tls(host, &options)?),
|
131
132
|
};
|
132
|
-
|
133
|
-
Ok(Self {
|
133
|
+
let bind = Self {
|
134
134
|
address,
|
135
135
|
port,
|
136
136
|
protocol,
|
137
137
|
tls_config,
|
138
|
-
}
|
138
|
+
};
|
139
|
+
Ok(bind)
|
139
140
|
}
|
140
141
|
}
|
141
142
|
|
@@ -19,7 +19,7 @@ use parking_lot::Mutex;
|
|
19
19
|
use std::{cmp::max, ops::Deref, sync::Arc};
|
20
20
|
use tracing::{info, instrument};
|
21
21
|
|
22
|
-
static DEFAULT_BIND: &str = "localhost:3000";
|
22
|
+
static DEFAULT_BIND: &str = "http://localhost:3000";
|
23
23
|
|
24
24
|
#[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
|
25
25
|
#[derive(Clone)]
|
@@ -231,13 +231,6 @@ impl Server {
|
|
231
231
|
drop(strategy);
|
232
232
|
Ok(())
|
233
233
|
})?;
|
234
|
-
if let Ok(listeners) = Arc::try_unwrap(listeners) {
|
235
|
-
listeners.into_iter().for_each(|listener| {
|
236
|
-
if let Ok(listener) = Arc::try_unwrap(listener) {
|
237
|
-
listener.unbind()
|
238
|
-
};
|
239
|
-
});
|
240
|
-
}
|
241
234
|
clear_signal_handlers();
|
242
235
|
Ok(())
|
243
236
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
use super::bind::{Bind, BindAddress};
|
2
2
|
use super::bind_protocol::BindProtocol;
|
3
3
|
use super::io_stream::IoStream;
|
4
|
+
use super::serve_strategy::single_mode::RunningPhase;
|
4
5
|
use super::tls::ItsiTlsAcceptor;
|
5
6
|
use itsi_error::{ItsiError, Result};
|
6
7
|
use itsi_tracing::info;
|
@@ -11,6 +12,7 @@ use std::{os::unix::net::UnixListener, path::PathBuf};
|
|
11
12
|
use tokio::net::TcpListener as TokioTcpListener;
|
12
13
|
use tokio::net::UnixListener as TokioUnixListener;
|
13
14
|
use tokio::net::{unix, TcpStream, UnixStream};
|
15
|
+
use tokio::sync::watch::Receiver;
|
14
16
|
use tokio_rustls::TlsAcceptor;
|
15
17
|
use tokio_stream::StreamExt;
|
16
18
|
use tracing::error;
|
@@ -23,45 +25,79 @@ pub(crate) enum Listener {
|
|
23
25
|
}
|
24
26
|
|
25
27
|
pub(crate) enum TokioListener {
|
26
|
-
Tcp
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Unix {
|
38
|
-
listener: TokioUnixListener,
|
39
|
-
},
|
40
|
-
UnixTls {
|
41
|
-
listener: TokioUnixListener,
|
42
|
-
acceptor: ItsiTlsAcceptor,
|
43
|
-
},
|
28
|
+
Tcp(TokioTcpListener),
|
29
|
+
TcpTls(TokioTcpListener, ItsiTlsAcceptor),
|
30
|
+
Unix(TokioUnixListener),
|
31
|
+
UnixTls(TokioUnixListener, ItsiTlsAcceptor),
|
32
|
+
}
|
33
|
+
|
34
|
+
#[derive(Debug, Clone)]
|
35
|
+
pub struct ListenerInfo {
|
36
|
+
pub host: String,
|
37
|
+
pub port: u16,
|
38
|
+
pub scheme: String,
|
44
39
|
}
|
45
40
|
|
46
41
|
impl TokioListener {
|
47
|
-
pub fn
|
42
|
+
pub fn listener_info(&self) -> ListenerInfo {
|
48
43
|
match self {
|
49
|
-
TokioListener::Tcp
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
TokioListener::Tcp(listener) => ListenerInfo {
|
45
|
+
host: listener
|
46
|
+
.local_addr()
|
47
|
+
.unwrap()
|
48
|
+
.ip()
|
49
|
+
.to_canonical()
|
50
|
+
.to_string(),
|
51
|
+
port: listener.local_addr().unwrap().port(),
|
52
|
+
scheme: "http".to_string(),
|
53
|
+
},
|
54
|
+
TokioListener::TcpTls(listener, _) => ListenerInfo {
|
55
|
+
host: listener
|
56
|
+
.local_addr()
|
57
|
+
.unwrap()
|
58
|
+
.ip()
|
59
|
+
.to_canonical()
|
60
|
+
.to_string(),
|
61
|
+
port: listener.local_addr().unwrap().port(),
|
62
|
+
scheme: "https".to_string(),
|
63
|
+
},
|
64
|
+
TokioListener::Unix(listener) => ListenerInfo {
|
65
|
+
host: listener
|
66
|
+
.local_addr()
|
67
|
+
.unwrap()
|
68
|
+
.as_pathname()
|
69
|
+
.unwrap()
|
70
|
+
.to_str()
|
71
|
+
.unwrap()
|
72
|
+
.to_owned(),
|
73
|
+
port: 0,
|
74
|
+
scheme: "unix".to_string(),
|
75
|
+
},
|
76
|
+
TokioListener::UnixTls(listener, _) => ListenerInfo {
|
77
|
+
host: listener
|
78
|
+
.local_addr()
|
79
|
+
.unwrap()
|
80
|
+
.as_pathname()
|
81
|
+
.unwrap()
|
82
|
+
.to_str()
|
83
|
+
.unwrap()
|
84
|
+
.to_owned(),
|
85
|
+
port: 0,
|
86
|
+
scheme: "ssl".to_string(),
|
87
|
+
},
|
88
|
+
}
|
54
89
|
}
|
90
|
+
|
55
91
|
pub(crate) async fn accept(&self) -> Result<IoStream> {
|
56
92
|
match self {
|
57
|
-
TokioListener::Tcp
|
58
|
-
TokioListener::TcpTls {
|
59
|
-
listener, acceptor
|
60
|
-
}
|
61
|
-
TokioListener::Unix
|
62
|
-
TokioListener::UnixTls {
|
63
|
-
listener, acceptor
|
64
|
-
}
|
93
|
+
TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
|
94
|
+
TokioListener::TcpTls(listener, acceptor) => {
|
95
|
+
TokioListener::accept_tls(listener, acceptor).await
|
96
|
+
}
|
97
|
+
TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
|
98
|
+
TokioListener::UnixTls(listener, acceptor) => {
|
99
|
+
TokioListener::accept_unix_tls(listener, acceptor).await
|
100
|
+
}
|
65
101
|
}
|
66
102
|
}
|
67
103
|
|
@@ -70,17 +106,24 @@ impl TokioListener {
|
|
70
106
|
Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
|
71
107
|
}
|
72
108
|
|
73
|
-
pub async fn spawn_state_task(&self) {
|
74
|
-
if let TokioListener::TcpTls
|
75
|
-
|
76
|
-
|
77
|
-
|
109
|
+
pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
|
110
|
+
if let TokioListener::TcpTls(
|
111
|
+
_,
|
112
|
+
ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
|
113
|
+
) = self
|
78
114
|
{
|
79
115
|
let mut state = state.lock().await;
|
80
116
|
loop {
|
81
|
-
|
82
|
-
|
83
|
-
|
117
|
+
tokio::select! {
|
118
|
+
stream_event = StreamExt::next(&mut *state) => {
|
119
|
+
match stream_event {
|
120
|
+
Some(event) => info!("Received acme event: {:?}", event),
|
121
|
+
None => error!("Received no acme event"),
|
122
|
+
}
|
123
|
+
},
|
124
|
+
_ = shutdown_receiver.changed() => {
|
125
|
+
break;
|
126
|
+
}
|
84
127
|
}
|
85
128
|
}
|
86
129
|
}
|
@@ -175,33 +218,6 @@ impl TokioListener {
|
|
175
218
|
},
|
176
219
|
}
|
177
220
|
}
|
178
|
-
|
179
|
-
pub(crate) fn scheme(&self) -> String {
|
180
|
-
match self {
|
181
|
-
TokioListener::Tcp { .. } => "http".to_string(),
|
182
|
-
TokioListener::TcpTls { .. } => "https".to_string(),
|
183
|
-
TokioListener::Unix { .. } => "http".to_string(),
|
184
|
-
TokioListener::UnixTls { .. } => "https".to_string(),
|
185
|
-
}
|
186
|
-
}
|
187
|
-
|
188
|
-
pub(crate) fn port(&self) -> u16 {
|
189
|
-
match self {
|
190
|
-
TokioListener::Tcp { port, .. } => *port,
|
191
|
-
TokioListener::TcpTls { port, .. } => *port,
|
192
|
-
TokioListener::Unix { .. } => 0,
|
193
|
-
TokioListener::UnixTls { .. } => 0,
|
194
|
-
}
|
195
|
-
}
|
196
|
-
|
197
|
-
pub(crate) fn host(&self) -> String {
|
198
|
-
match self {
|
199
|
-
TokioListener::Tcp { host, .. } => host.to_string(),
|
200
|
-
TokioListener::TcpTls { host, .. } => host.to_string(),
|
201
|
-
TokioListener::Unix { .. } => "unix".to_string(),
|
202
|
-
TokioListener::UnixTls { .. } => "unix".to_string(),
|
203
|
-
}
|
204
|
-
}
|
205
221
|
}
|
206
222
|
|
207
223
|
enum Stream {
|
@@ -227,48 +243,22 @@ impl std::fmt::Display for SockAddr {
|
|
227
243
|
}
|
228
244
|
|
229
245
|
impl Listener {
|
230
|
-
pub fn unbind(self) {
|
231
|
-
match self {
|
232
|
-
Listener::Tcp(listener) => drop(listener),
|
233
|
-
Listener::TcpTls((listener, _)) => drop(listener),
|
234
|
-
Listener::Unix(listener) => drop(listener),
|
235
|
-
Listener::UnixTls((listener, _)) => drop(listener),
|
236
|
-
};
|
237
|
-
}
|
238
246
|
pub fn to_tokio_listener(&self) -> TokioListener {
|
239
247
|
match self {
|
240
|
-
Listener::Tcp(listener) => TokioListener::Tcp
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
acceptor: acceptor.clone(),
|
255
|
-
host: listener
|
256
|
-
.local_addr()
|
257
|
-
.unwrap()
|
258
|
-
.ip()
|
259
|
-
.to_canonical()
|
260
|
-
.to_string(),
|
261
|
-
port: listener.local_addr().unwrap().port(),
|
262
|
-
},
|
263
|
-
Listener::Unix(listener) => TokioListener::Unix {
|
264
|
-
listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
|
265
|
-
.unwrap(),
|
266
|
-
},
|
267
|
-
Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls {
|
268
|
-
listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
|
269
|
-
.unwrap(),
|
270
|
-
acceptor: acceptor.clone(),
|
271
|
-
},
|
248
|
+
Listener::Tcp(listener) => TokioListener::Tcp(
|
249
|
+
TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
|
250
|
+
),
|
251
|
+
Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls(
|
252
|
+
TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
|
253
|
+
acceptor.clone(),
|
254
|
+
),
|
255
|
+
Listener::Unix(listener) => TokioListener::Unix(
|
256
|
+
TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
|
257
|
+
),
|
258
|
+
Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
|
259
|
+
TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
|
260
|
+
acceptor.clone(),
|
261
|
+
),
|
272
262
|
}
|
273
263
|
}
|
274
264
|
}
|
@@ -307,6 +297,7 @@ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
|
|
307
297
|
socket.set_nonblocking(true).ok();
|
308
298
|
socket.set_nodelay(true).ok();
|
309
299
|
socket.set_recv_buffer_size(262_144).ok();
|
300
|
+
info!("Binding to {:?}", socket_address);
|
310
301
|
socket.bind(&socket_address.into())?;
|
311
302
|
socket.listen(1024)?;
|
312
303
|
Ok(socket.into())
|
@@ -4,7 +4,7 @@ use crate::{
|
|
4
4
|
io_stream::IoStream,
|
5
5
|
itsi_server::{RequestJob, Server},
|
6
6
|
lifecycle_event::LifecycleEvent,
|
7
|
-
listener::{Listener,
|
7
|
+
listener::{Listener, ListenerInfo},
|
8
8
|
thread_worker::{build_thread_workers, ThreadWorker},
|
9
9
|
},
|
10
10
|
};
|
@@ -87,18 +87,25 @@ impl SingleMode {
|
|
87
87
|
pub fn run(self: Arc<Self>) -> Result<()> {
|
88
88
|
let mut listener_task_set = JoinSet::new();
|
89
89
|
let self_ref = Arc::new(self);
|
90
|
-
self_ref.build_runtime()
|
90
|
+
let runtime = self_ref.build_runtime();
|
91
91
|
|
92
|
-
|
93
|
-
|
92
|
+
runtime.block_on(async {
|
93
|
+
let tokio_listeners = self_ref
|
94
|
+
.listeners
|
95
|
+
.iter()
|
96
|
+
.map(|list| Arc::new(list.to_tokio_listener()))
|
97
|
+
.collect::<Vec<_>>();
|
98
|
+
for listener in tokio_listeners.iter() {
|
94
99
|
let mut lifecycle_rx = self_ref.lifecycle_channel.subscribe();
|
100
|
+
let listener_info = Arc::new(listener.listener_info());
|
95
101
|
let self_ref = self_ref.clone();
|
96
102
|
let listener = listener.clone();
|
97
103
|
let (shutdown_sender, mut shutdown_receiver) = tokio::sync::watch::channel::<RunningPhase>(RunningPhase::Running);
|
98
104
|
let listener_clone = listener.clone();
|
99
105
|
|
100
|
-
|
101
|
-
|
106
|
+
let shutdown_receiver_clone = shutdown_receiver.clone();
|
107
|
+
listener_task_set.spawn(async move {
|
108
|
+
listener_clone.spawn_state_task(shutdown_receiver_clone).await;
|
102
109
|
});
|
103
110
|
|
104
111
|
listener_task_set.spawn(async move {
|
@@ -107,8 +114,11 @@ impl SingleMode {
|
|
107
114
|
tokio::select! {
|
108
115
|
accept_result = listener.accept() => match accept_result {
|
109
116
|
Ok(accept_result) => {
|
110
|
-
|
111
|
-
|
117
|
+
match strategy.serve_connection(accept_result, listener_info.clone(), shutdown_receiver.clone()).await {
|
118
|
+
Ok(_) => {
|
119
|
+
debug!("Connection accepted and served");
|
120
|
+
},
|
121
|
+
Err(e) => error!("Error in serve_connection {:?}", e)
|
112
122
|
}
|
113
123
|
},
|
114
124
|
Err(e) => debug!("Listener.accept failed {:?}", e),
|
@@ -130,23 +140,23 @@ impl SingleMode {
|
|
130
140
|
}
|
131
141
|
}
|
132
142
|
}
|
133
|
-
if let Ok(listener) = Arc::try_unwrap(listener){
|
134
|
-
listener.unbind();
|
135
|
-
}
|
136
143
|
});
|
137
144
|
|
138
145
|
}
|
139
146
|
|
140
147
|
while let Some(_res) = listener_task_set.join_next().await {}
|
148
|
+
|
141
149
|
});
|
150
|
+
runtime.shutdown_timeout(Duration::from_millis(100));
|
142
151
|
|
152
|
+
info!("Runtime has shut down");
|
143
153
|
Ok(())
|
144
154
|
}
|
145
155
|
|
146
156
|
pub(crate) async fn serve_connection(
|
147
157
|
&self,
|
148
158
|
stream: IoStream,
|
149
|
-
listener: Arc<
|
159
|
+
listener: Arc<ListenerInfo>,
|
150
160
|
shutdown_channel: tokio::sync::watch::Receiver<RunningPhase>,
|
151
161
|
) -> Result<()> {
|
152
162
|
let sender_clone = self.sender.clone();
|
@@ -186,7 +186,15 @@ pub fn load_private_key(path: &str) -> PrivateKeyDer<'static> {
|
|
186
186
|
pub fn generate_ca_signed_cert(
|
187
187
|
domains: Vec<String>,
|
188
188
|
) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
|
189
|
-
info!(
|
189
|
+
info!(
|
190
|
+
domains = format!("{}", domains.join(", ")),
|
191
|
+
"Self signed cert",
|
192
|
+
);
|
193
|
+
info!(
|
194
|
+
"Add {} to your system's trusted cert store to resolve certificate errors.",
|
195
|
+
format!("{}/itsi_dev_ca.crt", ITSI_LOCAL_CA_DIR.to_str().unwrap())
|
196
|
+
);
|
197
|
+
info!("Dev CA path can be overridden by setting env var: `ITSI_LOCAL_CA_DIR`.");
|
190
198
|
let (ca_key_pem, ca_cert_pem) = get_or_create_local_dev_ca()?;
|
191
199
|
|
192
200
|
let ca_kp = KeyPair::from_pem(&ca_key_pem).expect("Failed to load CA key");
|
@@ -198,10 +206,6 @@ pub fn generate_ca_signed_cert(
|
|
198
206
|
let ee_key = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256).unwrap();
|
199
207
|
let mut ee_params = CertificateParams::default();
|
200
208
|
|
201
|
-
info!(
|
202
|
-
"Generated certificate will be valid for domains {:?}",
|
203
|
-
domains
|
204
|
-
);
|
205
209
|
use std::net::IpAddr;
|
206
210
|
|
207
211
|
ee_params.subject_alt_names = domains
|
@@ -0,0 +1,91 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title>Itsi - Default</title>
|
6
|
+
<style>
|
7
|
+
* {
|
8
|
+
box-sizing: border-box;
|
9
|
+
margin: 0;
|
10
|
+
padding: 0;
|
11
|
+
}
|
12
|
+
body {
|
13
|
+
font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
14
|
+
background-color: #f4f4f4;
|
15
|
+
color: #333;
|
16
|
+
line-height: 1.6;
|
17
|
+
}
|
18
|
+
.container {
|
19
|
+
max-width: 700px;
|
20
|
+
margin: 3rem auto;
|
21
|
+
background: #fff;
|
22
|
+
border-radius: 8px;
|
23
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
24
|
+
padding: 2rem;
|
25
|
+
}
|
26
|
+
h1 {
|
27
|
+
font-size: 1.8rem;
|
28
|
+
margin-bottom: 1rem;
|
29
|
+
text-align: center;
|
30
|
+
color: #444;
|
31
|
+
}
|
32
|
+
p {
|
33
|
+
margin-bottom: 1rem;
|
34
|
+
text-align: center;
|
35
|
+
color: #666;
|
36
|
+
}
|
37
|
+
ul.fields {
|
38
|
+
list-style: none;
|
39
|
+
margin-top: 1.5rem;
|
40
|
+
padding: 0;
|
41
|
+
}
|
42
|
+
ul.fields li {
|
43
|
+
background: #fafafa;
|
44
|
+
border: 1px solid #eee;
|
45
|
+
border-radius: 5px;
|
46
|
+
padding: 0.75rem;
|
47
|
+
margin-bottom: 0.75rem;
|
48
|
+
display: flex;
|
49
|
+
justify-content: space-between;
|
50
|
+
align-items: center;
|
51
|
+
}
|
52
|
+
.label {
|
53
|
+
font-weight: bold;
|
54
|
+
margin-right: 1rem;
|
55
|
+
}
|
56
|
+
</style>
|
57
|
+
</head>
|
58
|
+
<body>
|
59
|
+
<div class="container">
|
60
|
+
<h1>You're running on Itsi!</h1>
|
61
|
+
<p>RACK environment:</p>
|
62
|
+
|
63
|
+
<ul class="fields">
|
64
|
+
<li>
|
65
|
+
<span class="label">REQUEST_METHOD:</span>
|
66
|
+
<span>%{REQUEST_METHOD}</span>
|
67
|
+
</li>
|
68
|
+
<li>
|
69
|
+
<span class="label">PATH_INFO:</span>
|
70
|
+
<span>%{PATH_INFO}</span>
|
71
|
+
</li>
|
72
|
+
<li>
|
73
|
+
<span class="label">SERVER_NAME:</span>
|
74
|
+
<span>%{SERVER_NAME}</span>
|
75
|
+
</li>
|
76
|
+
<li>
|
77
|
+
<span class="label">SERVER_PORT:</span>
|
78
|
+
<span>%{SERVER_PORT}</span>
|
79
|
+
</li>
|
80
|
+
<li>
|
81
|
+
<span class="label">REMOTE_ADDR:</span>
|
82
|
+
<span>%{REMOTE_ADDR}</span>
|
83
|
+
</li>
|
84
|
+
<li>
|
85
|
+
<span class="label">HTTP_USER_AGENT:</span>
|
86
|
+
<span>%{HTTP_USER_AGENT}</span>
|
87
|
+
</li>
|
88
|
+
</ul>
|
89
|
+
</div>
|
90
|
+
</body>
|
91
|
+
</html>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
if defined?(ActiveSupport::IsolatedExecutionState) && !ENV["ITSI_DISABLE_AS_AUTO_FIBER_ISOLATION_LEVEL"]
|
2
2
|
Itsi.log_info \
|
3
3
|
"ActiveSupport Isolated Execution state detected. Automatically switching to :fiber mode. "\
|
4
|
-
"
|
4
|
+
"Set ITSI_DISABLE_AS_AUTO_FIBER_ISOLATION_LEVEL to disable this behavior"
|
5
5
|
ActiveSupport::IsolatedExecutionState.isolation_level = :fiber
|
6
6
|
end
|
data/lib/itsi/server/version.rb
CHANGED
data/lib/itsi/server.rb
CHANGED
@@ -6,6 +6,9 @@ require_relative "signals"
|
|
6
6
|
require_relative "request"
|
7
7
|
require_relative "stream_io"
|
8
8
|
require_relative "server/rack/handler/itsi"
|
9
|
+
require 'erb'
|
10
|
+
|
11
|
+
DEFAULT_INDEX = IO.read(__dir__ + '/index.html.erb')
|
9
12
|
|
10
13
|
module Itsi
|
11
14
|
class Server
|
@@ -14,8 +17,25 @@ module Itsi
|
|
14
17
|
@running ||= false
|
15
18
|
end
|
16
19
|
|
17
|
-
def self.start(
|
18
|
-
|
20
|
+
def self.start(
|
21
|
+
app: ->(env){
|
22
|
+
[env['CONTENT_TYPE'], env['HTTP_ACCEPT']].include?('application/json') ?
|
23
|
+
[200, {"Content-Type" => "application/json"}, ["{\"message\": \"You're running on Itsi!\"}"]] :
|
24
|
+
[200, {"Content-Type" => "text/html"}, [
|
25
|
+
DEFAULT_INDEX % {
|
26
|
+
REQUEST_METHOD: env['REQUEST_METHOD'],
|
27
|
+
PATH_INFO: env['PATH_INFO'],
|
28
|
+
SERVER_NAME: env['SERVER_NAME'],
|
29
|
+
SERVER_PORT: env['SERVER_PORT'],
|
30
|
+
REMOTE_ADDR: env['REMOTE_ADDR'],
|
31
|
+
HTTP_USER_AGENT: env['HTTP_USER_AGENT']
|
32
|
+
}
|
33
|
+
]]
|
34
|
+
},
|
35
|
+
binds: ['http://0.0.0.0:3000'],
|
36
|
+
**opts
|
37
|
+
)
|
38
|
+
server = new(app: ->{app}, binds: binds, **opts)
|
19
39
|
@running = true
|
20
40
|
Signal.trap('INT', 'DEFAULT')
|
21
41
|
server.start
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itsi-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
@@ -49,6 +49,8 @@ files:
|
|
49
49
|
- ".rubocop.yml"
|
50
50
|
- CHANGELOG.md
|
51
51
|
- CODE_OF_CONDUCT.md
|
52
|
+
- Cargo.lock
|
53
|
+
- Cargo.toml
|
52
54
|
- LICENSE.txt
|
53
55
|
- README.md
|
54
56
|
- Rakefile
|
@@ -70,6 +72,7 @@ files:
|
|
70
72
|
- ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs
|
71
73
|
- ext/itsi_scheduler/src/itsi_scheduler/timer.rs
|
72
74
|
- ext/itsi_scheduler/src/lib.rs
|
75
|
+
- ext/itsi_server/Cargo.lock
|
73
76
|
- ext/itsi_server/Cargo.toml
|
74
77
|
- ext/itsi_server/extconf.rb
|
75
78
|
- ext/itsi_server/src/body_proxy/big_bytes.rs
|
@@ -99,6 +102,7 @@ files:
|
|
99
102
|
- ext/itsi_tracing/Cargo.lock
|
100
103
|
- ext/itsi_tracing/Cargo.toml
|
101
104
|
- ext/itsi_tracing/src/lib.rs
|
105
|
+
- lib/itsi/index.html.erb
|
102
106
|
- lib/itsi/request.rb
|
103
107
|
- lib/itsi/server.rb
|
104
108
|
- lib/itsi/server/rack/handler/itsi.rb
|