itsi-server 0.2.16 → 0.2.17

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +3 -1
  3. data/exe/itsi +6 -1
  4. data/ext/itsi_acme/Cargo.toml +1 -1
  5. data/ext/itsi_scheduler/Cargo.toml +1 -1
  6. data/ext/itsi_server/Cargo.toml +3 -1
  7. data/ext/itsi_server/src/lib.rs +6 -1
  8. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +2 -0
  9. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +4 -4
  10. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +14 -13
  11. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +64 -33
  12. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +151 -152
  13. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +6 -15
  14. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +26 -5
  15. data/ext/itsi_server/src/ruby_types/itsi_server.rs +1 -1
  16. data/ext/itsi_server/src/server/binds/listener.rs +45 -7
  17. data/ext/itsi_server/src/server/frame_stream.rs +142 -0
  18. data/ext/itsi_server/src/server/http_message_types.rs +142 -9
  19. data/ext/itsi_server/src/server/io_stream.rs +28 -5
  20. data/ext/itsi_server/src/server/lifecycle_event.rs +1 -1
  21. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +2 -3
  22. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +8 -10
  23. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +2 -3
  24. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +3 -3
  25. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +54 -56
  26. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +5 -7
  27. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +5 -5
  28. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +7 -10
  29. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +2 -3
  30. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +1 -2
  31. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +4 -6
  32. data/ext/itsi_server/src/server/mod.rs +1 -0
  33. data/ext/itsi_server/src/server/process_worker.rs +3 -4
  34. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +16 -12
  35. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +87 -31
  36. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +158 -142
  37. data/ext/itsi_server/src/server/signal.rs +37 -9
  38. data/ext/itsi_server/src/server/thread_worker.rs +84 -69
  39. data/ext/itsi_server/src/services/itsi_http_service.rs +43 -43
  40. data/ext/itsi_server/src/services/static_file_server.rs +28 -47
  41. data/lib/itsi/http_request.rb +31 -39
  42. data/lib/itsi/http_response.rb +5 -0
  43. data/lib/itsi/rack_env_pool.rb +59 -0
  44. data/lib/itsi/server/config/dsl.rb +5 -4
  45. data/lib/itsi/server/config/middleware/proxy.rb +1 -1
  46. data/lib/itsi/server/config/middleware/rackup_file.rb +2 -2
  47. data/lib/itsi/server/config/options/auto_reload_config.rb +6 -2
  48. data/lib/itsi/server/config/options/include.rb +5 -2
  49. data/lib/itsi/server/config/options/pipeline_flush.md +16 -0
  50. data/lib/itsi/server/config/options/pipeline_flush.rb +19 -0
  51. data/lib/itsi/server/config/options/writev.md +25 -0
  52. data/lib/itsi/server/config/options/writev.rb +19 -0
  53. data/lib/itsi/server/config.rb +21 -8
  54. data/lib/itsi/server/default_config/Itsi.rb +1 -4
  55. data/lib/itsi/server/grpc/grpc_call.rb +2 -0
  56. data/lib/itsi/server/grpc/grpc_interface.rb +2 -2
  57. data/lib/itsi/server/rack/handler/itsi.rb +3 -1
  58. data/lib/itsi/server/rack_interface.rb +17 -12
  59. data/lib/itsi/server/scheduler_interface.rb +2 -0
  60. data/lib/itsi/server/version.rb +1 -1
  61. data/lib/itsi/server.rb +1 -0
  62. data/lib/ruby_lsp/itsi/addon.rb +12 -13
  63. metadata +7 -1
@@ -0,0 +1,142 @@
1
+ use bytes::{Bytes, BytesMut};
2
+ use futures::Stream;
3
+ use std::convert::Infallible;
4
+ use std::future::Future;
5
+ use std::pin::Pin;
6
+ use std::task::{Context, Poll};
7
+ use std::time::Duration;
8
+ use tokio::sync::mpsc::Receiver;
9
+ use tokio::sync::watch;
10
+ use tokio::time::{sleep, Sleep};
11
+
12
+ use super::serve_strategy::single_mode::RunningPhase;
13
+
14
+ #[derive(Debug)]
15
+ pub struct FrameStream {
16
+ receiver: Receiver<Bytes>,
17
+ shutdown_rx: watch::Receiver<RunningPhase>,
18
+ drained: bool,
19
+ }
20
+
21
+ impl FrameStream {
22
+ pub fn new(receiver: Receiver<Bytes>, shutdown_rx: watch::Receiver<RunningPhase>) -> Self {
23
+ Self {
24
+ receiver,
25
+ shutdown_rx,
26
+ drained: false,
27
+ }
28
+ }
29
+ }
30
+
31
+ impl Stream for FrameStream {
32
+ type Item = Result<Bytes, Infallible>;
33
+
34
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
35
+ let this = self.get_mut();
36
+
37
+ if this.drained {
38
+ return Poll::Ready(None);
39
+ }
40
+
41
+ match Pin::new(&mut this.receiver).poll_recv(cx) {
42
+ Poll::Ready(Some(bytes)) => Poll::Ready(Some(Ok(bytes))),
43
+ Poll::Ready(None) => {
44
+ this.drained = true;
45
+ Poll::Ready(None)
46
+ }
47
+ Poll::Pending => {
48
+ if this.shutdown_rx.has_changed().unwrap_or(false)
49
+ && *this.shutdown_rx.borrow() == RunningPhase::ShutdownPending
50
+ {
51
+ while let Ok(bytes) = this.receiver.try_recv() {
52
+ return Poll::Ready(Some(Ok(bytes)));
53
+ }
54
+ this.drained = true;
55
+ return Poll::Ready(None);
56
+ }
57
+
58
+ Poll::Pending
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ /// BufferedStream wraps a stream of Bytes and coalesces chunks into a larger buffer,
65
+ /// flushing either after `max_flush_bytes` is reached or `max_flush_interval` elapses.
66
+ pub struct BufferedStream<S> {
67
+ inner: S,
68
+ buffer: BytesMut,
69
+ max_flush_bytes: usize,
70
+ max_flush_interval: Duration,
71
+ flush_deadline: Option<Pin<Box<Sleep>>>,
72
+ }
73
+
74
+ impl<S> BufferedStream<S> {
75
+ pub fn new(inner: S, max_flush_bytes: usize, max_flush_interval: Duration) -> Self {
76
+ Self {
77
+ inner,
78
+ buffer: BytesMut::with_capacity(max_flush_bytes),
79
+ max_flush_bytes,
80
+ max_flush_interval,
81
+ flush_deadline: None,
82
+ }
83
+ }
84
+ }
85
+
86
+ impl<S> Stream for BufferedStream<S>
87
+ where
88
+ S: Stream<Item = Result<Bytes, Infallible>> + Unpin,
89
+ {
90
+ type Item = Result<Bytes, Infallible>;
91
+
92
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
93
+ let this = self.get_mut();
94
+
95
+ loop {
96
+ // Flush on timer if needed
97
+ if let Some(deadline) = &mut this.flush_deadline {
98
+ if Pin::new(deadline).poll(cx).is_ready() && !this.buffer.is_empty() {
99
+ let flushed = this.buffer.split().freeze();
100
+ this.flush_deadline = None;
101
+ return Poll::Ready(Some(Ok(flushed)));
102
+ }
103
+ }
104
+
105
+ match Pin::new(&mut this.inner).poll_next(cx) {
106
+ Poll::Ready(Some(Ok(bytes))) => {
107
+ this.buffer.extend_from_slice(&bytes);
108
+
109
+ if bytes.is_empty() || this.buffer.len() >= this.max_flush_bytes {
110
+ let flushed = this.buffer.split().freeze();
111
+ this.flush_deadline = None;
112
+ return Poll::Ready(Some(Ok(flushed)));
113
+ }
114
+
115
+ if this.flush_deadline.is_none() {
116
+ this.flush_deadline = Some(Box::pin(sleep(this.max_flush_interval)));
117
+ }
118
+ }
119
+ Poll::Ready(None) => {
120
+ if this.buffer.is_empty() {
121
+ return Poll::Ready(None);
122
+ } else {
123
+ let flushed = this.buffer.split().freeze();
124
+ this.flush_deadline = None;
125
+ return Poll::Ready(Some(Ok(flushed)));
126
+ }
127
+ }
128
+ Poll::Pending => {
129
+ if let Some(deadline) = &mut this.flush_deadline {
130
+ let deadline = deadline.as_mut();
131
+ if deadline.poll(cx).is_ready() && !this.buffer.is_empty() {
132
+ let flushed = this.buffer.split().freeze();
133
+ this.flush_deadline = None;
134
+ return Poll::Ready(Some(Ok(flushed)));
135
+ }
136
+ }
137
+ return Poll::Pending;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
@@ -1,13 +1,146 @@
1
- use std::convert::Infallible;
2
-
3
1
  use bytes::Bytes;
4
- use http::{Request, Response};
5
- use http_body_util::combinators::BoxBody;
6
- use hyper::body::Incoming;
2
+ use core::fmt;
3
+ use futures::Stream;
4
+ use futures_util::TryStreamExt;
5
+ use http::Request;
6
+ use http_body_util::{combinators::WithTrailers, BodyExt, Either, Empty, Full, StreamBody};
7
+ use hyper::body::{Body, Frame, Incoming, SizeHint};
8
+ use std::{
9
+ convert::Infallible,
10
+ pin::Pin,
11
+ task::{Context, Poll},
12
+ };
7
13
 
8
14
  use super::size_limited_incoming::SizeLimitedIncoming;
9
15
 
10
- pub type HttpResponse = Response<BoxBody<Bytes, Infallible>>;
16
+ type Inner = Either<Full<Bytes>, Empty<Bytes>>;
17
+
18
+ type BoxStream =
19
+ Pin<Box<dyn Stream<Item = Result<Frame<Bytes>, Infallible>> + Send + Sync + 'static>>;
20
+
21
+ pub struct PlainBody(Either<StreamBody<BoxStream>, Inner>);
22
+
23
+ impl fmt::Debug for PlainBody {
24
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25
+ match &self.0 {
26
+ Either::Left(_) => f.write_str("PlainBody::Stream(..)"),
27
+ Either::Right(inner) => match inner {
28
+ Either::Left(full) => f.debug_tuple("PlainBody::Full").field(full).finish(),
29
+ Either::Right(_) => f.write_str("PlainBody::Empty"),
30
+ },
31
+ }
32
+ }
33
+ }
34
+ type DynErr = Box<dyn std::error::Error + Send + Sync>;
35
+
36
+ impl Body for PlainBody {
37
+ type Data = Bytes;
38
+ type Error = DynErr;
39
+
40
+ fn poll_frame(
41
+ self: Pin<&mut Self>,
42
+ cx: &mut Context<'_>,
43
+ ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
44
+ unsafe { self.map_unchecked_mut(|s| &mut s.0) }.poll_frame(cx)
45
+ }
46
+
47
+ fn size_hint(&self) -> SizeHint {
48
+ self.0.size_hint()
49
+ }
50
+ }
51
+
52
+ impl PlainBody {
53
+ fn stream<S>(s: S) -> Self
54
+ where
55
+ S: Stream<Item = Result<Bytes, Infallible>> + Send + Sync + 'static,
56
+ {
57
+ let boxed: BoxStream = Box::pin(s.map_ok(Frame::data));
58
+ Self(Either::Left(StreamBody::new(boxed)))
59
+ }
60
+
61
+ fn full(bytes: Bytes) -> Self {
62
+ Self(Either::Right(Either::Left(Full::new(bytes))))
63
+ }
64
+
65
+ fn empty() -> Self {
66
+ Self(Either::Right(Either::Right(Empty::new())))
67
+ }
68
+ }
69
+
70
+ type BoxTrailers = Pin<
71
+ Box<dyn std::future::Future<Output = Option<Result<http::HeaderMap, DynErr>>> + Send + Sync>,
72
+ >;
73
+
74
+ pub enum HttpBody {
75
+ Plain(PlainBody),
76
+ WithT(WithTrailers<PlainBody, BoxTrailers>),
77
+ }
78
+
79
+ impl fmt::Debug for HttpBody {
80
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81
+ match self {
82
+ HttpBody::Plain(b) => f.debug_tuple("HttpBody::Plain").field(b).finish(),
83
+ HttpBody::WithT(_) => f.write_str("HttpBody::WithT(..)"),
84
+ }
85
+ }
86
+ }
87
+
88
+ impl Body for HttpBody {
89
+ type Data = Bytes;
90
+ type Error = DynErr;
91
+
92
+ fn poll_frame(
93
+ self: Pin<&mut Self>,
94
+ cx: &mut Context<'_>,
95
+ ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
96
+ unsafe {
97
+ match self.get_unchecked_mut() {
98
+ HttpBody::Plain(b) => Pin::new_unchecked(b).poll_frame(cx),
99
+ HttpBody::WithT(b) => Pin::new_unchecked(b).poll_frame(cx),
100
+ }
101
+ }
102
+ }
103
+
104
+ fn size_hint(&self) -> SizeHint {
105
+ match self {
106
+ HttpBody::Plain(b) => b.size_hint(),
107
+ HttpBody::WithT(b) => b.size_hint(),
108
+ }
109
+ }
110
+ }
111
+
112
+ impl HttpBody {
113
+ pub fn stream<S>(s: S) -> Self
114
+ where
115
+ S: Stream<Item = Result<Bytes, Infallible>> + Send + Sync + 'static,
116
+ {
117
+ HttpBody::Plain(PlainBody::stream(s))
118
+ }
119
+
120
+ pub fn full(bytes: Bytes) -> Self {
121
+ HttpBody::Plain(PlainBody::full(bytes))
122
+ }
123
+
124
+ pub fn empty() -> Self {
125
+ HttpBody::Plain(PlainBody::empty())
126
+ }
127
+
128
+ pub fn with_trailers<Fut>(self, fut: Fut) -> Self
129
+ where
130
+ Fut: std::future::Future<Output = Option<Result<http::HeaderMap, DynErr>>>
131
+ + Send
132
+ + Sync
133
+ + 'static,
134
+ {
135
+ let boxed: BoxTrailers = Box::pin(fut);
136
+ match self {
137
+ HttpBody::Plain(p) => HttpBody::WithT(p.with_trailers(boxed)),
138
+ already @ HttpBody::WithT(_) => already,
139
+ }
140
+ }
141
+ }
142
+
143
+ pub type HttpResponse = http::Response<HttpBody>;
11
144
  pub type HttpRequest = Request<SizeLimitedIncoming<Incoming>>;
12
145
 
13
146
  pub trait ConversionExt {
@@ -64,7 +197,7 @@ impl PathExt for str {
64
197
  if self == "/" {
65
198
  self
66
199
  } else {
67
- self.trim_end_matches("/")
200
+ self.trim_end_matches('/')
68
201
  }
69
202
  }
70
203
  }
@@ -91,7 +224,7 @@ impl RequestExt for HttpRequest {
91
224
  fn query_param(&self, query_name: &str) -> Option<&str> {
92
225
  self.uri()
93
226
  .query()
94
- .and_then(|query| query.split('&').find(|param| param.starts_with(query_name)))
95
- .map(|param| param.split('=').nth(1).unwrap_or(""))
227
+ .and_then(|q| q.split('&').find(|p| p.starts_with(query_name)))
228
+ .map(|p| p.split('=').nth(1).unwrap_or(""))
96
229
  }
97
230
  }
@@ -2,6 +2,7 @@ use pin_project::pin_project;
2
2
  use tokio::net::{TcpStream, UnixStream};
3
3
  use tokio_rustls::server::TlsStream;
4
4
 
5
+ use std::io::{self, IoSlice};
5
6
  use std::os::unix::io::{AsRawFd, RawFd};
6
7
  use std::pin::Pin;
7
8
  use std::task::{Context, Poll};
@@ -34,12 +35,12 @@ pub enum IoStream {
34
35
  }
35
36
 
36
37
  impl IoStream {
37
- pub fn addr(&self) -> SockAddr {
38
+ pub fn addr(&self) -> String {
38
39
  match self {
39
- IoStream::Tcp { addr, .. } => addr.clone(),
40
- IoStream::TcpTls { addr, .. } => addr.clone(),
41
- IoStream::Unix { addr, .. } => addr.clone(),
42
- IoStream::UnixTls { addr, .. } => addr.clone(),
40
+ IoStream::Tcp { addr, .. } => addr.to_string(),
41
+ IoStream::TcpTls { addr, .. } => addr.to_string(),
42
+ IoStream::Unix { addr, .. } => addr.to_string(),
43
+ IoStream::UnixTls { addr, .. } => addr.to_string(),
43
44
  }
44
45
  }
45
46
  }
@@ -90,6 +91,28 @@ impl AsyncWrite for IoStream {
90
91
  IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_shutdown(cx),
91
92
  }
92
93
  }
94
+
95
+ fn poll_write_vectored(
96
+ self: Pin<&mut Self>,
97
+ cx: &mut Context<'_>,
98
+ bufs: &[IoSlice<'_>],
99
+ ) -> Poll<io::Result<usize>> {
100
+ match self.project() {
101
+ IoStreamEnumProj::Tcp { stream, .. } => stream.poll_write_vectored(cx, bufs),
102
+ IoStreamEnumProj::TcpTls { stream, .. } => stream.poll_write_vectored(cx, bufs),
103
+ IoStreamEnumProj::Unix { stream, .. } => stream.poll_write_vectored(cx, bufs),
104
+ IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_write_vectored(cx, bufs),
105
+ }
106
+ }
107
+
108
+ fn is_write_vectored(&self) -> bool {
109
+ match self {
110
+ IoStream::Tcp { stream, .. } => stream.is_write_vectored(),
111
+ IoStream::TcpTls { stream, .. } => stream.is_write_vectored(),
112
+ IoStream::Unix { stream, .. } => stream.is_write_vectored(),
113
+ IoStream::UnixTls { stream, .. } => stream.is_write_vectored(),
114
+ }
115
+ }
93
116
  }
94
117
 
95
118
  impl AsRawFd for IoStream {
@@ -1,4 +1,4 @@
1
- #[derive(Debug, Clone)]
1
+ #[derive(Debug, Clone, PartialEq)]
2
2
  pub enum LifecycleEvent {
3
3
  Start,
4
4
  Shutdown,
@@ -3,7 +3,6 @@ use base64::{engine::general_purpose, Engine};
3
3
  use bytes::Bytes;
4
4
  use either::Either;
5
5
  use http::{Response, StatusCode};
6
- use http_body_util::{combinators::BoxBody, Full};
7
6
  use magnus::error::Result;
8
7
  use serde::{Deserialize, Serialize};
9
8
  use std::collections::HashMap;
@@ -11,7 +10,7 @@ use std::str;
11
10
  use tracing::debug;
12
11
 
13
12
  use crate::{
14
- server::http_message_types::{HttpRequest, HttpResponse, RequestExt},
13
+ server::http_message_types::{HttpBody, HttpRequest, HttpResponse, RequestExt},
15
14
  services::{itsi_http_service::HttpRequestContext, password_hasher::verify_password_hash},
16
15
  };
17
16
 
@@ -34,7 +33,7 @@ impl AuthBasic {
34
33
  "WWW-Authenticate",
35
34
  format!("Basic realm=\"{}\"", self.realm),
36
35
  )
37
- .body(BoxBody::new(Full::new(Bytes::from("Unauthorized"))))
36
+ .body(HttpBody::full(Bytes::from("Unauthorized")))
38
37
  .unwrap()
39
38
  }
40
39
  }
@@ -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::{combinators::BoxBody, BodyExt, Full, StreamBody};
24
- use hyper::body::{Body, Frame};
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) -> BoxBody<Bytes, Infallible>
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).map(|res| {
134
- res.map(Frame::data)
135
- .map_err(|_| -> Infallible { unreachable!("We handle IO errors above") })
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
- BoxBody::new(Full::new(Bytes::from(compressed_bytes)))
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(BoxBody::new(Empty::new()))
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::{combinators::BoxBody, BodyExt, Empty};
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(BoxBody::new(Empty::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
  }
@@ -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(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())),
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(Full::new(
21
+ 500 => ContentSource::Static(
24
22
  include_str!("../../../../default_responses/html/500.html").into(),
25
- )),
26
- 404 => ContentSource::Static(Full::new(
23
+ ),
24
+ 404 => ContentSource::Static(
27
25
  include_str!("../../../../default_responses/html/404.html").into(),
28
- )),
29
- 401 => ContentSource::Static(Full::new(
26
+ ),
27
+ 401 => ContentSource::Static(
30
28
  include_str!("../../../../default_responses/html/401.html").into(),
31
- )),
32
- 403 => ContentSource::Static(Full::new(
29
+ ),
30
+ 403 => ContentSource::Static(
33
31
  include_str!("../../../../default_responses/html/403.html").into(),
34
- )),
35
- 413 => ContentSource::Static(Full::new(
32
+ ),
33
+ 413 => ContentSource::Static(
36
34
  include_str!("../../../../default_responses/html/413.html").into(),
37
- )),
38
- 429 => ContentSource::Static(Full::new(
35
+ ),
36
+ 429 => ContentSource::Static(
39
37
  include_str!("../../../../default_responses/html/429.html").into(),
40
- )),
41
- 502 => ContentSource::Static(Full::new(
38
+ ),
39
+ 502 => ContentSource::Static(
42
40
  include_str!("../../../../default_responses/html/502.html").into(),
43
- )),
44
- 503 => ContentSource::Static(Full::new(
41
+ ),
42
+ 503 => ContentSource::Static(
45
43
  include_str!("../../../../default_responses/html/503.html").into(),
46
- )),
47
- 504 => ContentSource::Static(Full::new(
44
+ ),
45
+ 504 => ContentSource::Static(
48
46
  include_str!("../../../../default_responses/html/504.html").into(),
49
- )),
50
- _ => ContentSource::Static(Full::new(
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(Full::new(
53
+ 500 => ContentSource::Static(
56
54
  include_str!("../../../../default_responses/json/500.json").into(),
57
- )),
58
- 404 => ContentSource::Static(Full::new(
55
+ ),
56
+ 404 => ContentSource::Static(
59
57
  include_str!("../../../../default_responses/json/404.json").into(),
60
- )),
61
- 401 => ContentSource::Static(Full::new(
58
+ ),
59
+ 401 => ContentSource::Static(
62
60
  include_str!("../../../../default_responses/json/401.json").into(),
63
- )),
64
- 403 => ContentSource::Static(Full::new(
61
+ ),
62
+ 403 => ContentSource::Static(
65
63
  include_str!("../../../../default_responses/json/403.json").into(),
66
- )),
67
- 413 => ContentSource::Static(Full::new(
64
+ ),
65
+ 413 => ContentSource::Static(
68
66
  include_str!("../../../../default_responses/json/413.json").into(),
69
- )),
70
- 429 => ContentSource::Static(Full::new(
67
+ ),
68
+ 429 => ContentSource::Static(
71
69
  include_str!("../../../../default_responses/json/429.json").into(),
72
- )),
73
- 502 => ContentSource::Static(Full::new(
70
+ ),
71
+ 502 => ContentSource::Static(
74
72
  include_str!("../../../../default_responses/json/502.json").into(),
75
- )),
76
- 503 => ContentSource::Static(Full::new(
73
+ ),
74
+ 503 => ContentSource::Static(
77
75
  include_str!("../../../../default_responses/json/503.json").into(),
78
- )),
79
- 504 => ContentSource::Static(Full::new(
76
+ ),
77
+ 504 => ContentSource::Static(
80
78
  include_str!("../../../../default_responses/json/504.json").into(),
81
- )),
82
- _ => ContentSource::Static(Full::new("Unexpected Error".into())),
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) -> BoxBody<Bytes, Infallible> {
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) => BoxBody::new(Full::new(Bytes::from(bytes))),
97
- ContentSource::Static(bytes) => BoxBody::new(bytes),
98
- ContentSource::File(_) => BoxBody::new(Full::new(Bytes::from("Unexpected error"))),
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 {