1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-05-19 16:58:14 +00:00
actix-web/actix-http/src/config.rs

237 lines
6.8 KiB
Rust
Raw Normal View History

use std::{
net,
rc::Rc,
2022-01-31 17:30:34 +00:00
time::{Duration, Instant},
};
2019-03-26 18:54:35 +00:00
use bytes::BytesMut;
2022-01-31 17:30:34 +00:00
use crate::{date::DateService, KeepAlive};
2019-03-26 18:54:35 +00:00
2022-01-31 17:30:34 +00:00
/// HTTP service configuration.
#[derive(Debug, Clone)]
2019-03-26 18:54:35 +00:00
pub struct ServiceConfig(Rc<Inner>);
2022-01-31 17:30:34 +00:00
#[derive(Debug)]
2019-03-26 18:54:35 +00:00
struct Inner {
2022-01-31 17:30:34 +00:00
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
2019-12-02 11:33:11 +00:00
secure: bool,
local_addr: Option<std::net::SocketAddr>,
2021-02-12 21:52:58 +00:00
date_service: DateService,
2019-03-26 18:54:35 +00:00
}
impl Default for ServiceConfig {
fn default() -> Self {
2022-01-31 17:30:34 +00:00
Self::new(
KeepAlive::default(),
Duration::from_secs(5),
Duration::ZERO,
false,
None,
)
2019-03-26 18:54:35 +00:00
}
}
impl ServiceConfig {
2022-07-24 15:42:35 +00:00
/// Create instance of `ServiceConfig`.
2019-03-26 18:54:35 +00:00
pub fn new(
keep_alive: KeepAlive,
2022-01-31 17:30:34 +00:00
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
2019-12-02 11:33:11 +00:00
secure: bool,
local_addr: Option<net::SocketAddr>,
2019-03-26 18:54:35 +00:00
) -> ServiceConfig {
ServiceConfig(Rc::new(Inner {
2022-01-31 17:30:34 +00:00
keep_alive: keep_alive.normalize(),
client_request_timeout,
client_disconnect_timeout,
2019-12-02 11:33:11 +00:00
secure,
local_addr,
2021-02-12 21:52:58 +00:00
date_service: DateService::new(),
2019-03-26 18:54:35 +00:00
}))
}
2022-01-31 17:30:34 +00:00
/// Returns `true` if connection is secure (i.e., using TLS / HTTPS).
2019-12-02 11:33:11 +00:00
#[inline]
pub fn secure(&self) -> bool {
self.0.secure
}
/// Returns the local address that this server is bound to.
2021-07-12 15:55:24 +00:00
///
/// Returns `None` for connections via UDS (Unix Domain Socket).
2021-02-11 22:39:54 +00:00
#[inline]
2019-12-02 11:33:11 +00:00
pub fn local_addr(&self) -> Option<net::SocketAddr> {
self.0.local_addr
}
2022-01-31 17:30:34 +00:00
/// Connection keep-alive setting.
2021-02-11 22:39:54 +00:00
#[inline]
2022-01-31 17:30:34 +00:00
pub fn keep_alive(&self) -> KeepAlive {
2019-03-26 18:54:35 +00:00
self.0.keep_alive
}
2022-01-31 17:30:34 +00:00
/// Creates a time object representing the deadline for this connection's keep-alive period, if
/// enabled.
///
/// When [`KeepAlive::Os`] or [`KeepAlive::Disabled`] is set, this will return `None`.
pub fn keep_alive_deadline(&self) -> Option<Instant> {
match self.keep_alive() {
KeepAlive::Timeout(dur) => Some(self.now() + dur),
KeepAlive::Os => None,
KeepAlive::Disabled => None,
2019-03-26 18:54:35 +00:00
}
}
2022-01-31 17:30:34 +00:00
/// Creates a time object representing the deadline for the client to finish sending the head of
/// its first request.
///
/// Returns `None` if this `ServiceConfig was` constructed with `client_request_timeout: 0`.
pub fn client_request_deadline(&self) -> Option<Instant> {
let timeout = self.0.client_request_timeout;
(timeout != Duration::ZERO).then(|| self.now() + timeout)
2019-03-26 18:54:35 +00:00
}
2022-01-31 17:30:34 +00:00
/// Creates a time object representing the deadline for the client to disconnect.
pub fn client_disconnect_deadline(&self) -> Option<Instant> {
let timeout = self.0.client_disconnect_timeout;
(timeout != Duration::ZERO).then(|| self.now() + timeout)
2019-03-26 18:54:35 +00:00
}
pub(crate) fn now(&self) -> Instant {
2021-02-12 21:52:58 +00:00
self.0.date_service.now()
2019-03-26 18:54:35 +00:00
}
2022-02-04 20:37:33 +00:00
/// Writes date header to `dst` buffer.
///
/// Low-level method that utilizes the built-in efficient date service, requiring fewer syscalls
/// than normal. Note that a CRLF (`\r\n`) is included in what is written.
#[doc(hidden)]
pub fn write_date_header(&self, dst: &mut BytesMut, camel_case: bool) {
let mut buf: [u8; 37] = [0; 37];
buf[..6].copy_from_slice(if camel_case { b"Date: " } else { b"date: " });
2019-07-18 11:37:41 +00:00
self.0
2021-02-12 21:52:58 +00:00
.date_service
2022-01-31 17:30:34 +00:00
.with_date(|date| buf[6..35].copy_from_slice(&date.bytes));
2022-02-04 20:37:33 +00:00
buf[35..].copy_from_slice(b"\r\n");
2019-03-26 18:54:35 +00:00
dst.extend_from_slice(&buf);
}
2022-01-31 21:22:23 +00:00
#[allow(unused)] // used with `http2` feature flag
2022-01-31 17:30:34 +00:00
pub(crate) fn write_date_header_value(&self, dst: &mut BytesMut) {
2019-07-18 11:37:41 +00:00
self.0
2021-02-12 21:52:58 +00:00
.date_service
2022-01-31 17:30:34 +00:00
.with_date(|date| dst.extend_from_slice(&date.bytes));
2019-03-26 18:54:35 +00:00
}
}
#[cfg(test)]
mod tests {
2022-01-31 17:30:34 +00:00
use actix_rt::{
task::yield_now,
time::{sleep, sleep_until},
};
use memchr::memmem;
2021-02-12 21:52:58 +00:00
2023-07-17 01:38:12 +00:00
use super::*;
use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
2021-02-12 21:52:58 +00:00
#[actix_rt::test]
async fn test_date_service_update() {
2022-01-31 17:30:34 +00:00
let settings =
ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
2021-02-12 21:52:58 +00:00
yield_now().await;
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf1, false);
2021-02-12 21:52:58 +00:00
let now1 = settings.now();
2022-01-31 17:30:34 +00:00
sleep_until((Instant::now() + Duration::from_secs(2)).into()).await;
2021-02-12 21:52:58 +00:00
yield_now().await;
let now2 = settings.now();
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf2, false);
2021-02-12 21:52:58 +00:00
assert_ne!(now1, now2);
assert_ne!(buf1, buf2);
drop(settings);
2021-07-09 22:57:21 +00:00
// Ensure the task will drop eventually
let mut times = 0;
while !notify_on_drop::is_dropped() {
sleep(Duration::from_millis(100)).await;
times += 1;
assert!(times < 10, "Timeout waiting for task drop");
}
2021-02-12 21:52:58 +00:00
}
#[actix_rt::test]
async fn test_date_service_drop() {
let service = Rc::new(DateService::new());
// yield so date service have a chance to register the spawned timer update task.
yield_now().await;
let clone1 = service.clone();
let clone2 = service.clone();
let clone3 = service.clone();
drop(clone1);
assert!(!notify_on_drop::is_dropped());
2021-02-12 21:52:58 +00:00
drop(clone2);
assert!(!notify_on_drop::is_dropped());
2021-02-12 21:52:58 +00:00
drop(clone3);
assert!(!notify_on_drop::is_dropped());
2021-02-12 21:52:58 +00:00
drop(service);
2021-07-09 22:57:21 +00:00
// Ensure the task will drop eventually
let mut times = 0;
while !notify_on_drop::is_dropped() {
sleep(Duration::from_millis(100)).await;
times += 1;
assert!(times < 10, "Timeout waiting for task drop");
}
}
2019-03-26 18:54:35 +00:00
#[test]
fn test_date_len() {
assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
}
2019-11-26 05:25:50 +00:00
#[actix_rt::test]
async fn test_date() {
let settings = ServiceConfig::default();
2019-11-26 05:25:50 +00:00
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf1, false);
2019-11-26 05:25:50 +00:00
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf2, false);
2019-11-26 05:25:50 +00:00
assert_eq!(buf1, buf2);
2019-03-26 18:54:35 +00:00
}
#[actix_rt::test]
async fn test_date_camel_case() {
let settings = ServiceConfig::default();
let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf, false);
assert!(memmem::find(&buf, b"date:").is_some());
let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
2022-01-31 17:30:34 +00:00
settings.write_date_header(&mut buf, true);
assert!(memmem::find(&buf, b"Date:").is_some());
}
2019-03-26 18:54:35 +00:00
}