Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions actix-http/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler> {
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
max_buffer_size: Option<usize>,
secure: bool,
local_addr: Option<net::SocketAddr>,
expect: X,
Expand All @@ -38,6 +39,7 @@ where
keep_alive: KeepAlive::default(),
client_request_timeout: Duration::from_secs(5),
client_disconnect_timeout: Duration::ZERO,
max_buffer_size: None,
secure: false,
local_addr: None,

Expand Down Expand Up @@ -124,6 +126,15 @@ where
self.client_disconnect_timeout(dur)
}

/// Set maximum buffer size.
///
/// Defines the maximum size of the buffer. When the size is reached, the dispatcher
/// will flush the data to the IO streams
pub fn max_buffer_size(mut self, size: usize) -> Self {
self.max_buffer_size = Some(size);
self
}

/// Provide service for `EXPECT: 100-Continue` support.
///
/// Service get called with request that contains `EXPECT` header.
Expand All @@ -140,6 +151,7 @@ where
keep_alive: self.keep_alive,
client_request_timeout: self.client_request_timeout,
client_disconnect_timeout: self.client_disconnect_timeout,
max_buffer_size: self.max_buffer_size,
secure: self.secure,
local_addr: self.local_addr,
expect: expect.into_factory(),
Expand All @@ -164,6 +176,7 @@ where
keep_alive: self.keep_alive,
client_request_timeout: self.client_request_timeout,
client_disconnect_timeout: self.client_disconnect_timeout,
max_buffer_size: self.max_buffer_size,
secure: self.secure,
local_addr: self.local_addr,
expect: self.expect,
Expand Down Expand Up @@ -199,6 +212,7 @@ where
self.keep_alive,
self.client_request_timeout,
self.client_disconnect_timeout,
self.max_buffer_size,
self.secure,
self.local_addr,
);
Expand All @@ -224,6 +238,7 @@ where
self.keep_alive,
self.client_request_timeout,
self.client_disconnect_timeout,
self.max_buffer_size,
self.secure,
self.local_addr,
);
Expand All @@ -246,6 +261,7 @@ where
self.keep_alive,
self.client_request_timeout,
self.client_disconnect_timeout,
self.max_buffer_size,
self.secure,
self.local_addr,
);
Expand Down
18 changes: 16 additions & 2 deletions actix-http/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct Inner {
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
max_buffer_size: Option<usize>,
secure: bool,
local_addr: Option<std::net::SocketAddr>,
date_service: DateService,
Expand All @@ -28,6 +29,7 @@ impl Default for ServiceConfig {
KeepAlive::default(),
Duration::from_secs(5),
Duration::ZERO,
None,
false,
None,
)
Expand All @@ -40,13 +42,15 @@ impl ServiceConfig {
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
max_buffer_size: Option<usize>,
secure: bool,
local_addr: Option<net::SocketAddr>,
) -> ServiceConfig {
ServiceConfig(Rc::new(Inner {
keep_alive: keep_alive.normalize(),
client_request_timeout,
client_disconnect_timeout,
max_buffer_size,
secure,
local_addr,
date_service: DateService::new(),
Expand Down Expand Up @@ -104,6 +108,10 @@ impl ServiceConfig {
self.0.date_service.now()
}

pub fn max_buffer_size(&self) -> Option<usize> {
self.0.max_buffer_size
}

/// Writes date header to `dst` buffer.
///
/// Low-level method that utilizes the built-in efficient date service, requiring fewer syscalls
Expand Down Expand Up @@ -143,8 +151,14 @@ mod tests {

#[actix_rt::test]
async fn test_date_service_update() {
let settings =
ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
let settings = ServiceConfig::new(
KeepAlive::Os,
Duration::ZERO,
Duration::ZERO,
None,
false,
None,
);

yield_now().await;

Expand Down
6 changes: 4 additions & 2 deletions actix-http/src/h1/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pin_project! {
pub(super) io: Option<T>,
read_buf: BytesMut,
write_buf: BytesMut,
max_buffer_size: usize,
codec: Codec,
}
}
Expand Down Expand Up @@ -278,6 +279,7 @@ where
io: Some(io),
read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
max_buffer_size: config.max_buffer_size().unwrap_or(MAX_BUFFER_SIZE),
codec: Codec::new(config),
},
},
Expand Down Expand Up @@ -493,7 +495,7 @@ where
StateProj::SendPayload { mut body } => {
// keep populate writer buffer until buffer size limit hit,
// get blocked or finished.
while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE {
while this.write_buf.len() < *this.max_buffer_size {
match body.as_mut().poll_next(cx) {
Poll::Ready(Some(Ok(item))) => {
this.codec
Expand Down Expand Up @@ -532,7 +534,7 @@ where

// keep populate writer buffer until buffer size limit hit,
// get blocked or finished.
while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE {
while this.write_buf.len() < *this.max_buffer_size {
match body.as_mut().poll_next(cx) {
Poll::Ready(Some(Ok(item))) => {
this.codec
Expand Down
9 changes: 9 additions & 0 deletions actix-http/src/h1/dispatcher_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ async fn late_request() {
KeepAlive::Disabled,
Duration::from_millis(100),
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -149,6 +150,7 @@ async fn oneshot_connection() {
KeepAlive::Disabled,
Duration::from_millis(100),
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -210,6 +212,7 @@ async fn keep_alive_timeout() {
KeepAlive::Timeout(Duration::from_millis(200)),
Duration::from_millis(100),
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -289,6 +292,7 @@ async fn keep_alive_follow_up_req() {
KeepAlive::Timeout(Duration::from_millis(500)),
Duration::from_millis(100),
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -453,6 +457,7 @@ async fn pipelining_ok_then_ok() {
KeepAlive::Disabled,
Duration::from_millis(1),
Duration::from_millis(1),
None,
false,
None,
);
Expand Down Expand Up @@ -523,6 +528,7 @@ async fn pipelining_ok_then_bad() {
KeepAlive::Disabled,
Duration::from_millis(1),
Duration::from_millis(1),
None,
false,
None,
);
Expand Down Expand Up @@ -586,6 +592,7 @@ async fn expect_handling() {
KeepAlive::Disabled,
Duration::ZERO,
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -663,6 +670,7 @@ async fn expect_eager() {
KeepAlive::Disabled,
Duration::ZERO,
Duration::ZERO,
None,
false,
None,
);
Expand Down Expand Up @@ -746,6 +754,7 @@ async fn upgrade_handling() {
KeepAlive::Disabled,
Duration::ZERO,
Duration::ZERO,
None,
false,
None,
);
Expand Down
15 changes: 15 additions & 0 deletions actix-web/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct Config {
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
max_buffer_size: Option<usize>,
#[allow(dead_code)] // only dead when no TLS features are enabled
tls_handshake_timeout: Option<Duration>,
}
Expand Down Expand Up @@ -116,6 +117,7 @@ where
keep_alive: KeepAlive::default(),
client_request_timeout: Duration::from_secs(5),
client_disconnect_timeout: Duration::from_secs(1),
max_buffer_size: None,
tls_handshake_timeout: None,
})),
backlog: 1024,
Expand Down Expand Up @@ -234,6 +236,15 @@ where
self
}

/// Set maximum buffer size.
///
/// Defines the maximum size of the write buffer. When the size is reached, the dispatcher
/// will flush the data to the IO streams
pub fn max_buffer_size(self, size: usize) -> Self {
self.config.lock().unwrap().max_buffer_size = Some(size);
self
}

/// Sets TLS handshake timeout.
///
/// Defines a timeout for TLS handshake. If the TLS handshake does not complete within this
Expand Down Expand Up @@ -560,6 +571,10 @@ where
.client_disconnect_timeout(cfg.client_disconnect_timeout)
.local_addr(addr);

if let Some(size) = cfg.max_buffer_size {
svc = svc.max_buffer_size(size);
};

if let Some(handler) = on_connect_fn.clone() {
svc =
svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
Expand Down
Loading