mirror of
https://github.com/actix/actix-web.git
synced 2024-11-24 10:31:07 +00:00
apply standard formatting
This commit is contained in:
parent
60c76c5e10
commit
79a38e0628
138 changed files with 916 additions and 1180 deletions
|
@ -1,2 +1,3 @@
|
|||
max_width = 96
|
||||
reorder_imports = true
|
||||
group_imports = "StdExternalCrate"
|
||||
imports_granularity = "Crate"
|
||||
use_field_init_shorthand = true
|
||||
|
|
|
@ -7,11 +7,10 @@ use std::{
|
|||
};
|
||||
|
||||
use actix_web::{error::Error, web::Bytes};
|
||||
use futures_core::{ready, Stream};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
#[cfg(feature = "experimental-io-uring")]
|
||||
use bytes::BytesMut;
|
||||
use futures_core::{ready, Stream};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
use super::named::File;
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
use std::{fmt::Write, fs::DirEntry, io, path::Path, path::PathBuf};
|
||||
use std::{
|
||||
fmt::Write,
|
||||
fs::DirEntry,
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use actix_web::{dev::ServiceResponse, HttpRequest, HttpResponse};
|
||||
use percent_encoding::{utf8_percent_encode, CONTROLS};
|
||||
|
|
|
@ -8,8 +8,7 @@ use std::{
|
|||
use actix_service::{boxed, IntoServiceFactory, ServiceFactory, ServiceFactoryExt};
|
||||
use actix_web::{
|
||||
dev::{
|
||||
AppService, HttpServiceFactory, RequestHead, ResourceDef, ServiceRequest,
|
||||
ServiceResponse,
|
||||
AppService, HttpServiceFactory, RequestHead, ResourceDef, ServiceRequest, ServiceResponse,
|
||||
},
|
||||
error::Error,
|
||||
guard::Guard,
|
||||
|
@ -301,12 +300,8 @@ impl Files {
|
|||
pub fn default_handler<F, U>(mut self, f: F) -> Self
|
||||
where
|
||||
F: IntoServiceFactory<U, ServiceRequest>,
|
||||
U: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Config = (),
|
||||
Response = ServiceResponse,
|
||||
Error = Error,
|
||||
> + 'static,
|
||||
U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
|
||||
+ 'static,
|
||||
{
|
||||
// create and configure default resource
|
||||
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::factory(
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use actix_service::boxed::{BoxService, BoxServiceFactory};
|
||||
use actix_web::{
|
||||
dev::{RequestHead, ServiceRequest, ServiceResponse},
|
||||
|
@ -25,7 +27,6 @@ use actix_web::{
|
|||
http::header::DispositionType,
|
||||
};
|
||||
use mime_guess::from_ext;
|
||||
use std::path::Path;
|
||||
|
||||
mod chunked;
|
||||
mod directory;
|
||||
|
@ -37,16 +38,15 @@ mod path_buf;
|
|||
mod range;
|
||||
mod service;
|
||||
|
||||
pub use self::chunked::ChunkedReadFile;
|
||||
pub use self::directory::Directory;
|
||||
pub use self::files::Files;
|
||||
pub use self::named::NamedFile;
|
||||
pub use self::range::HttpRange;
|
||||
pub use self::service::FilesService;
|
||||
|
||||
use self::directory::{directory_listing, DirectoryRenderer};
|
||||
use self::error::FilesError;
|
||||
use self::path_buf::PathBufWrap;
|
||||
pub use self::{
|
||||
chunked::ChunkedReadFile, directory::Directory, files::Files, named::NamedFile,
|
||||
range::HttpRange, service::FilesService,
|
||||
};
|
||||
use self::{
|
||||
directory::{directory_listing, DirectoryRenderer},
|
||||
error::FilesError,
|
||||
path_buf::PathBufWrap,
|
||||
};
|
||||
|
||||
type HttpService = BoxService<ServiceRequest, ServiceResponse, Error>;
|
||||
type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>;
|
||||
|
@ -554,9 +554,8 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_static_files_with_spaces() {
|
||||
let srv = test::init_service(
|
||||
App::new().service(Files::new("/", ".").index_file("Cargo.toml")),
|
||||
)
|
||||
let srv =
|
||||
test::init_service(App::new().service(Files::new("/", ".").index_file("Cargo.toml")))
|
||||
.await;
|
||||
let request = TestRequest::get()
|
||||
.uri("/tests/test%20space.binary")
|
||||
|
@ -667,8 +666,7 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_static_files() {
|
||||
let srv =
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing()))
|
||||
.await;
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing())).await;
|
||||
let req = TestRequest::with_uri("/missing").to_request();
|
||||
|
||||
let resp = test::call_service(&srv, req).await;
|
||||
|
@ -681,8 +679,7 @@ mod tests {
|
|||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let srv =
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing()))
|
||||
.await;
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing())).await;
|
||||
let req = TestRequest::with_uri("/tests").to_request();
|
||||
let resp = test::call_service(&srv, req).await;
|
||||
assert_eq!(
|
||||
|
|
|
@ -8,13 +8,13 @@ use std::{
|
|||
use actix_web::{
|
||||
body::{self, BoxBody, SizedStream},
|
||||
dev::{
|
||||
self, AppService, HttpServiceFactory, ResourceDef, Service, ServiceFactory,
|
||||
ServiceRequest, ServiceResponse,
|
||||
self, AppService, HttpServiceFactory, ResourceDef, Service, ServiceFactory, ServiceRequest,
|
||||
ServiceResponse,
|
||||
},
|
||||
http::{
|
||||
header::{
|
||||
self, Charset, ContentDisposition, ContentEncoding, DispositionParam,
|
||||
DispositionType, ExtendedValue, HeaderValue,
|
||||
self, Charset, ContentDisposition, ContentEncoding, DispositionParam, DispositionType,
|
||||
ExtendedValue, HeaderValue,
|
||||
},
|
||||
StatusCode,
|
||||
},
|
||||
|
@ -85,6 +85,7 @@ pub struct NamedFile {
|
|||
|
||||
#[cfg(not(feature = "experimental-io-uring"))]
|
||||
pub(crate) use std::fs::File;
|
||||
|
||||
#[cfg(feature = "experimental-io-uring")]
|
||||
pub(crate) use tokio_uring::fs::File;
|
||||
|
||||
|
@ -139,8 +140,7 @@ impl NamedFile {
|
|||
_ => DispositionType::Attachment,
|
||||
};
|
||||
|
||||
let mut parameters =
|
||||
vec![DispositionParam::Filename(String::from(filename.as_ref()))];
|
||||
let mut parameters = vec![DispositionParam::Filename(String::from(filename.as_ref()))];
|
||||
|
||||
if !filename.is_ascii() {
|
||||
parameters.push(DispositionParam::FilenameExt(ExtendedValue {
|
||||
|
|
|
@ -48,8 +48,8 @@ impl HttpRange {
|
|||
/// `header` is HTTP Range header (e.g. `bytes=bytes=0-9`).
|
||||
/// `size` is full size of response (file).
|
||||
pub fn parse(header: &str, size: u64) -> Result<Vec<HttpRange>, ParseRangeErr> {
|
||||
let ranges = http_range::HttpRange::parse(header, size)
|
||||
.map_err(|err| ParseRangeErr(err.into()))?;
|
||||
let ranges =
|
||||
http_range::HttpRange::parse(header, size).map_err(|err| ParseRangeErr(err.into()))?;
|
||||
|
||||
Ok(ranges
|
||||
.iter()
|
||||
|
|
|
@ -62,11 +62,7 @@ impl FilesService {
|
|||
}
|
||||
}
|
||||
|
||||
fn serve_named_file(
|
||||
&self,
|
||||
req: ServiceRequest,
|
||||
mut named_file: NamedFile,
|
||||
) -> ServiceResponse {
|
||||
fn serve_named_file(&self, req: ServiceRequest, mut named_file: NamedFile) -> ServiceResponse {
|
||||
if let Some(ref mime_override) = self.mime_override {
|
||||
let new_disposition = mime_override(&named_file.content_type.type_());
|
||||
named_file.content_disposition.disposition = new_disposition;
|
||||
|
@ -120,10 +116,8 @@ impl Service<ServiceRequest> for FilesService {
|
|||
));
|
||||
}
|
||||
|
||||
let path_on_disk = match PathBufWrap::parse_path(
|
||||
req.match_info().unprocessed(),
|
||||
this.hidden_files,
|
||||
) {
|
||||
let path_on_disk =
|
||||
match PathBufWrap::parse_path(req.match_info().unprocessed(), this.hidden_files) {
|
||||
Ok(item) => item,
|
||||
Err(err) => return Ok(req.error_response(err)),
|
||||
};
|
||||
|
@ -177,8 +171,7 @@ impl Service<ServiceRequest> for FilesService {
|
|||
match NamedFile::open_async(&path).await {
|
||||
Ok(mut named_file) => {
|
||||
if let Some(ref mime_override) = this.mime_override {
|
||||
let new_disposition =
|
||||
mime_override(&named_file.content_type.type_());
|
||||
let new_disposition = mime_override(&named_file.content_type.type_());
|
||||
named_file.content_disposition.disposition = new_disposition;
|
||||
}
|
||||
named_file.flags = this.file_flags;
|
||||
|
|
|
@ -24,8 +24,7 @@ async fn test_utf8_file_contents() {
|
|||
|
||||
// disable UTF-8 attribute
|
||||
let srv =
|
||||
test::init_service(App::new().service(Files::new("/", "./tests").prefer_utf8(false)))
|
||||
.await;
|
||||
test::init_service(App::new().service(Files::new("/", "./tests").prefer_utf8(false))).await;
|
||||
|
||||
let req = TestRequest::with_uri("/utf8.txt").to_request();
|
||||
let res = test::call_service(&srv, req).await;
|
||||
|
|
|
@ -12,9 +12,7 @@ async fn test_guard_filter() {
|
|||
let srv = test::init_service(
|
||||
App::new()
|
||||
.service(Files::new("/", "./tests/fixtures/guards/first").guard(Host("first.com")))
|
||||
.service(
|
||||
Files::new("/", "./tests/fixtures/guards/second").guard(Host("second.com")),
|
||||
),
|
||||
.service(Files::new("/", "./tests/fixtures/guards/second").guard(Host("second.com"))),
|
||||
)
|
||||
.await;
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ use actix_web::{
|
|||
async fn test_directory_traversal_prevention() {
|
||||
let srv = test::init_service(App::new().service(Files::new("/", "./tests"))).await;
|
||||
|
||||
let req =
|
||||
TestRequest::with_uri("/../../../../../../../../../../../etc/passwd").to_request();
|
||||
let req = TestRequest::with_uri("/../../../../../../../../../../../etc/passwd").to_request();
|
||||
let res = test::call_service(&srv, req).await;
|
||||
assert_eq!(res.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
|
|
|
@ -23,10 +23,7 @@ async fn main() -> io::Result<()> {
|
|||
res.insert_header(("x-head", HeaderValue::from_static("dummy value!")));
|
||||
|
||||
let forty_two = req.conn_data::<u32>().unwrap().to_string();
|
||||
res.insert_header((
|
||||
"x-forty-two",
|
||||
HeaderValue::from_str(&forty_two).unwrap(),
|
||||
));
|
||||
res.insert_header(("x-forty-two", HeaderValue::from_str(&forty_two).unwrap()));
|
||||
|
||||
Ok::<_, Infallible>(res.body("Hello world!"))
|
||||
})
|
||||
|
|
|
@ -77,12 +77,8 @@ impl MessageBody for BoxBody {
|
|||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, Self::Error>>> {
|
||||
match &mut self.0 {
|
||||
BoxBodyInner::None(body) => {
|
||||
Pin::new(body).poll_next(cx).map_err(|err| match err {})
|
||||
}
|
||||
BoxBodyInner::Bytes(body) => {
|
||||
Pin::new(body).poll_next(cx).map_err(|err| match err {})
|
||||
}
|
||||
BoxBodyInner::None(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}),
|
||||
BoxBodyInner::Bytes(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}),
|
||||
BoxBodyInner::Stream(body) => Pin::new(body).poll_next(cx),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ mod size;
|
|||
mod sized_stream;
|
||||
mod utils;
|
||||
|
||||
pub use self::body_stream::BodyStream;
|
||||
pub use self::boxed::BoxBody;
|
||||
pub use self::either::EitherBody;
|
||||
pub use self::message_body::MessageBody;
|
||||
pub(crate) use self::message_body::MessageBodyMapErr;
|
||||
pub use self::none::None;
|
||||
pub use self::size::BodySize;
|
||||
pub use self::sized_stream::SizedStream;
|
||||
pub use self::utils::{to_bytes, to_bytes_limited, BodyLimitExceeded};
|
||||
pub use self::{
|
||||
body_stream::BodyStream,
|
||||
boxed::BoxBody,
|
||||
either::EitherBody,
|
||||
message_body::MessageBody,
|
||||
none::None,
|
||||
size::BodySize,
|
||||
sized_stream::SizedStream,
|
||||
utils::{to_bytes, to_bytes_limited, BodyLimitExceeded},
|
||||
};
|
||||
|
|
|
@ -132,15 +132,15 @@ impl ServiceConfig {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
|
||||
|
||||
use actix_rt::{
|
||||
task::yield_now,
|
||||
time::{sleep, sleep_until},
|
||||
};
|
||||
use memchr::memmem;
|
||||
|
||||
use super::*;
|
||||
use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_date_service_update() {
|
||||
let settings =
|
||||
|
|
|
@ -9,11 +9,9 @@ use std::{
|
|||
|
||||
use actix_rt::task::{spawn_blocking, JoinHandle};
|
||||
use bytes::Bytes;
|
||||
use futures_core::{ready, Stream};
|
||||
|
||||
#[cfg(feature = "compress-gzip")]
|
||||
use flate2::write::{GzDecoder, ZlibDecoder};
|
||||
|
||||
use futures_core::{ready, Stream};
|
||||
#[cfg(feature = "compress-zstd")]
|
||||
use zstd::stream::write::Decoder as ZstdDecoder;
|
||||
|
||||
|
@ -49,9 +47,9 @@ where
|
|||
))),
|
||||
|
||||
#[cfg(feature = "compress-gzip")]
|
||||
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(
|
||||
ZlibDecoder::new(Writer::new()),
|
||||
))),
|
||||
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(ZlibDecoder::new(
|
||||
Writer::new(),
|
||||
)))),
|
||||
|
||||
#[cfg(feature = "compress-gzip")]
|
||||
ContentEncoding::Gzip => Some(ContentDecoder::Gzip(Box::new(GzDecoder::new(
|
||||
|
|
|
@ -11,12 +11,10 @@ use std::{
|
|||
use actix_rt::task::{spawn_blocking, JoinHandle};
|
||||
use bytes::Bytes;
|
||||
use derive_more::Display;
|
||||
use futures_core::ready;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
#[cfg(feature = "compress-gzip")]
|
||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||
|
||||
use futures_core::ready;
|
||||
use pin_project_lite::pin_project;
|
||||
use tracing::trace;
|
||||
#[cfg(feature = "compress-zstd")]
|
||||
use zstd::stream::write::Encoder as ZstdEncoder;
|
||||
|
|
|
@ -7,8 +7,7 @@ use bytes::{Bytes, BytesMut};
|
|||
mod decoder;
|
||||
mod encoder;
|
||||
|
||||
pub use self::decoder::Decoder;
|
||||
pub use self::encoder::Encoder;
|
||||
pub use self::{decoder::Decoder, encoder::Encoder};
|
||||
|
||||
/// Special-purpose writer for streaming (de-)compression.
|
||||
///
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error};
|
||||
|
||||
use derive_more::{Display, Error, From};
|
||||
pub use http::Error as HttpError;
|
||||
use http::{uri::InvalidUri, StatusCode};
|
||||
|
||||
use crate::{body::BoxBody, Response};
|
||||
|
||||
pub use http::Error as HttpError;
|
||||
|
||||
pub struct Error {
|
||||
inner: Box<ErrorInner>,
|
||||
}
|
||||
|
|
|
@ -9,9 +9,7 @@ use super::{
|
|||
decoder::{self, PayloadDecoder, PayloadItem, PayloadType},
|
||||
encoder, Message, MessageType,
|
||||
};
|
||||
use crate::{
|
||||
body::BodySize, error::ParseError, ConnectionType, Request, Response, ServiceConfig,
|
||||
};
|
||||
use crate::{body::BodySize, error::ParseError, ConnectionType, Request, Response, ServiceConfig};
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
@ -94,9 +94,7 @@ pub(crate) trait MessageType: Sized {
|
|||
// SAFETY: httparse already checks header value is only visible ASCII bytes
|
||||
// from_maybe_shared_unchecked contains debug assertions so they are omitted here
|
||||
let value = unsafe {
|
||||
HeaderValue::from_maybe_shared_unchecked(
|
||||
slice.slice(idx.value.0..idx.value.1),
|
||||
)
|
||||
HeaderValue::from_maybe_shared_unchecked(slice.slice(idx.value.0..idx.value.1))
|
||||
};
|
||||
|
||||
match name {
|
||||
|
@ -275,8 +273,7 @@ impl MessageType for Request {
|
|||
let mut msg = Request::new();
|
||||
|
||||
// convert headers
|
||||
let mut length =
|
||||
msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
||||
let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
||||
|
||||
// disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
|
||||
// see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
|
||||
|
@ -356,8 +353,8 @@ impl MessageType for ResponseHead {
|
|||
Version::HTTP_10
|
||||
};
|
||||
|
||||
let status = StatusCode::from_u16(res.code.unwrap())
|
||||
.map_err(|_| ParseError::Status)?;
|
||||
let status =
|
||||
StatusCode::from_u16(res.code.unwrap()).map_err(|_| ParseError::Status)?;
|
||||
HeaderIndex::record(src, res.headers, &mut headers);
|
||||
|
||||
(len, version, status, res.headers.len())
|
||||
|
@ -378,8 +375,7 @@ impl MessageType for ResponseHead {
|
|||
msg.version = ver;
|
||||
|
||||
// convert headers
|
||||
let mut length =
|
||||
msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
||||
let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
||||
|
||||
// Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
|
||||
// Protects against some request smuggling attacks.
|
||||
|
|
|
@ -19,14 +19,6 @@ use tokio::io::{AsyncRead, AsyncWrite};
|
|||
use tokio_util::codec::{Decoder as _, Encoder as _};
|
||||
use tracing::{error, trace};
|
||||
|
||||
use crate::{
|
||||
body::{BodySize, BoxBody, MessageBody},
|
||||
config::ServiceConfig,
|
||||
error::{DispatchError, ParseError, PayloadError},
|
||||
service::HttpFlow,
|
||||
Error, Extensions, OnConnectData, Request, Response, StatusCode,
|
||||
};
|
||||
|
||||
use super::{
|
||||
codec::Codec,
|
||||
decoder::MAX_BUFFER_SIZE,
|
||||
|
@ -34,6 +26,13 @@ use super::{
|
|||
timer::TimerState,
|
||||
Message, MessageType,
|
||||
};
|
||||
use crate::{
|
||||
body::{BodySize, BoxBody, MessageBody},
|
||||
config::ServiceConfig,
|
||||
error::{DispatchError, ParseError, PayloadError},
|
||||
service::HttpFlow,
|
||||
Error, Extensions, OnConnectData, Request, Response, StatusCode,
|
||||
};
|
||||
|
||||
const LW_BUFFER_SIZE: usize = 1024;
|
||||
const HW_BUFFER_SIZE: usize = 1024 * 8;
|
||||
|
@ -213,9 +212,7 @@ where
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::None => write!(f, "State::None"),
|
||||
Self::ExpectCall { .. } => {
|
||||
f.debug_struct("State::ExpectCall").finish_non_exhaustive()
|
||||
}
|
||||
Self::ExpectCall { .. } => f.debug_struct("State::ExpectCall").finish_non_exhaustive(),
|
||||
Self::ServiceCall { .. } => {
|
||||
f.debug_struct("State::ServiceCall").finish_non_exhaustive()
|
||||
}
|
||||
|
@ -276,9 +273,7 @@ where
|
|||
|
||||
head_timer: TimerState::new(config.client_request_deadline().is_some()),
|
||||
ka_timer: TimerState::new(config.keep_alive().enabled()),
|
||||
shutdown_timer: TimerState::new(
|
||||
config.client_disconnect_deadline().is_some(),
|
||||
),
|
||||
shutdown_timer: TimerState::new(config.client_disconnect_deadline().is_some()),
|
||||
|
||||
io: Some(io),
|
||||
read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
|
||||
|
@ -456,9 +451,7 @@ where
|
|||
}
|
||||
|
||||
// return with upgrade request and poll it exclusively
|
||||
Some(DispatcherMessage::Upgrade(req)) => {
|
||||
return Ok(PollResponse::Upgrade(req))
|
||||
}
|
||||
Some(DispatcherMessage::Upgrade(req)) => return Ok(PollResponse::Upgrade(req)),
|
||||
|
||||
// all messages are dealt with
|
||||
None => {
|
||||
|
@ -675,9 +668,7 @@ where
|
|||
}
|
||||
|
||||
_ => {
|
||||
unreachable!(
|
||||
"State must be set to ServiceCall or ExceptCall in handle_request"
|
||||
)
|
||||
unreachable!("State must be set to ServiceCall or ExceptCall in handle_request")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -686,10 +677,7 @@ where
|
|||
/// Process one incoming request.
|
||||
///
|
||||
/// Returns true if any meaningful work was done.
|
||||
fn poll_request(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
fn poll_request(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<bool, DispatchError> {
|
||||
let pipeline_queue_full = self.messages.len() >= MAX_PIPELINED_MESSAGES;
|
||||
let can_not_read = !self.can_read(cx);
|
||||
|
||||
|
@ -859,10 +847,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_ka_timer(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<(), DispatchError> {
|
||||
fn poll_ka_timer(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> {
|
||||
let this = self.as_mut().project();
|
||||
if let TimerState::Active { timer } = this.ka_timer {
|
||||
debug_assert!(
|
||||
|
@ -927,10 +912,7 @@ where
|
|||
}
|
||||
|
||||
/// Poll head, keep-alive, and disconnect timer.
|
||||
fn poll_timers(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<(), DispatchError> {
|
||||
fn poll_timers(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> {
|
||||
self.as_mut().poll_head_timer(cx)?;
|
||||
self.as_mut().poll_ka_timer(cx)?;
|
||||
self.as_mut().poll_shutdown_timer(cx)?;
|
||||
|
@ -944,10 +926,7 @@ where
|
|||
/// - `std::io::ErrorKind::ConnectionReset` after partial read;
|
||||
/// - all data read done.
|
||||
#[inline(always)] // TODO: bench this inline
|
||||
fn read_available(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
fn read_available(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<bool, DispatchError> {
|
||||
let this = self.project();
|
||||
|
||||
if this.flags.contains(Flags::READ_DISCONNECT) {
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
use std::{future::Future, str, task::Poll, time::Duration};
|
||||
|
||||
use actix_rt::{pin, time::sleep};
|
||||
use actix_service::fn_service;
|
||||
use actix_utils::future::{ready, Ready};
|
||||
use bytes::Bytes;
|
||||
use futures_util::future::lazy;
|
||||
|
||||
use actix_codec::Framed;
|
||||
use actix_service::Service;
|
||||
use bytes::{Buf, BytesMut};
|
||||
use actix_rt::{pin, time::sleep};
|
||||
use actix_service::{fn_service, Service};
|
||||
use actix_utils::future::{ready, Ready};
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use futures_util::future::lazy;
|
||||
|
||||
use super::dispatcher::{Dispatcher, DispatcherState, DispatcherStateProj, Flags};
|
||||
use crate::{
|
||||
|
@ -43,8 +40,8 @@ fn status_service(
|
|||
fn_service(move |_req: Request| ready(Ok::<_, Error>(Response::new(status))))
|
||||
}
|
||||
|
||||
fn echo_path_service(
|
||||
) -> impl Service<Request, Response = Response<impl MessageBody>, Error = Error> {
|
||||
fn echo_path_service() -> impl Service<Request, Response = Response<impl MessageBody>, Error = Error>
|
||||
{
|
||||
fn_service(|req: Request| {
|
||||
let path = req.path().as_bytes();
|
||||
ready(Ok::<_, Error>(
|
||||
|
@ -53,8 +50,8 @@ fn echo_path_service(
|
|||
})
|
||||
}
|
||||
|
||||
fn drop_payload_service(
|
||||
) -> impl Service<Request, Response = Response<&'static str>, Error = Error> {
|
||||
fn drop_payload_service() -> impl Service<Request, Response = Response<&'static str>, Error = Error>
|
||||
{
|
||||
fn_service(|mut req: Request| async move {
|
||||
let _ = req.take_payload();
|
||||
Ok::<_, Error>(Response::with_body(StatusCode::OK, "payload dropped"))
|
||||
|
|
|
@ -17,14 +17,16 @@ mod timer;
|
|||
mod upgrade;
|
||||
mod utils;
|
||||
|
||||
pub use self::client::{ClientCodec, ClientPayloadCodec};
|
||||
pub use self::codec::Codec;
|
||||
pub use self::dispatcher::Dispatcher;
|
||||
pub use self::expect::ExpectHandler;
|
||||
pub use self::payload::Payload;
|
||||
pub use self::service::{H1Service, H1ServiceHandler};
|
||||
pub use self::upgrade::UpgradeHandler;
|
||||
pub use self::utils::SendResponse;
|
||||
pub use self::{
|
||||
client::{ClientCodec, ClientPayloadCodec},
|
||||
codec::Codec,
|
||||
dispatcher::Dispatcher,
|
||||
expect::ExpectHandler,
|
||||
payload::Payload,
|
||||
service::{H1Service, H1ServiceHandler},
|
||||
upgrade::UpgradeHandler,
|
||||
utils::SendResponse,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Codec message
|
||||
|
|
|
@ -15,6 +15,7 @@ use actix_utils::future::ready;
|
|||
use futures_core::future::LocalBoxFuture;
|
||||
use tracing::error;
|
||||
|
||||
use super::{codec::Codec, dispatcher::Dispatcher, ExpectHandler, UpgradeHandler};
|
||||
use crate::{
|
||||
body::{BoxBody, MessageBody},
|
||||
config::ServiceConfig,
|
||||
|
@ -23,8 +24,6 @@ use crate::{
|
|||
ConnectCallback, OnConnectData, Request, Response,
|
||||
};
|
||||
|
||||
use super::{codec::Codec, dispatcher::Dispatcher, ExpectHandler, UpgradeHandler};
|
||||
|
||||
/// `ServiceFactory` implementation for HTTP1 transport
|
||||
pub struct H1Service<T, S, B, X = ExpectHandler, U = UpgradeHandler> {
|
||||
srv: S,
|
||||
|
@ -82,13 +81,8 @@ where
|
|||
/// Create simple tcp stream service
|
||||
pub fn tcp(
|
||||
self,
|
||||
) -> impl ServiceFactory<
|
||||
TcpStream,
|
||||
Config = (),
|
||||
Response = (),
|
||||
Error = DispatchError,
|
||||
InitError = (),
|
||||
> {
|
||||
) -> impl ServiceFactory<TcpStream, Config = (), Response = (), Error = DispatchError, InitError = ()>
|
||||
{
|
||||
fn_service(|io: TcpStream| {
|
||||
let peer_addr = io.peer_addr().ok();
|
||||
ready(Ok((io, peer_addr)))
|
||||
|
@ -99,8 +93,6 @@ where
|
|||
|
||||
#[cfg(feature = "openssl")]
|
||||
mod openssl {
|
||||
use super::*;
|
||||
|
||||
use actix_tls::accept::{
|
||||
openssl::{
|
||||
reexports::{Error as SslError, SslAcceptor},
|
||||
|
@ -109,6 +101,8 @@ mod openssl {
|
|||
TlsError,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<S, B, X, U> H1Service<TlsStream<TcpStream>, S, B, X, U>
|
||||
where
|
||||
S: ServiceFactory<Request, Config = ()>,
|
||||
|
|
|
@ -23,8 +23,7 @@ use crate::{
|
|||
mod dispatcher;
|
||||
mod service;
|
||||
|
||||
pub use self::dispatcher::Dispatcher;
|
||||
pub use self::service::H2Service;
|
||||
pub use self::{dispatcher::Dispatcher, service::H2Service};
|
||||
|
||||
/// HTTP/2 peer stream.
|
||||
pub struct Payload {
|
||||
|
@ -58,10 +57,7 @@ impl Stream for Payload {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handshake_with_timeout<T>(
|
||||
io: T,
|
||||
config: &ServiceConfig,
|
||||
) -> HandshakeWithTimeout<T>
|
||||
pub(crate) fn handshake_with_timeout<T>(io: T, config: &ServiceConfig) -> HandshakeWithTimeout<T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ use actix_utils::future::ready;
|
|||
use futures_core::{future::LocalBoxFuture, ready};
|
||||
use tracing::{error, trace};
|
||||
|
||||
use super::{dispatcher::Dispatcher, handshake_with_timeout, HandshakeWithTimeout};
|
||||
use crate::{
|
||||
body::{BoxBody, MessageBody},
|
||||
config::ServiceConfig,
|
||||
|
@ -24,8 +25,6 @@ use crate::{
|
|||
ConnectCallback, OnConnectData, Request, Response,
|
||||
};
|
||||
|
||||
use super::{dispatcher::Dispatcher, handshake_with_timeout, HandshakeWithTimeout};
|
||||
|
||||
/// `ServiceFactory` implementation for HTTP/2 transport
|
||||
pub struct H2Service<T, S, B> {
|
||||
srv: S,
|
||||
|
|
|
@ -1120,9 +1120,7 @@ mod tests {
|
|||
assert!(vals.next().is_none());
|
||||
}
|
||||
|
||||
fn owned_pair<'a>(
|
||||
(name, val): (&'a HeaderName, &'a HeaderValue),
|
||||
) -> (HeaderName, HeaderValue) {
|
||||
fn owned_pair<'a>((name, val): (&'a HeaderName, &'a HeaderValue)) -> (HeaderName, HeaderValue) {
|
||||
(name.clone(), val.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,33 +3,30 @@
|
|||
// declaring new header consts will yield this error
|
||||
#![allow(clippy::declare_interior_mutable_const)]
|
||||
|
||||
use percent_encoding::{AsciiSet, CONTROLS};
|
||||
|
||||
// re-export from http except header map related items
|
||||
pub use ::http::header::{
|
||||
HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue, ToStrError,
|
||||
};
|
||||
|
||||
// re-export const header names, list is explicit so that any updates to `common` module do not
|
||||
// conflict with this set
|
||||
pub use ::http::header::{
|
||||
ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, ACCEPT_LANGUAGE, ACCEPT_RANGES,
|
||||
ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS,
|
||||
ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS,
|
||||
ACCESS_CONTROL_MAX_AGE, ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, AGE,
|
||||
ALLOW, ALT_SVC, AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION,
|
||||
CONTENT_ENCODING, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_RANGE,
|
||||
CONTENT_SECURITY_POLICY, CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, COOKIE, DATE,
|
||||
DNT, ETAG, EXPECT, EXPIRES, FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE,
|
||||
IF_NONE_MATCH, IF_RANGE, IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, LOCATION, MAX_FORWARDS,
|
||||
ORIGIN, PRAGMA, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, PUBLIC_KEY_PINS,
|
||||
PUBLIC_KEY_PINS_REPORT_ONLY, RANGE, REFERER, REFERRER_POLICY, REFRESH, RETRY_AFTER,
|
||||
SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_EXTENSIONS, SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL,
|
||||
SEC_WEBSOCKET_VERSION, SERVER, SET_COOKIE, STRICT_TRANSPORT_SECURITY, TE, TRAILER,
|
||||
TRANSFER_ENCODING, UPGRADE, UPGRADE_INSECURE_REQUESTS, USER_AGENT, VARY, VIA, WARNING,
|
||||
WWW_AUTHENTICATE, X_CONTENT_TYPE_OPTIONS, X_DNS_PREFETCH_CONTROL, X_FRAME_OPTIONS,
|
||||
X_XSS_PROTECTION,
|
||||
ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,
|
||||
ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS, ACCESS_CONTROL_MAX_AGE,
|
||||
ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, AGE, ALLOW, ALT_SVC,
|
||||
AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION, CONTENT_ENCODING,
|
||||
CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_RANGE, CONTENT_SECURITY_POLICY,
|
||||
CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, COOKIE, DATE, DNT, ETAG, EXPECT, EXPIRES,
|
||||
FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE, IF_NONE_MATCH, IF_RANGE,
|
||||
IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, LOCATION, MAX_FORWARDS, ORIGIN, PRAGMA,
|
||||
PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, PUBLIC_KEY_PINS, PUBLIC_KEY_PINS_REPORT_ONLY, RANGE,
|
||||
REFERER, REFERRER_POLICY, REFRESH, RETRY_AFTER, SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_EXTENSIONS,
|
||||
SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL, SEC_WEBSOCKET_VERSION, SERVER, SET_COOKIE,
|
||||
STRICT_TRANSPORT_SECURITY, TE, TRAILER, TRANSFER_ENCODING, UPGRADE, UPGRADE_INSECURE_REQUESTS,
|
||||
USER_AGENT, VARY, VIA, WARNING, WWW_AUTHENTICATE, X_CONTENT_TYPE_OPTIONS,
|
||||
X_DNS_PREFETCH_CONTROL, X_FRAME_OPTIONS, X_XSS_PROTECTION,
|
||||
};
|
||||
use percent_encoding::{AsciiSet, CONTROLS};
|
||||
|
||||
use crate::{error::ParseError, HttpMessage};
|
||||
|
||||
|
@ -43,23 +40,22 @@ mod utils;
|
|||
|
||||
pub use self::{
|
||||
as_name::AsHeaderName,
|
||||
// re-export list is explicit so that any updates to `http` do not conflict with this set
|
||||
common::{
|
||||
CACHE_STATUS, CDN_CACHE_CONTROL, CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY,
|
||||
CROSS_ORIGIN_RESOURCE_POLICY, PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST,
|
||||
X_FORWARDED_PROTO,
|
||||
},
|
||||
into_pair::TryIntoHeaderPair,
|
||||
into_value::TryIntoHeaderValue,
|
||||
map::HeaderMap,
|
||||
shared::{
|
||||
parse_extended_value, q, Charset, ContentEncoding, ExtendedValue, HttpDate,
|
||||
LanguageTag, Quality, QualityItem,
|
||||
parse_extended_value, q, Charset, ContentEncoding, ExtendedValue, HttpDate, LanguageTag,
|
||||
Quality, QualityItem,
|
||||
},
|
||||
utils::{fmt_comma_delimited, from_comma_delimited, from_one_raw_str, http_percent_encode},
|
||||
};
|
||||
|
||||
// re-export list is explicit so that any updates to `http` do not conflict with this set
|
||||
pub use self::common::{
|
||||
CACHE_STATUS, CDN_CACHE_CONTROL, CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY,
|
||||
CROSS_ORIGIN_RESOURCE_POLICY, PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST,
|
||||
X_FORWARDED_PROTO,
|
||||
};
|
||||
|
||||
/// An interface for types that already represent a valid header.
|
||||
pub trait Header: TryIntoHeaderValue {
|
||||
/// Returns the name of the header field.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Originally taken from `hyper::header::shared`.
|
||||
|
||||
pub use language_tags::LanguageTag;
|
||||
|
||||
mod charset;
|
||||
mod content_encoding;
|
||||
mod extended;
|
||||
|
@ -7,10 +9,11 @@ mod http_date;
|
|||
mod quality;
|
||||
mod quality_item;
|
||||
|
||||
pub use self::charset::Charset;
|
||||
pub use self::content_encoding::ContentEncoding;
|
||||
pub use self::extended::{parse_extended_value, ExtendedValue};
|
||||
pub use self::http_date::HttpDate;
|
||||
pub use self::quality::{q, Quality};
|
||||
pub use self::quality_item::QualityItem;
|
||||
pub use language_tags::LanguageTag;
|
||||
pub use self::{
|
||||
charset::Charset,
|
||||
content_encoding::ContentEncoding,
|
||||
extended::{parse_extended_value, ExtendedValue},
|
||||
http_date::HttpDate,
|
||||
quality::{q, Quality},
|
||||
quality_item::QualityItem,
|
||||
};
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::{cmp, fmt, str};
|
||||
|
||||
use crate::error::ParseError;
|
||||
|
||||
use super::Quality;
|
||||
use crate::error::ParseError;
|
||||
|
||||
/// Represents an item with a quality value as defined
|
||||
/// in [RFC 7231 §5.3.1](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.1).
|
||||
|
|
|
@ -61,9 +61,7 @@ pub trait HttpMessage: Sized {
|
|||
fn encoding(&self) -> Result<&'static Encoding, ContentTypeError> {
|
||||
if let Some(mime_type) = self.mime_type()? {
|
||||
if let Some(charset) = mime_type.get_param("charset") {
|
||||
if let Some(enc) =
|
||||
Encoding::for_label_no_replacement(charset.as_str().as_bytes())
|
||||
{
|
||||
if let Some(enc) = Encoding::for_label_no_replacement(charset.as_str().as_bytes()) {
|
||||
Ok(enc)
|
||||
} else {
|
||||
Err(ContentTypeError::UnknownEncoding)
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
pub use ::http::{uri, uri::Uri};
|
||||
pub use ::http::{Method, StatusCode, Version};
|
||||
pub use ::http::{uri, uri::Uri, Method, StatusCode, Version};
|
||||
|
||||
pub mod body;
|
||||
mod builder;
|
||||
|
@ -57,22 +56,24 @@ pub mod test;
|
|||
#[cfg(feature = "ws")]
|
||||
pub mod ws;
|
||||
|
||||
pub use self::builder::HttpServiceBuilder;
|
||||
pub use self::config::ServiceConfig;
|
||||
pub use self::error::Error;
|
||||
pub use self::extensions::Extensions;
|
||||
pub use self::header::ContentEncoding;
|
||||
pub use self::http_message::HttpMessage;
|
||||
pub use self::keep_alive::KeepAlive;
|
||||
pub use self::message::ConnectionType;
|
||||
pub use self::message::Message;
|
||||
#[allow(deprecated)]
|
||||
pub use self::payload::{BoxedPayloadStream, Payload, PayloadStream};
|
||||
pub use self::requests::{Request, RequestHead, RequestHeadType};
|
||||
pub use self::responses::{Response, ResponseBuilder, ResponseHead};
|
||||
pub use self::service::HttpService;
|
||||
pub use self::payload::PayloadStream;
|
||||
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||
pub use self::service::TlsAcceptorConfig;
|
||||
pub use self::{
|
||||
builder::HttpServiceBuilder,
|
||||
config::ServiceConfig,
|
||||
error::Error,
|
||||
extensions::Extensions,
|
||||
header::ContentEncoding,
|
||||
http_message::HttpMessage,
|
||||
keep_alive::KeepAlive,
|
||||
message::{ConnectionType, Message},
|
||||
payload::{BoxedPayloadStream, Payload},
|
||||
requests::{Request, RequestHead, RequestHeadType},
|
||||
responses::{Response, ResponseBuilder, ResponseHead},
|
||||
service::HttpService,
|
||||
};
|
||||
|
||||
/// A major HTTP protocol version.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -3,5 +3,7 @@
|
|||
mod head;
|
||||
mod request;
|
||||
|
||||
pub use self::head::{RequestHead, RequestHeadType};
|
||||
pub use self::request::Request;
|
||||
pub use self::{
|
||||
head::{RequestHead, RequestHeadType},
|
||||
request::Request,
|
||||
};
|
||||
|
|
|
@ -10,8 +10,7 @@ use std::{
|
|||
use http::{header, Method, Uri, Version};
|
||||
|
||||
use crate::{
|
||||
header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload,
|
||||
RequestHead,
|
||||
header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload, RequestHead,
|
||||
};
|
||||
|
||||
/// An HTTP request.
|
||||
|
|
|
@ -5,7 +5,5 @@ mod head;
|
|||
#[allow(clippy::module_inception)]
|
||||
mod response;
|
||||
|
||||
pub use self::builder::ResponseBuilder;
|
||||
pub(crate) use self::head::BoxedResponseHead;
|
||||
pub use self::head::ResponseHead;
|
||||
pub use self::response::Response;
|
||||
pub use self::{builder::ResponseBuilder, head::ResponseHead, response::Response};
|
||||
|
|
|
@ -200,13 +200,8 @@ where
|
|||
/// The resulting service only supports HTTP/1.x.
|
||||
pub fn tcp(
|
||||
self,
|
||||
) -> impl ServiceFactory<
|
||||
TcpStream,
|
||||
Config = (),
|
||||
Response = (),
|
||||
Error = DispatchError,
|
||||
InitError = (),
|
||||
> {
|
||||
) -> impl ServiceFactory<TcpStream, Config = (), Response = (), Error = DispatchError, InitError = ()>
|
||||
{
|
||||
fn_service(|io: TcpStream| async {
|
||||
let peer_addr = io.peer_addr().ok();
|
||||
Ok((io, Protocol::Http1, peer_addr))
|
||||
|
@ -219,13 +214,8 @@ where
|
|||
#[cfg(feature = "http2")]
|
||||
pub fn tcp_auto_h2c(
|
||||
self,
|
||||
) -> impl ServiceFactory<
|
||||
TcpStream,
|
||||
Config = (),
|
||||
Response = (),
|
||||
Error = DispatchError,
|
||||
InitError = (),
|
||||
> {
|
||||
) -> impl ServiceFactory<TcpStream, Config = (), Response = (), Error = DispatchError, InitError = ()>
|
||||
{
|
||||
fn_service(move |io: TcpStream| async move {
|
||||
// subset of HTTP/2 preface defined by RFC 9113 §3.4
|
||||
// this subset was chosen to maximize likelihood that peeking only once will allow us to
|
||||
|
@ -563,10 +553,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn _poll_ready(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), Response<BoxBody>>> {
|
||||
pub(super) fn _poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Response<BoxBody>>> {
|
||||
ready!(self.flow.expect.poll_ready(cx).map_err(Into::into))?;
|
||||
|
||||
ready!(self.flow.service.poll_ready(cx).map_err(Into::into))?;
|
||||
|
@ -625,10 +612,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
(io, proto, peer_addr): (T, Protocol, Option<net::SocketAddr>),
|
||||
) -> Self::Future {
|
||||
fn call(&self, (io, proto, peer_addr): (T, Protocol, Option<net::SocketAddr>)) -> Self::Future {
|
||||
let conn_data = OnConnectData::from_io(&io, self.on_connect_ext.as_deref());
|
||||
|
||||
match proto {
|
||||
|
|
|
@ -70,15 +70,14 @@ mod inner {
|
|||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_codec::Framed;
|
||||
use actix_service::{IntoService, Service};
|
||||
use futures_core::stream::Stream;
|
||||
use local_channel::mpsc;
|
||||
use pin_project_lite::pin_project;
|
||||
use tracing::debug;
|
||||
|
||||
use actix_codec::Framed;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{body::BoxBody, Response};
|
||||
|
||||
|
@ -413,9 +412,7 @@ mod inner {
|
|||
}
|
||||
State::Error(_) => {
|
||||
// flush write buffer
|
||||
if !this.framed.is_write_buf_empty()
|
||||
&& this.framed.flush(cx).is_pending()
|
||||
{
|
||||
if !this.framed.is_write_buf_empty() && this.framed.flush(cx).is_pending() {
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(Err(this.state.take_error()))
|
||||
|
|
|
@ -221,9 +221,10 @@ impl Parser {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
|
||||
struct F {
|
||||
finished: bool,
|
||||
opcode: OpCode,
|
||||
|
|
|
@ -8,8 +8,7 @@ use std::io;
|
|||
use derive_more::{Display, Error, From};
|
||||
use http::{header, Method, StatusCode};
|
||||
|
||||
use crate::body::BoxBody;
|
||||
use crate::{header::HeaderValue, RequestHead, Response, ResponseBuilder};
|
||||
use crate::{body::BoxBody, header::HeaderValue, RequestHead, Response, ResponseBuilder};
|
||||
|
||||
mod codec;
|
||||
mod dispatcher;
|
||||
|
@ -17,10 +16,12 @@ mod frame;
|
|||
mod mask;
|
||||
mod proto;
|
||||
|
||||
pub use self::codec::{Codec, Frame, Item, Message};
|
||||
pub use self::dispatcher::Dispatcher;
|
||||
pub use self::frame::Parser;
|
||||
pub use self::proto::{hash_key, CloseCode, CloseReason, OpCode};
|
||||
pub use self::{
|
||||
codec::{Codec, Frame, Item, Message},
|
||||
dispatcher::Dispatcher,
|
||||
frame::Parser,
|
||||
proto::{hash_key, CloseCode, CloseReason, OpCode},
|
||||
};
|
||||
|
||||
/// WebSocket protocol errors.
|
||||
#[derive(Debug, Display, Error, From)]
|
||||
|
@ -219,10 +220,8 @@ pub fn handshake_response(req: &RequestHead) -> ResponseBuilder {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{header, Method};
|
||||
|
||||
use super::*;
|
||||
use crate::test::TestRequest;
|
||||
use crate::{header, test::TestRequest, Method};
|
||||
|
||||
#[test]
|
||||
fn test_handshake() {
|
||||
|
|
|
@ -321,8 +321,7 @@ async fn h2_body_length() {
|
|||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| async {
|
||||
let body =
|
||||
once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) });
|
||||
let body = once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) });
|
||||
|
||||
Ok::<_, Infallible>(
|
||||
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
|
||||
|
|
|
@ -90,10 +90,8 @@ pub fn get_negotiated_alpn_protocol(
|
|||
|
||||
config.alpn_protocols.push(client_alpn_protocol.to_vec());
|
||||
|
||||
let mut sess = rustls::ClientConnection::new(
|
||||
Arc::new(config),
|
||||
ServerName::try_from("localhost").unwrap(),
|
||||
)
|
||||
let mut sess =
|
||||
rustls::ClientConnection::new(Arc::new(config), ServerName::try_from("localhost").unwrap())
|
||||
.unwrap();
|
||||
|
||||
let mut sock = StdTcpStream::connect(addr).unwrap();
|
||||
|
|
|
@ -166,8 +166,7 @@ async fn chunked_payload() {
|
|||
|
||||
for chunk_size in chunk_sizes.iter() {
|
||||
let mut bytes = Vec::new();
|
||||
let random_bytes: Vec<u8> =
|
||||
(0..*chunk_size).map(|_| rand::random::<u8>()).collect();
|
||||
let random_bytes: Vec<u8> = (0..*chunk_size).map(|_| rand::random::<u8>()).collect();
|
||||
|
||||
bytes.extend(format!("{:X}\r\n", chunk_size).as_bytes());
|
||||
bytes.extend(&random_bytes[..]);
|
||||
|
@ -352,8 +351,7 @@ async fn http10_keepalive() {
|
|||
.await;
|
||||
|
||||
let mut stream = net::TcpStream::connect(srv.addr()).unwrap();
|
||||
let _ =
|
||||
stream.write_all(b"GET /test/tests/test HTTP/1.0\r\nconnection: keep-alive\r\n\r\n");
|
||||
let _ = stream.write_all(b"GET /test/tests/test HTTP/1.0\r\nconnection: keep-alive\r\n\r\n");
|
||||
let mut data = vec![0; 1024];
|
||||
let _ = stream.read(&mut data);
|
||||
assert_eq!(&data[..17], b"HTTP/1.0 200 OK\r\n");
|
||||
|
@ -795,8 +793,9 @@ async fn not_modified_spec_h1() {
|
|||
.map_into_boxed_body(),
|
||||
|
||||
// with no content-length
|
||||
"/body" => Response::with_body(StatusCode::NOT_MODIFIED, "1234")
|
||||
.map_into_boxed_body(),
|
||||
"/body" => {
|
||||
Response::with_body(StatusCode::NOT_MODIFIED, "1234").map_into_boxed_body()
|
||||
}
|
||||
|
||||
// with manual content-length header and specific None body
|
||||
"/cl-none" => {
|
||||
|
|
|
@ -27,11 +27,7 @@ pub struct Bytes {
|
|||
impl<'t> FieldReader<'t> for Bytes {
|
||||
type Future = LocalBoxFuture<'t, Result<Self, MultipartError>>;
|
||||
|
||||
fn read_field(
|
||||
_: &'t HttpRequest,
|
||||
mut field: Field,
|
||||
limits: &'t mut Limits,
|
||||
) -> Self::Future {
|
||||
fn read_field(_: &'t HttpRequest, mut field: Field, limits: &'t mut Limits) -> Self::Future {
|
||||
Box::pin(async move {
|
||||
let mut buf = BytesMut::with_capacity(131_072);
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@ use derive_more::{Deref, DerefMut, Display, Error};
|
|||
use futures_core::future::LocalBoxFuture;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use super::FieldErrorHandler;
|
||||
use crate::{
|
||||
form::{bytes::Bytes, FieldReader, Limits},
|
||||
Field, MultipartError,
|
||||
};
|
||||
|
||||
use super::FieldErrorHandler;
|
||||
|
||||
/// Deserialize from JSON.
|
||||
#[derive(Debug, Deref, DerefMut)]
|
||||
pub struct Json<T: DeserializeOwned>(pub T);
|
||||
|
|
|
@ -429,8 +429,7 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_options() {
|
||||
let srv =
|
||||
actix_test::start(|| App::new().route("/", web::post().to(test_options_route)));
|
||||
let srv = actix_test::start(|| App::new().route("/", web::post().to(test_options_route)));
|
||||
|
||||
let mut form = multipart::Form::default();
|
||||
form.add_text("field1", "value");
|
||||
|
@ -481,9 +480,7 @@ mod tests {
|
|||
field3: Text<String>,
|
||||
}
|
||||
|
||||
async fn test_field_renaming_route(
|
||||
form: MultipartForm<TestFieldRenaming>,
|
||||
) -> impl Responder {
|
||||
async fn test_field_renaming_route(form: MultipartForm<TestFieldRenaming>) -> impl Responder {
|
||||
assert_eq!(&*form.field1, "renamed");
|
||||
assert_eq!(&*form.field2, "field1");
|
||||
assert_eq!(&*form.field3, "field3");
|
||||
|
@ -492,9 +489,8 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_field_renaming() {
|
||||
let srv = actix_test::start(|| {
|
||||
App::new().route("/", web::post().to(test_field_renaming_route))
|
||||
});
|
||||
let srv =
|
||||
actix_test::start(|| App::new().route("/", web::post().to(test_field_renaming_route)));
|
||||
|
||||
let mut form = multipart::Form::default();
|
||||
form.add_text("renamed", "renamed");
|
||||
|
@ -623,9 +619,7 @@ mod tests {
|
|||
HttpResponse::Ok().finish()
|
||||
}
|
||||
|
||||
async fn test_upload_limits_file(
|
||||
form: MultipartForm<TestFileUploadLimits>,
|
||||
) -> impl Responder {
|
||||
async fn test_upload_limits_file(form: MultipartForm<TestFileUploadLimits>) -> impl Responder {
|
||||
assert!(form.field.size > 0);
|
||||
HttpResponse::Ok().finish()
|
||||
}
|
||||
|
|
|
@ -39,21 +39,18 @@ pub struct TempFile {
|
|||
impl<'t> FieldReader<'t> for TempFile {
|
||||
type Future = LocalBoxFuture<'t, Result<Self, MultipartError>>;
|
||||
|
||||
fn read_field(
|
||||
req: &'t HttpRequest,
|
||||
mut field: Field,
|
||||
limits: &'t mut Limits,
|
||||
) -> Self::Future {
|
||||
fn read_field(req: &'t HttpRequest, mut field: Field, limits: &'t mut Limits) -> Self::Future {
|
||||
Box::pin(async move {
|
||||
let config = TempFileConfig::from_req(req);
|
||||
let field_name = field.name().to_owned();
|
||||
let mut size = 0;
|
||||
|
||||
let file = config.create_tempfile().map_err(|err| {
|
||||
config.map_error(req, &field_name, TempFileError::FileIo(err))
|
||||
})?;
|
||||
let file = config
|
||||
.create_tempfile()
|
||||
.map_err(|err| config.map_error(req, &field_name, TempFileError::FileIo(err)))?;
|
||||
|
||||
let mut file_async = tokio::fs::File::from_std(file.reopen().map_err(|err| {
|
||||
let mut file_async =
|
||||
tokio::fs::File::from_std(file.reopen().map_err(|err| {
|
||||
config.map_error(req, &field_name, TempFileError::FileIo(err))
|
||||
})?);
|
||||
|
||||
|
@ -65,9 +62,10 @@ impl<'t> FieldReader<'t> for TempFile {
|
|||
})?;
|
||||
}
|
||||
|
||||
file_async.flush().await.map_err(|err| {
|
||||
config.map_error(req, &field_name, TempFileError::FileIo(err))
|
||||
})?;
|
||||
file_async
|
||||
.flush()
|
||||
.await
|
||||
.map_err(|err| config.map_error(req, &field_name, TempFileError::FileIo(err)))?;
|
||||
|
||||
Ok(TempFile {
|
||||
file,
|
||||
|
@ -131,12 +129,7 @@ impl TempFileConfig {
|
|||
.unwrap_or(&DEFAULT_CONFIG)
|
||||
}
|
||||
|
||||
fn map_error(
|
||||
&self,
|
||||
req: &HttpRequest,
|
||||
field_name: &str,
|
||||
err: TempFileError,
|
||||
) -> MultipartError {
|
||||
fn map_error(&self, req: &HttpRequest, field_name: &str, err: TempFileError) -> MultipartError {
|
||||
let source = if let Some(ref err_handler) = self.err_handler {
|
||||
(err_handler)(err, req)
|
||||
} else {
|
||||
|
|
|
@ -17,5 +17,7 @@ mod server;
|
|||
|
||||
pub mod form;
|
||||
|
||||
pub use self::error::MultipartError;
|
||||
pub use self::server::{Field, Multipart};
|
||||
pub use self::{
|
||||
error::MultipartError,
|
||||
server::{Field, Multipart},
|
||||
};
|
||||
|
|
|
@ -161,8 +161,8 @@ impl InnerMultipart {
|
|||
for h in hdrs {
|
||||
let name =
|
||||
HeaderName::try_from(h.name).map_err(|_| ParseError::Header)?;
|
||||
let value = HeaderValue::try_from(h.value)
|
||||
.map_err(|_| ParseError::Header)?;
|
||||
let value =
|
||||
HeaderValue::try_from(h.value).map_err(|_| ParseError::Header)?;
|
||||
headers.append(name, value);
|
||||
}
|
||||
|
||||
|
@ -222,8 +222,7 @@ impl InnerMultipart {
|
|||
if chunk.len() < boundary.len() {
|
||||
continue;
|
||||
}
|
||||
if &chunk[..2] == b"--" && &chunk[2..chunk.len() - 2] == boundary.as_bytes()
|
||||
{
|
||||
if &chunk[..2] == b"--" && &chunk[2..chunk.len() - 2] == boundary.as_bytes() {
|
||||
break;
|
||||
} else {
|
||||
if chunk.len() < boundary.len() + 2 {
|
||||
|
@ -268,9 +267,7 @@ impl InnerMultipart {
|
|||
match field.borrow_mut().poll(safety) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Some(Ok(_))) => continue,
|
||||
Poll::Ready(Some(Err(err))) => {
|
||||
return Poll::Ready(Some(Err(err)))
|
||||
}
|
||||
Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))),
|
||||
Poll::Ready(None) => true,
|
||||
}
|
||||
}
|
||||
|
@ -289,8 +286,7 @@ impl InnerMultipart {
|
|||
match self.state {
|
||||
// read until first boundary
|
||||
InnerState::FirstBoundary => {
|
||||
match InnerMultipart::skip_until_boundary(&mut payload, &self.boundary)?
|
||||
{
|
||||
match InnerMultipart::skip_until_boundary(&mut payload, &self.boundary)? {
|
||||
Some(eof) => {
|
||||
if eof {
|
||||
self.state = InnerState::Eof;
|
||||
|
@ -667,9 +663,7 @@ impl InnerField {
|
|||
Ok(None) => Poll::Pending,
|
||||
Ok(Some(line)) => {
|
||||
if line.as_ref() != b"\r\n" {
|
||||
log::warn!(
|
||||
"multipart field did not read all the data or it is malformed"
|
||||
);
|
||||
log::warn!("multipart field did not read all the data or it is malformed");
|
||||
}
|
||||
Poll::Ready(None)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#![allow(clippy::uninlined_format_args)]
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
fn compare_quoters(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("Compare Quoters");
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use serde::de::{self, Deserializer, Error as DeError, Visitor};
|
||||
use serde::forward_to_deserialize_any;
|
||||
use serde::{
|
||||
de::{self, Deserializer, Error as DeError, Visitor},
|
||||
forward_to_deserialize_any,
|
||||
};
|
||||
|
||||
use crate::path::{Path, PathIter};
|
||||
use crate::{Quoter, ResourcePath};
|
||||
use crate::{
|
||||
path::{Path, PathIter},
|
||||
Quoter, ResourcePath,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
static FULL_QUOTER: Quoter = Quoter::new(b"", b"");
|
||||
|
@ -486,11 +490,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant {
|
|||
Err(de::value::Error::custom("not supported"))
|
||||
}
|
||||
|
||||
fn struct_variant<V>(
|
||||
self,
|
||||
_: &'static [&'static str],
|
||||
_: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
fn struct_variant<V>(self, _: &'static [&'static str], _: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
|
@ -503,9 +503,7 @@ mod tests {
|
|||
use serde::{de, Deserialize};
|
||||
|
||||
use super::*;
|
||||
use crate::path::Path;
|
||||
use crate::router::Router;
|
||||
use crate::ResourceDef;
|
||||
use crate::{path::Path, router::Router, ResourceDef};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MyStruct {
|
||||
|
@ -572,13 +570,11 @@ mod tests {
|
|||
assert_eq!(s.key, "name");
|
||||
assert_eq!(s.value, 32);
|
||||
|
||||
let s: (String, u8) =
|
||||
de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
|
||||
let s: (String, u8) = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
|
||||
assert_eq!(s.0, "name");
|
||||
assert_eq!(s.1, 32);
|
||||
|
||||
let res: Vec<String> =
|
||||
de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
|
||||
let res: Vec<String> = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
|
||||
assert_eq!(res[0], "name".to_owned());
|
||||
assert_eq!(res[1], "32".to_owned());
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@ mod router;
|
|||
#[cfg(feature = "http")]
|
||||
mod url;
|
||||
|
||||
pub use self::de::PathDeserializer;
|
||||
pub use self::path::Path;
|
||||
pub use self::pattern::{IntoPatterns, Patterns};
|
||||
pub use self::quoter::Quoter;
|
||||
pub use self::resource::ResourceDef;
|
||||
pub use self::resource_path::{Resource, ResourcePath};
|
||||
pub use self::router::{ResourceId, Router, RouterBuilder};
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
pub use self::url::Url;
|
||||
pub use self::{
|
||||
de::PathDeserializer,
|
||||
path::Path,
|
||||
pattern::{IntoPatterns, Patterns},
|
||||
quoter::Quoter,
|
||||
resource::ResourceDef,
|
||||
resource_path::{Resource, ResourcePath},
|
||||
router::{ResourceId, Router, RouterBuilder},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::ops::{DerefMut, Index};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
ops::{DerefMut, Index},
|
||||
};
|
||||
|
||||
use serde::de;
|
||||
|
||||
|
|
|
@ -1741,9 +1741,7 @@ mod tests {
|
|||
ResourceDef::new("/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}");
|
||||
|
||||
// panics
|
||||
ResourceDef::new(
|
||||
"/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}/{q}",
|
||||
);
|
||||
ResourceDef::new("/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}/{q}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -117,11 +117,7 @@ where
|
|||
U: Default,
|
||||
{
|
||||
/// Registers resource for specified path.
|
||||
pub fn path(
|
||||
&mut self,
|
||||
path: impl IntoPatterns,
|
||||
val: T,
|
||||
) -> (&mut ResourceDef, &mut T, &mut U) {
|
||||
pub fn path(&mut self, path: impl IntoPatterns, val: T) -> (&mut ResourceDef, &mut T, &mut U) {
|
||||
self.push(ResourceDef::new(path), val, U::default())
|
||||
}
|
||||
|
||||
|
@ -142,8 +138,10 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::path::Path;
|
||||
use crate::router::{ResourceId, Router};
|
||||
use crate::{
|
||||
path::Path,
|
||||
router::{ResourceId, Router},
|
||||
};
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use crate::ResourcePath;
|
||||
|
||||
use crate::Quoter;
|
||||
use crate::{Quoter, ResourcePath};
|
||||
|
||||
thread_local! {
|
||||
static DEFAULT_QUOTER: Quoter = Quoter::new(b"", b"%/+");
|
||||
|
|
|
@ -45,8 +45,8 @@ use actix_http::{header::HeaderMap, ws, HttpService, Method, Request, Response};
|
|||
pub use actix_http_test::unused_addr;
|
||||
use actix_service::{map_config, IntoServiceFactory, ServiceFactory, ServiceFactoryExt as _};
|
||||
pub use actix_web::test::{
|
||||
call_and_read_body, call_and_read_body_json, call_service, init_service, ok_service,
|
||||
read_body, read_body_json, status_service, TestRequest,
|
||||
call_and_read_body, call_and_read_body_json, call_service, init_service, ok_service, read_body,
|
||||
read_body_json, status_service, TestRequest,
|
||||
};
|
||||
use actix_web::{
|
||||
body::MessageBody,
|
||||
|
@ -159,11 +159,8 @@ where
|
|||
let srv = match srv_cfg.stream {
|
||||
StreamType::Tcp => match srv_cfg.tp {
|
||||
HttpVer::Http1 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -175,11 +172,8 @@ where
|
|||
.tcp()
|
||||
}),
|
||||
HttpVer::Http2 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -191,11 +185,8 @@ where
|
|||
.tcp()
|
||||
}),
|
||||
HttpVer::Both => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -210,11 +201,8 @@ where
|
|||
#[cfg(feature = "openssl")]
|
||||
StreamType::Openssl(acceptor) => match cfg.tp {
|
||||
HttpVer::Http1 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -226,11 +214,8 @@ where
|
|||
.openssl(acceptor.clone())
|
||||
}),
|
||||
HttpVer::Http2 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -242,11 +227,8 @@ where
|
|||
.openssl(acceptor.clone())
|
||||
}),
|
||||
HttpVer::Both => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -261,11 +243,8 @@ where
|
|||
#[cfg(feature = "rustls")]
|
||||
StreamType::Rustls(config) => match cfg.tp {
|
||||
HttpVer::Http1 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -277,11 +256,8 @@ where
|
|||
.rustls(config.clone())
|
||||
}),
|
||||
HttpVer::Http2 => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
@ -293,11 +269,8 @@ where
|
|||
.rustls(config.clone())
|
||||
}),
|
||||
HttpVer::Both => builder.listen("test", tcp, move || {
|
||||
let app_cfg = AppConfig::__priv_test_new(
|
||||
false,
|
||||
local_addr.to_string(),
|
||||
local_addr,
|
||||
);
|
||||
let app_cfg =
|
||||
AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr);
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix::dev::{AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, ToEnvelope};
|
||||
use actix::fut::ActorFuture;
|
||||
use actix::{
|
||||
dev::{AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, ToEnvelope},
|
||||
fut::ActorFuture,
|
||||
Actor, ActorContext, ActorState, Addr, AsyncContext, Handler, Message, SpawnHandle,
|
||||
};
|
||||
use actix_web::error::Error;
|
||||
|
@ -247,9 +249,11 @@ mod tests {
|
|||
use std::time::Duration;
|
||||
|
||||
use actix::Actor;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::test::{call_service, init_service, read_body, TestRequest};
|
||||
use actix_web::{web, App, HttpResponse};
|
||||
use actix_web::{
|
||||
http::StatusCode,
|
||||
test::{call_service, init_service, read_body, TestRequest},
|
||||
web, App, HttpResponse,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
|
|
|
@ -66,17 +66,14 @@ use std::{
|
|||
|
||||
use actix::{
|
||||
dev::{
|
||||
AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, StreamHandler,
|
||||
ToEnvelope,
|
||||
AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, StreamHandler, ToEnvelope,
|
||||
},
|
||||
fut::ActorFuture,
|
||||
Actor, ActorContext, ActorState, Addr, AsyncContext, Handler, Message as ActixMessage,
|
||||
SpawnHandle,
|
||||
};
|
||||
use actix_http::ws::{hash_key, Codec};
|
||||
pub use actix_http::ws::{
|
||||
CloseCode, CloseReason, Frame, HandshakeError, Message, ProtocolError,
|
||||
};
|
||||
pub use actix_http::ws::{CloseCode, CloseReason, Frame, HandshakeError, Message, ProtocolError};
|
||||
use actix_web::{
|
||||
error::{Error, PayloadError},
|
||||
http::{
|
||||
|
@ -426,8 +423,8 @@ pub fn handshake_with_protocols(
|
|||
};
|
||||
|
||||
// check requested protocols
|
||||
let protocol =
|
||||
req.headers()
|
||||
let protocol = req
|
||||
.headers()
|
||||
.get(&header::SEC_WEBSOCKET_PROTOCOL)
|
||||
.and_then(|req_protocols| {
|
||||
let req_protocols = req_protocols.to_str().ok()?;
|
||||
|
|
|
@ -153,37 +153,37 @@ pub fn routes(_: TokenStream, input: TokenStream) -> TokenStream {
|
|||
|
||||
macro_rules! method_macro {
|
||||
($variant:ident, $method:ident) => {
|
||||
#[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")]
|
||||
///
|
||||
/// # Syntax
|
||||
/// ```plain
|
||||
#[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)]
|
||||
/// ```
|
||||
///
|
||||
/// # Attributes
|
||||
/// - `"path"`: Raw literal string with path for which to register handler.
|
||||
/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function
|
||||
/// name of handler is used.
|
||||
/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
|
||||
/// - `wrap = "Middleware"`: Registers a resource middleware.
|
||||
///
|
||||
/// # Notes
|
||||
/// Function name can be specified as any expression that is going to be accessible to the
|
||||
/// generate code, e.g `my_guard` or `my_module::my_guard`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use actix_web::HttpResponse;
|
||||
#[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")]
|
||||
#[doc = concat!("#[", stringify!($method), r#"("/")]"#)]
|
||||
/// async fn example() -> HttpResponse {
|
||||
/// HttpResponse::Ok().finish()
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
#[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")]
|
||||
///
|
||||
/// # Syntax
|
||||
/// ```plain
|
||||
#[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)]
|
||||
/// ```
|
||||
///
|
||||
/// # Attributes
|
||||
/// - `"path"`: Raw literal string with path for which to register handler.
|
||||
/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the
|
||||
/// function name of handler is used.
|
||||
/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
|
||||
/// - `wrap = "Middleware"`: Registers a resource middleware.
|
||||
///
|
||||
/// # Notes
|
||||
/// Function name can be specified as any expression that is going to be accessible to the
|
||||
/// generate code, e.g `my_guard` or `my_module::my_guard`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use actix_web::HttpResponse;
|
||||
#[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")]
|
||||
#[doc = concat!("#[", stringify!($method), r#"("/")]"#)]
|
||||
/// async fn example() -> HttpResponse {
|
||||
/// HttpResponse::Ok().finish()
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
route::with_method(Some(route::MethodType::$variant), args, input)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -488,8 +488,7 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
|||
|
||||
ast.attrs = others.into_iter().map(Result::unwrap_err).collect();
|
||||
|
||||
let methods =
|
||||
match methods
|
||||
let methods = match methods
|
||||
.into_iter()
|
||||
.map(Result::unwrap)
|
||||
.map(|(method, attr)| {
|
||||
|
@ -503,13 +502,15 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
|||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
{
|
||||
Ok(methods) if methods.is_empty() => return input_and_compile_error(
|
||||
Ok(methods) if methods.is_empty() => {
|
||||
return input_and_compile_error(
|
||||
input,
|
||||
syn::Error::new(
|
||||
Span::call_site(),
|
||||
"The #[routes] macro requires at least one `#[<method>(..)]` attribute.",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
Ok(methods) => methods,
|
||||
Err(err) => return input_and_compile_error(input, err),
|
||||
};
|
||||
|
|
|
@ -99,8 +99,7 @@ fn responder(c: &mut Criterion) {
|
|||
let req = TestRequest::default().to_http_request();
|
||||
c.bench_function("responder", move |b| {
|
||||
b.iter_custom(|_| {
|
||||
let responders =
|
||||
(0..100_000).map(|_| StringResponder(String::from("Hello World!!")));
|
||||
let responders = (0..100_000).map(|_| StringResponder(String::from("Hello World!!")));
|
||||
|
||||
let start = Instant::now();
|
||||
let _res = rt.block_on(async {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use actix_service::Service;
|
||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||
use actix_web::{web, App, Error, HttpResponse};
|
||||
use criterion::{criterion_main, Criterion};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use actix_web::test::{init_service, ok_service, TestRequest};
|
||||
use actix_service::Service;
|
||||
use actix_web::{
|
||||
dev::{ServiceRequest, ServiceResponse},
|
||||
test::{init_service, ok_service, TestRequest},
|
||||
web, App, Error, HttpResponse,
|
||||
};
|
||||
use criterion::{criterion_main, Criterion};
|
||||
|
||||
/// Criterion Benchmark for async Service
|
||||
/// Should be used from within criterion group:
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
use std::{any::Any, io, net::SocketAddr};
|
||||
|
||||
use actix_web::{
|
||||
dev::Extensions, rt::net::TcpStream, web, App, HttpRequest, HttpResponse, HttpServer,
|
||||
Responder,
|
||||
dev::Extensions, rt::net::TcpStream, web, App, HttpRequest, HttpResponse, HttpServer, Responder,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -24,9 +23,7 @@ async fn route_whoami(req: HttpRequest) -> impl Responder {
|
|||
Some(info) => HttpResponse::Ok().body(format!(
|
||||
"Here is some info about your connection:\n\n{info:#?}",
|
||||
)),
|
||||
None => {
|
||||
HttpResponse::InternalServerError().body("Missing expected request extension data")
|
||||
}
|
||||
None => HttpResponse::InternalServerError().body("Missing expected request extension data"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,12 +264,8 @@ where
|
|||
pub fn default_service<F, U>(mut self, svc: F) -> Self
|
||||
where
|
||||
F: IntoServiceFactory<U, ServiceRequest>,
|
||||
U: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Config = (),
|
||||
Response = ServiceResponse,
|
||||
Error = Error,
|
||||
> + 'static,
|
||||
U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
|
||||
+ 'static,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
let svc = svc
|
||||
|
|
|
@ -348,13 +348,17 @@ impl ServiceFactory<ServiceRequest> for AppEntry {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
use actix_service::Service;
|
||||
|
||||
use crate::test::{init_service, TestRequest};
|
||||
use crate::{web, App, HttpResponse};
|
||||
use crate::{
|
||||
test::{init_service, TestRequest},
|
||||
web, App, HttpResponse,
|
||||
};
|
||||
|
||||
struct DropData(Arc<AtomicBool>);
|
||||
|
||||
|
|
|
@ -232,12 +232,8 @@ impl ServiceConfig {
|
|||
pub fn default_service<F, U>(&mut self, f: F) -> &mut Self
|
||||
where
|
||||
F: IntoServiceFactory<U, ServiceRequest>,
|
||||
U: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Config = (),
|
||||
Response = ServiceResponse,
|
||||
Error = Error,
|
||||
> + 'static,
|
||||
U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
|
||||
+ 'static,
|
||||
U::InitError: std::fmt::Debug,
|
||||
{
|
||||
let svc = f
|
||||
|
@ -308,9 +304,11 @@ mod tests {
|
|||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
use crate::http::{Method, StatusCode};
|
||||
use crate::test::{assert_body_eq, call_service, init_service, read_body, TestRequest};
|
||||
use crate::{web, App, HttpRequest, HttpResponse};
|
||||
use crate::{
|
||||
http::{Method, StatusCode},
|
||||
test::{assert_body_eq, call_service, init_service, read_body, TestRequest},
|
||||
web, App, HttpRequest, HttpResponse,
|
||||
};
|
||||
|
||||
// allow deprecated `ServiceConfig::data`
|
||||
#[allow(deprecated)]
|
||||
|
|
|
@ -186,12 +186,14 @@ mod tests {
|
|||
#[allow(deprecated)]
|
||||
#[actix_rt::test]
|
||||
async fn test_data_extractor() {
|
||||
let srv = init_service(App::new().data("TEST".to_string()).service(
|
||||
web::resource("/").to(|data: web::Data<String>| {
|
||||
let srv = init_service(
|
||||
App::new()
|
||||
.data("TEST".to_string())
|
||||
.service(web::resource("/").to(|data: web::Data<String>| {
|
||||
assert_eq!(data.to_lowercase(), "test");
|
||||
HttpResponse::Ok()
|
||||
}),
|
||||
))
|
||||
})),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::default().to_request();
|
||||
|
@ -286,15 +288,16 @@ mod tests {
|
|||
#[allow(deprecated)]
|
||||
#[actix_rt::test]
|
||||
async fn test_override_data() {
|
||||
let srv =
|
||||
init_service(App::new().data(1usize).service(
|
||||
web::resource("/").data(10usize).route(web::get().to(
|
||||
let srv = init_service(
|
||||
App::new()
|
||||
.data(1usize)
|
||||
.service(web::resource("/").data(10usize).route(web::get().to(
|
||||
|data: web::Data<usize>| {
|
||||
assert_eq!(**data, 10);
|
||||
HttpResponse::Ok()
|
||||
},
|
||||
)),
|
||||
))
|
||||
))),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::default().to_request();
|
||||
|
|
|
@ -7,26 +7,25 @@
|
|||
//! - [`ConnectionInfo`]: Connection information
|
||||
//! - [`PeerAddr`]: Connection information
|
||||
|
||||
#[cfg(feature = "__compress")]
|
||||
pub use actix_http::encoding::Decoder as Decompress;
|
||||
pub use actix_http::{Extensions, Payload, RequestHead, Response, ResponseHead};
|
||||
use actix_router::Patterns;
|
||||
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
||||
pub use actix_server::{Server, ServerHandle};
|
||||
pub use actix_service::{
|
||||
always_ready, fn_factory, fn_service, forward_ready, Service, ServiceFactory, Transform,
|
||||
};
|
||||
|
||||
#[cfg(feature = "__compress")]
|
||||
pub use actix_http::encoding::Decoder as Decompress;
|
||||
|
||||
pub use crate::config::{AppConfig, AppService};
|
||||
#[doc(hidden)]
|
||||
pub use crate::handler::Handler;
|
||||
pub use crate::info::{ConnectionInfo, PeerAddr};
|
||||
pub use crate::rmap::ResourceMap;
|
||||
pub use crate::service::{HttpServiceFactory, ServiceRequest, ServiceResponse, WebService};
|
||||
|
||||
pub use crate::types::{JsonBody, Readlines, UrlEncoded};
|
||||
|
||||
use actix_router::Patterns;
|
||||
pub use crate::{
|
||||
config::{AppConfig, AppService},
|
||||
info::{ConnectionInfo, PeerAddr},
|
||||
rmap::ResourceMap,
|
||||
service::{HttpServiceFactory, ServiceRequest, ServiceResponse, WebService},
|
||||
types::{JsonBody, Readlines, UrlEncoded},
|
||||
};
|
||||
|
||||
pub(crate) fn ensure_leading_slash(mut patterns: Patterns) -> Patterns {
|
||||
match &mut patterns {
|
||||
|
|
|
@ -42,8 +42,7 @@ macro_rules! downcast_dyn {
|
|||
/// Downcasts generic body to a specific type.
|
||||
#[allow(dead_code)]
|
||||
pub fn downcast_ref<T: $name + 'static>(&self) -> Option<&T> {
|
||||
if self.__private_get_type_id__(PrivateHelper(())).0
|
||||
== std::any::TypeId::of::<T>()
|
||||
if self.__private_get_type_id__(PrivateHelper(())).0 == std::any::TypeId::of::<T>()
|
||||
{
|
||||
// SAFETY: external crates cannot override the default
|
||||
// implementation of `__private_get_type_id__`, since
|
||||
|
@ -59,8 +58,7 @@ macro_rules! downcast_dyn {
|
|||
/// Downcasts a generic body to a mutable specific type.
|
||||
#[allow(dead_code)]
|
||||
pub fn downcast_mut<T: $name + 'static>(&mut self) -> Option<&mut T> {
|
||||
if self.__private_get_type_id__(PrivateHelper(())).0
|
||||
== std::any::TypeId::of::<T>()
|
||||
if self.__private_get_type_id__(PrivateHelper(())).0 == std::any::TypeId::of::<T>()
|
||||
{
|
||||
// SAFETY: external crates cannot override the default
|
||||
// implementation of `__private_get_type_id__`, since
|
||||
|
@ -76,7 +74,8 @@ macro_rules! downcast_dyn {
|
|||
};
|
||||
}
|
||||
|
||||
pub(crate) use {downcast_dyn, downcast_get_type_id};
|
||||
pub(crate) use downcast_dyn;
|
||||
pub(crate) use downcast_get_type_id;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -5,14 +5,10 @@
|
|||
// expanded manually.
|
||||
//
|
||||
// See <https://github.com/rust-lang/rust/issues/83375>
|
||||
pub use actix_http::error::{
|
||||
ContentTypeError, DispatchError, HttpError, ParseError, PayloadError,
|
||||
};
|
||||
|
||||
pub use actix_http::error::{ContentTypeError, DispatchError, HttpError, ParseError, PayloadError};
|
||||
use derive_more::{Display, Error, From};
|
||||
use serde_json::error::Error as JsonError;
|
||||
use serde_urlencoded::de::Error as FormDeError;
|
||||
use serde_urlencoded::ser::Error as FormError;
|
||||
use serde_urlencoded::{de::Error as FormDeError, ser::Error as FormError};
|
||||
use url::ParseError as UrlParseError;
|
||||
|
||||
use crate::http::StatusCode;
|
||||
|
@ -23,10 +19,8 @@ mod internal;
|
|||
mod macros;
|
||||
mod response_error;
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use self::internal::*;
|
||||
pub use self::response_error::ResponseError;
|
||||
pub(crate) use macros::{downcast_dyn, downcast_get_type_id};
|
||||
pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id};
|
||||
pub use self::{error::Error, internal::*, response_error::ResponseError};
|
||||
|
||||
/// A convenience [`Result`](std::result::Result) for Actix Web operations.
|
||||
///
|
||||
|
|
|
@ -429,8 +429,10 @@ mod tests {
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::*;
|
||||
use crate::test::TestRequest;
|
||||
use crate::types::{Form, FormConfig};
|
||||
use crate::{
|
||||
test::TestRequest,
|
||||
types::{Form, FormConfig},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
struct Info {
|
||||
|
|
|
@ -61,8 +61,10 @@ use crate::{http::header::Header, service::ServiceRequest, HttpMessage as _};
|
|||
mod acceptable;
|
||||
mod host;
|
||||
|
||||
pub use self::acceptable::Acceptable;
|
||||
pub use self::host::{Host, HostGuard};
|
||||
pub use self::{
|
||||
acceptable::Acceptable,
|
||||
host::{Host, HostGuard},
|
||||
};
|
||||
|
||||
/// Provides access to request parts that are useful during routing.
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -94,10 +94,7 @@ impl AcceptEncoding {
|
|||
/// includes the server's supported encodings in the body plus a [`Vary`] header.
|
||||
///
|
||||
/// [`Vary`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
|
||||
pub fn negotiate<'a>(
|
||||
&self,
|
||||
supported: impl Iterator<Item = &'a Encoding>,
|
||||
) -> Option<Encoding> {
|
||||
pub fn negotiate<'a>(&self, supported: impl Iterator<Item = &'a Encoding>) -> Option<Encoding> {
|
||||
// 1. If no Accept-Encoding field is in the request, any content-coding is considered
|
||||
// acceptable by the user agent.
|
||||
|
||||
|
@ -375,9 +372,7 @@ mod tests {
|
|||
Some(Encoding::deflate())
|
||||
);
|
||||
assert_eq!(
|
||||
test.negotiate(
|
||||
[Encoding::gzip(), Encoding::deflate(), Encoding::identity()].iter()
|
||||
),
|
||||
test.negotiate([Encoding::gzip(), Encoding::deflate(), Encoding::identity()].iter()),
|
||||
Some(Encoding::gzip())
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
|
@ -592,9 +592,8 @@ mod tests {
|
|||
fn test_from_raw_basic() {
|
||||
assert!(ContentDisposition::from_raw(&HeaderValue::from_static("")).is_err());
|
||||
|
||||
let a = HeaderValue::from_static(
|
||||
"form-data; dummy=3; name=upload; filename=\"sample.png\"",
|
||||
);
|
||||
let a =
|
||||
HeaderValue::from_static("form-data; dummy=3; name=upload; filename=\"sample.png\"");
|
||||
let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap();
|
||||
let b = ContentDisposition {
|
||||
disposition: DispositionType::FormData,
|
||||
|
@ -648,8 +647,8 @@ mod tests {
|
|||
charset: Charset::Ext(String::from("UTF-8")),
|
||||
language_tag: None,
|
||||
value: vec![
|
||||
0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r',
|
||||
b'a', b't', b'e', b's',
|
||||
0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', b'a',
|
||||
b't', b'e', b's',
|
||||
],
|
||||
})],
|
||||
};
|
||||
|
@ -665,8 +664,8 @@ mod tests {
|
|||
charset: Charset::Ext(String::from("UTF-8")),
|
||||
language_tag: None,
|
||||
value: vec![
|
||||
0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r',
|
||||
b'a', b't', b'e', b's',
|
||||
0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', b'a',
|
||||
b't', b'e', b's',
|
||||
],
|
||||
})],
|
||||
};
|
||||
|
@ -742,8 +741,8 @@ mod tests {
|
|||
};
|
||||
assert_eq!(a, b);
|
||||
|
||||
let a = ContentDisposition::from_raw(&HeaderValue::from_static("unknown-disp-param"))
|
||||
.unwrap();
|
||||
let a =
|
||||
ContentDisposition::from_raw(&HeaderValue::from_static("unknown-disp-param")).unwrap();
|
||||
let b = ContentDisposition {
|
||||
disposition: DispositionType::Ext(String::from("unknown-disp-param")),
|
||||
parameters: vec![],
|
||||
|
@ -782,8 +781,7 @@ mod tests {
|
|||
Mainstream browsers like Firefox (gecko) and Chrome use UTF-8 directly as above.
|
||||
(And now, only UTF-8 is handled by this implementation.)
|
||||
*/
|
||||
let a =
|
||||
HeaderValue::from_str("form-data; name=upload; filename=\"文件.webp\"").unwrap();
|
||||
let a = HeaderValue::from_str("form-data; name=upload; filename=\"文件.webp\"").unwrap();
|
||||
let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap();
|
||||
let b = ContentDisposition {
|
||||
disposition: DispositionType::FormData,
|
||||
|
@ -803,9 +801,7 @@ mod tests {
|
|||
disposition: DispositionType::FormData,
|
||||
parameters: vec![
|
||||
DispositionParam::Name(String::from("upload")),
|
||||
DispositionParam::Filename(String::from(
|
||||
"余固知謇謇之為患兮,忍而不能舍也.pptx",
|
||||
)),
|
||||
DispositionParam::Filename(String::from("余固知謇謇之為患兮,忍而不能舍也.pptx")),
|
||||
],
|
||||
};
|
||||
assert_eq!(a, b);
|
||||
|
@ -870,8 +866,7 @@ mod tests {
|
|||
};
|
||||
assert_eq!(a, b);
|
||||
|
||||
let a =
|
||||
HeaderValue::from_static("form-data; name=photo; filename=\"%74%65%73%74.png\"");
|
||||
let a = HeaderValue::from_static("form-data; name=photo; filename=\"%74%65%73%74.png\"");
|
||||
let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap();
|
||||
let b = ContentDisposition {
|
||||
disposition: DispositionType::FormData,
|
||||
|
|
|
@ -127,8 +127,7 @@ impl FromStr for ContentRangeSpec {
|
|||
fn from_str(s: &str) -> Result<Self, ParseError> {
|
||||
let res = match split_in_two(s, ' ') {
|
||||
Some(("bytes", resp)) => {
|
||||
let (range, instance_length) =
|
||||
split_in_two(resp, '/').ok_or(ParseError::Header)?;
|
||||
let (range, instance_length) = split_in_two(resp, '/').ok_or(ParseError::Header)?;
|
||||
|
||||
let instance_length = if instance_length == "*" {
|
||||
None
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::CONTENT_TYPE;
|
||||
use mime::Mime;
|
||||
|
||||
use super::CONTENT_TYPE;
|
||||
|
||||
crate::http::header::common_header! {
|
||||
/// `Content-Type` header, defined
|
||||
/// in [RFC 7231 §3.1.1.5](https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.5)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::{HttpDate, DATE};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use super::{HttpDate, DATE};
|
||||
|
||||
crate::http::header::common_header! {
|
||||
/// `Date` header, defined
|
||||
/// in [RFC 7231 §7.1.1.2](https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.2)
|
||||
|
|
|
@ -152,9 +152,7 @@ impl FromStr for EntityTag {
|
|||
return Err(crate::error::ParseError::Header);
|
||||
}
|
||||
// The etag is weak if its first char is not a DQUOTE.
|
||||
if slice.len() >= 2
|
||||
&& slice.starts_with('"')
|
||||
&& check_slice_validity(&slice[1..length - 1])
|
||||
if slice.len() >= 2 && slice.starts_with('"') && check_slice_validity(&slice[1..length - 1])
|
||||
{
|
||||
// No need to check if the last char is a DQUOTE,
|
||||
// we already did that above.
|
||||
|
|
|
@ -4,9 +4,7 @@ use super::{
|
|||
from_one_raw_str, EntityTag, Header, HeaderName, HeaderValue, HttpDate, InvalidHeaderValue,
|
||||
TryIntoHeaderValue, Writer,
|
||||
};
|
||||
use crate::error::ParseError;
|
||||
use crate::http::header;
|
||||
use crate::HttpMessage;
|
||||
use crate::{error::ParseError, http::header, HttpMessage};
|
||||
|
||||
/// `If-Range` header, defined
|
||||
/// in [RFC 7233 §3.2](https://datatracker.ietf.org/doc/html/rfc7233#section-3.2)
|
||||
|
|
|
@ -314,7 +314,7 @@ macro_rules! common_header {
|
|||
};
|
||||
}
|
||||
|
||||
pub(crate) use {common_header, common_header_test_module};
|
||||
|
||||
pub(crate) use common_header;
|
||||
#[cfg(test)]
|
||||
pub(crate) use common_header_test;
|
||||
pub(crate) use common_header_test_module;
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
|
||||
// re-export from actix-http
|
||||
// - header name / value types
|
||||
// - relevant traits for converting to header name / value
|
||||
|
@ -16,6 +14,7 @@ use bytes::{Bytes, BytesMut};
|
|||
// - the few typed headers from actix-http
|
||||
// - header parsing utils
|
||||
pub use actix_http::header::*;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
|
||||
mod accept;
|
||||
mod accept_charset;
|
||||
|
@ -43,32 +42,33 @@ mod preference;
|
|||
mod range;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) use macros::common_header_test;
|
||||
pub(crate) use macros::{common_header, common_header_test_module};
|
||||
|
||||
pub use self::accept::Accept;
|
||||
pub use self::accept_charset::AcceptCharset;
|
||||
pub use self::accept_encoding::AcceptEncoding;
|
||||
pub use self::accept_language::AcceptLanguage;
|
||||
pub use self::allow::Allow;
|
||||
pub use self::cache_control::{CacheControl, CacheDirective};
|
||||
pub use self::content_disposition::{ContentDisposition, DispositionParam, DispositionType};
|
||||
pub use self::content_language::ContentLanguage;
|
||||
pub use self::content_range::{ContentRange, ContentRangeSpec};
|
||||
pub use self::content_type::ContentType;
|
||||
pub use self::date::Date;
|
||||
pub use self::encoding::Encoding;
|
||||
pub use self::entity::EntityTag;
|
||||
pub use self::etag::ETag;
|
||||
pub use self::expires::Expires;
|
||||
pub use self::if_match::IfMatch;
|
||||
pub use self::if_modified_since::IfModifiedSince;
|
||||
pub use self::if_none_match::IfNoneMatch;
|
||||
pub use self::if_range::IfRange;
|
||||
pub use self::if_unmodified_since::IfUnmodifiedSince;
|
||||
pub use self::last_modified::LastModified;
|
||||
pub use self::preference::Preference;
|
||||
pub use self::range::{ByteRangeSpec, Range};
|
||||
pub(crate) use self::macros::common_header_test;
|
||||
pub(crate) use self::macros::{common_header, common_header_test_module};
|
||||
pub use self::{
|
||||
accept::Accept,
|
||||
accept_charset::AcceptCharset,
|
||||
accept_encoding::AcceptEncoding,
|
||||
accept_language::AcceptLanguage,
|
||||
allow::Allow,
|
||||
cache_control::{CacheControl, CacheDirective},
|
||||
content_disposition::{ContentDisposition, DispositionParam, DispositionType},
|
||||
content_language::ContentLanguage,
|
||||
content_range::{ContentRange, ContentRangeSpec},
|
||||
content_type::ContentType,
|
||||
date::Date,
|
||||
encoding::Encoding,
|
||||
entity::EntityTag,
|
||||
etag::ETag,
|
||||
expires::Expires,
|
||||
if_match::IfMatch,
|
||||
if_modified_since::IfModifiedSince,
|
||||
if_none_match::IfNoneMatch,
|
||||
if_range::IfRange,
|
||||
if_unmodified_since::IfUnmodifiedSince,
|
||||
last_modified::LastModified,
|
||||
preference::Preference,
|
||||
range::{ByteRangeSpec, Range},
|
||||
};
|
||||
|
||||
/// Format writer ([`fmt::Write`]) for a [`BytesMut`].
|
||||
#[derive(Debug, Default)]
|
||||
|
|
|
@ -74,6 +74,11 @@
|
|||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
pub use actix_http::{body, HttpMessage};
|
||||
#[cfg(feature = "cookies")]
|
||||
#[doc(inline)]
|
||||
pub use cookie;
|
||||
|
||||
mod app;
|
||||
mod app_service;
|
||||
mod config;
|
||||
|
@ -102,25 +107,21 @@ pub mod test;
|
|||
pub(crate) mod types;
|
||||
pub mod web;
|
||||
|
||||
pub use crate::app::App;
|
||||
#[doc(inline)]
|
||||
pub use crate::error::Result;
|
||||
pub use crate::error::{Error, ResponseError};
|
||||
pub use crate::extract::FromRequest;
|
||||
pub use crate::handler::Handler;
|
||||
pub use crate::request::HttpRequest;
|
||||
pub use crate::resource::Resource;
|
||||
pub use crate::response::{CustomizeResponder, HttpResponse, HttpResponseBuilder, Responder};
|
||||
pub use crate::route::Route;
|
||||
pub use crate::scope::Scope;
|
||||
pub use crate::server::HttpServer;
|
||||
pub use crate::types::Either;
|
||||
|
||||
pub use actix_http::{body, HttpMessage};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
#[doc(inline)]
|
||||
pub use cookie;
|
||||
pub use crate::{
|
||||
app::App,
|
||||
error::{Error, ResponseError},
|
||||
extract::FromRequest,
|
||||
handler::Handler,
|
||||
request::HttpRequest,
|
||||
resource::Resource,
|
||||
response::{CustomizeResponder, HttpResponse, HttpResponseBuilder, Responder},
|
||||
route::Route,
|
||||
scope::Scope,
|
||||
server::HttpServer,
|
||||
types::Either,
|
||||
};
|
||||
|
||||
macro_rules! codegen_reexport {
|
||||
($name:ident) => {
|
||||
|
|
|
@ -146,10 +146,9 @@ mod tests {
|
|||
// easier to code when cookies feature is disabled
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::*;
|
||||
|
||||
use actix_service::IntoService;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
dev::ServiceRequest,
|
||||
http::StatusCode,
|
||||
|
@ -207,9 +206,9 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_condition_scope_middleware() {
|
||||
let srv = |req: ServiceRequest| {
|
||||
Box::pin(async move {
|
||||
Ok(req.into_response(HttpResponse::InternalServerError().finish()))
|
||||
})
|
||||
Box::pin(
|
||||
async move { Ok(req.into_response(HttpResponse::InternalServerError().finish())) },
|
||||
)
|
||||
};
|
||||
|
||||
let logger = Logger::default();
|
||||
|
|
|
@ -540,21 +540,17 @@ mod tests {
|
|||
let mw_server = make_mw(StatusCode::INTERNAL_SERVER_ERROR).await;
|
||||
let mw_client = make_mw(StatusCode::BAD_REQUEST).await;
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_server, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_server, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn default_handlers_separate_client_server() {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn error_handler_client<B>(
|
||||
mut res: ServiceResponse<B>,
|
||||
) -> Result<ErrorHandlerResponse<B>> {
|
||||
fn error_handler_client<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
res.response_mut()
|
||||
.headers_mut()
|
||||
.insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
|
||||
|
@ -562,9 +558,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn error_handler_server<B>(
|
||||
mut res: ServiceResponse<B>,
|
||||
) -> Result<ErrorHandlerResponse<B>> {
|
||||
fn error_handler_server<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
res.response_mut()
|
||||
.headers_mut()
|
||||
.insert(CONTENT_TYPE, HeaderValue::from_static("0002"));
|
||||
|
@ -582,21 +576,17 @@ mod tests {
|
|||
let mw_server = make_mw(StatusCode::INTERNAL_SERVER_ERROR).await;
|
||||
let mw_client = make_mw(StatusCode::BAD_REQUEST).await;
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_server, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_server, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn default_handlers_specialization() {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn error_handler_client<B>(
|
||||
mut res: ServiceResponse<B>,
|
||||
) -> Result<ErrorHandlerResponse<B>> {
|
||||
fn error_handler_client<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
res.response_mut()
|
||||
.headers_mut()
|
||||
.insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
|
||||
|
@ -624,12 +614,10 @@ mod tests {
|
|||
let mw_client = make_mw(StatusCode::BAD_REQUEST).await;
|
||||
let mw_specific = make_mw(StatusCode::UNPROCESSABLE_ENTITY).await;
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
|
||||
let resp =
|
||||
test::call_service(&mw_specific, TestRequest::default().to_srv_request()).await;
|
||||
let resp = test::call_service(&mw_specific, TestRequest::default().to_srv_request()).await;
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0003");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -489,12 +489,8 @@ impl Format {
|
|||
unreachable!("regex and code mismatch")
|
||||
}
|
||||
}
|
||||
"i" => {
|
||||
FormatText::RequestHeader(HeaderName::try_from(key.as_str()).unwrap())
|
||||
}
|
||||
"o" => {
|
||||
FormatText::ResponseHeader(HeaderName::try_from(key.as_str()).unwrap())
|
||||
}
|
||||
"i" => FormatText::RequestHeader(HeaderName::try_from(key.as_str()).unwrap()),
|
||||
"o" => FormatText::ResponseHeader(HeaderName::try_from(key.as_str()).unwrap()),
|
||||
"e" => FormatText::EnvironHeader(key.as_str().to_owned()),
|
||||
"xi" => FormatText::CustomRequest(key.as_str().to_owned(), None),
|
||||
"xo" => FormatText::CustomResponse(key.as_str().to_owned(), None),
|
||||
|
@ -710,9 +706,7 @@ impl FormatText {
|
|||
}
|
||||
|
||||
/// Converter to get a String from something that writes to a Formatter.
|
||||
pub(crate) struct FormatDisplay<'a>(
|
||||
&'a dyn Fn(&mut fmt::Formatter<'_>) -> Result<(), fmt::Error>,
|
||||
);
|
||||
pub(crate) struct FormatDisplay<'a>(&'a dyn Fn(&mut fmt::Formatter<'_>) -> Result<(), fmt::Error>);
|
||||
|
||||
impl<'a> fmt::Display for FormatDisplay<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
|
|
|
@ -9,14 +9,16 @@ mod logger;
|
|||
mod noop;
|
||||
mod normalize;
|
||||
|
||||
pub use self::compat::Compat;
|
||||
pub use self::condition::Condition;
|
||||
pub use self::default_headers::DefaultHeaders;
|
||||
pub use self::err_handlers::{ErrorHandlerResponse, ErrorHandlers};
|
||||
pub use self::logger::Logger;
|
||||
#[cfg(test)]
|
||||
pub(crate) use self::noop::Noop;
|
||||
pub use self::normalize::{NormalizePath, TrailingSlash};
|
||||
pub use self::{
|
||||
compat::Compat,
|
||||
condition::Condition,
|
||||
default_headers::DefaultHeaders,
|
||||
err_handlers::{ErrorHandlerResponse, ErrorHandlers},
|
||||
logger::Logger,
|
||||
normalize::{NormalizePath, TrailingSlash},
|
||||
};
|
||||
|
||||
#[cfg(feature = "__compress")]
|
||||
mod compress;
|
||||
|
@ -26,9 +28,8 @@ pub use self::compress::Compress;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{http::StatusCode, App};
|
||||
|
||||
use super::*;
|
||||
use crate::{http::StatusCode, App};
|
||||
|
||||
#[test]
|
||||
fn common_combinations() {
|
||||
|
|
|
@ -181,9 +181,8 @@ impl Responder for Redirect {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{dev::Service, http::StatusCode, test, App};
|
||||
|
||||
use super::*;
|
||||
use crate::{dev::Service, http::StatusCode, test, App};
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn absolute_redirects() {
|
||||
|
|
|
@ -653,13 +653,13 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_drop_http_request_pool() {
|
||||
let srv = init_service(App::new().service(web::resource("/").to(
|
||||
|req: HttpRequest| {
|
||||
let srv = init_service(
|
||||
App::new().service(web::resource("/").to(|req: HttpRequest| {
|
||||
HttpResponse::Ok()
|
||||
.insert_header(("pool_cap", req.app_state().pool().cap))
|
||||
.finish()
|
||||
},
|
||||
)))
|
||||
})),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::default().to_request();
|
||||
|
@ -807,10 +807,7 @@ mod tests {
|
|||
web::scope("/user/{id}")
|
||||
.service(web::resource("/profile").route(web::get().to(
|
||||
move |req: HttpRequest| {
|
||||
assert_eq!(
|
||||
req.match_pattern(),
|
||||
Some("/user/{id}/profile".to_owned())
|
||||
);
|
||||
assert_eq!(req.match_pattern(), Some("/user/{id}/profile".to_owned()));
|
||||
|
||||
HttpResponse::Ok().finish()
|
||||
},
|
||||
|
|
|
@ -353,12 +353,8 @@ where
|
|||
pub fn default_service<F, U>(mut self, f: F) -> Self
|
||||
where
|
||||
F: IntoServiceFactory<U, ServiceRequest>,
|
||||
U: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Config = (),
|
||||
Response = ServiceResponse,
|
||||
Error = Error,
|
||||
> + 'static,
|
||||
U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
|
||||
+ 'static,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
// create and configure default resource
|
||||
|
@ -625,10 +621,8 @@ mod tests {
|
|||
let fut = srv.call(req);
|
||||
async {
|
||||
fut.await.map(|mut res| {
|
||||
res.headers_mut().insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_static("0001"),
|
||||
);
|
||||
res.headers_mut()
|
||||
.insert(header::CONTENT_TYPE, HeaderValue::from_static("0001"));
|
||||
res
|
||||
})
|
||||
}
|
||||
|
@ -660,12 +654,9 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_pattern() {
|
||||
let srv = init_service(
|
||||
App::new().service(
|
||||
web::resource(["/test", "/test2"])
|
||||
.to(|| async { Ok::<_, Error>(HttpResponse::Ok()) }),
|
||||
),
|
||||
)
|
||||
let srv = init_service(App::new().service(
|
||||
web::resource(["/test", "/test2"]).to(|| async { Ok::<_, Error>(HttpResponse::Ok()) }),
|
||||
))
|
||||
.await;
|
||||
let req = TestRequest::with_uri("/test").to_request();
|
||||
let resp = call_service(&srv, req).await;
|
||||
|
@ -804,7 +795,8 @@ mod tests {
|
|||
#[allow(deprecated)]
|
||||
#[actix_rt::test]
|
||||
async fn test_data_default_service() {
|
||||
let srv = init_service(
|
||||
let srv =
|
||||
init_service(
|
||||
App::new().data(1usize).service(
|
||||
web::resource("/test")
|
||||
.data(10usize)
|
||||
|
|
|
@ -14,8 +14,10 @@ use crate::{
|
|||
body::{BodyStream, BoxBody, MessageBody},
|
||||
dev::Extensions,
|
||||
error::{Error, JsonPayloadError},
|
||||
http::header::{self, HeaderName, TryIntoHeaderPair, TryIntoHeaderValue},
|
||||
http::{ConnectionType, StatusCode},
|
||||
http::{
|
||||
header::{self, HeaderName, TryIntoHeaderPair, TryIntoHeaderValue},
|
||||
ConnectionType, StatusCode,
|
||||
},
|
||||
BoxError, HttpRequest, HttpResponse, Responder,
|
||||
};
|
||||
|
||||
|
@ -472,9 +474,8 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_serde_json_in_body() {
|
||||
let resp = HttpResponse::Ok().body(
|
||||
serde_json::to_vec(&serde_json::json!({ "test-key": "test-value" })).unwrap(),
|
||||
);
|
||||
let resp = HttpResponse::Ok()
|
||||
.body(serde_json::to_vec(&serde_json::json!({ "test-key": "test-value" })).unwrap());
|
||||
|
||||
assert_eq!(
|
||||
body::to_bytes(resp.into_body()).await.unwrap().as_ref(),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use actix_http::{
|
||||
body::EitherBody, error::HttpError, header::HeaderMap, header::TryIntoHeaderPair,
|
||||
body::EitherBody,
|
||||
error::HttpError,
|
||||
header::{HeaderMap, TryIntoHeaderPair},
|
||||
StatusCode,
|
||||
};
|
||||
|
||||
|
@ -168,9 +170,8 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bytes::Bytes;
|
||||
|
||||
use actix_http::body::to_bytes;
|
||||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
|
|
|
@ -87,8 +87,7 @@ impl HttpResponse {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::http::StatusCode;
|
||||
use crate::HttpResponse;
|
||||
use crate::{http::StatusCode, HttpResponse};
|
||||
|
||||
#[test]
|
||||
fn test_build() {
|
||||
|
|
|
@ -5,10 +5,9 @@ mod responder;
|
|||
#[allow(clippy::module_inception)]
|
||||
mod response;
|
||||
|
||||
pub use self::builder::HttpResponseBuilder;
|
||||
pub use self::customize_responder::CustomizeResponder;
|
||||
pub use self::responder::Responder;
|
||||
pub use self::response::HttpResponse;
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
pub use self::response::CookieIter;
|
||||
pub use self::{
|
||||
builder::HttpResponseBuilder, customize_responder::CustomizeResponder, responder::Responder,
|
||||
response::HttpResponse,
|
||||
};
|
||||
|
|
|
@ -186,11 +186,10 @@ impl_into_string_responder!(Cow<'_, str>);
|
|||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use actix_http::body::to_bytes;
|
||||
use actix_service::Service;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
|
||||
use actix_http::body::to_bytes;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
error,
|
||||
|
|
|
@ -8,7 +8,6 @@ use actix_http::{
|
|||
header::HeaderMap,
|
||||
Extensions, Response, ResponseHead, StatusCode,
|
||||
};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
use {
|
||||
actix_http::{
|
||||
|
|
|
@ -290,7 +290,8 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_route() {
|
||||
let srv = init_service(
|
||||
let srv =
|
||||
init_service(
|
||||
App::new()
|
||||
.service(
|
||||
web::resource("/test")
|
||||
|
|
|
@ -66,8 +66,7 @@
|
|||
// - Re-export but hide the runtime macros because they won't work directly but are required for
|
||||
// `#[actix_web::main]` and `#[actix_web::test]` to work.
|
||||
|
||||
pub use actix_rt::{net, pin, signal, spawn, task, time, Runtime, System, SystemRunner};
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
#[doc(hidden)]
|
||||
pub use actix_macros::{main, test};
|
||||
pub use actix_rt::{net, pin, signal, spawn, task, time, Runtime, System, SystemRunner};
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::{cell::RefCell, fmt, future::Future, mem, rc::Rc};
|
|||
use actix_http::{body::MessageBody, Extensions};
|
||||
use actix_router::{ResourceDef, Router};
|
||||
use actix_service::{
|
||||
apply, apply_fn_factory, boxed, IntoServiceFactory, Service, ServiceFactory,
|
||||
ServiceFactoryExt, Transform,
|
||||
apply, apply_fn_factory, boxed, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt,
|
||||
Transform,
|
||||
};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use futures_util::future::join_all;
|
||||
|
@ -273,12 +273,8 @@ where
|
|||
pub fn default_service<F, U>(mut self, f: F) -> Self
|
||||
where
|
||||
F: IntoServiceFactory<U, ServiceRequest>,
|
||||
U: ServiceFactory<
|
||||
ServiceRequest,
|
||||
Config = (),
|
||||
Response = ServiceResponse,
|
||||
Error = Error,
|
||||
> + 'static,
|
||||
U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
|
||||
+ 'static,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
// create and configure default resource
|
||||
|
@ -604,10 +600,10 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_scope() {
|
||||
let srv =
|
||||
init_service(App::new().service(
|
||||
web::scope("/app").service(web::resource("/path1").to(HttpResponse::Ok)),
|
||||
))
|
||||
let srv = init_service(
|
||||
App::new()
|
||||
.service(web::scope("/app").service(web::resource("/path1").to(HttpResponse::Ok))),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::with_uri("/app/path1").to_request();
|
||||
|
@ -638,8 +634,7 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_scope_root2() {
|
||||
let srv = init_service(
|
||||
App::new()
|
||||
.service(web::scope("/app/").service(web::resource("").to(HttpResponse::Ok))),
|
||||
App::new().service(web::scope("/app/").service(web::resource("").to(HttpResponse::Ok))),
|
||||
)
|
||||
.await;
|
||||
|
||||
|
@ -784,7 +779,8 @@ mod tests {
|
|||
|
||||
#[actix_rt::test]
|
||||
async fn test_nested_scope_no_slash() {
|
||||
let srv = init_service(App::new().service(web::scope("/app").service(
|
||||
let srv =
|
||||
init_service(App::new().service(web::scope("/app").service(
|
||||
web::scope("t1").service(web::resource("/path1").to(HttpResponse::Created)),
|
||||
)))
|
||||
.await;
|
||||
|
@ -845,12 +841,9 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_nested_scope_with_variable_segment() {
|
||||
let srv = init_service(App::new().service(web::scope("/app").service(
|
||||
web::scope("/{project_id}").service(web::resource("/path1").to(
|
||||
|r: HttpRequest| {
|
||||
HttpResponse::Created()
|
||||
.body(format!("project: {}", &r.match_info()["project_id"]))
|
||||
},
|
||||
)),
|
||||
web::scope("/{project_id}").service(web::resource("/path1").to(|r: HttpRequest| {
|
||||
HttpResponse::Created().body(format!("project: {}", &r.match_info()["project_id"]))
|
||||
})),
|
||||
)))
|
||||
.await;
|
||||
|
||||
|
@ -1065,7 +1058,8 @@ mod tests {
|
|||
#[allow(deprecated)]
|
||||
#[actix_rt::test]
|
||||
async fn test_override_data_default_service() {
|
||||
let srv = init_service(App::new().data(1usize).service(
|
||||
let srv =
|
||||
init_service(App::new().data(1usize).service(
|
||||
web::scope("app").data(10usize).default_service(web::to(
|
||||
|data: web::Data<usize>| {
|
||||
assert_eq!(**data, 10);
|
||||
|
@ -1150,11 +1144,11 @@ mod tests {
|
|||
#[actix_rt::test]
|
||||
async fn test_url_for_nested() {
|
||||
let srv = init_service(App::new().service(web::scope("/a").service(
|
||||
web::scope("/b").service(web::resource("/c/{stuff}").name("c").route(
|
||||
web::get().to(|req: HttpRequest| {
|
||||
web::scope("/b").service(web::resource("/c/{stuff}").name("c").route(web::get().to(
|
||||
|req: HttpRequest| {
|
||||
HttpResponse::Ok().body(format!("{}", req.url_for("c", ["12345"]).unwrap()))
|
||||
}),
|
||||
)),
|
||||
},
|
||||
))),
|
||||
)))
|
||||
.await;
|
||||
|
||||
|
|
|
@ -7,20 +7,18 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||
use actix_http::TlsAcceptorConfig;
|
||||
use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
|
||||
use actix_server::{Server, ServerBuilder};
|
||||
use actix_service::{
|
||||
map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _,
|
||||
};
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder};
|
||||
#[cfg(feature = "rustls")]
|
||||
use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig;
|
||||
|
||||
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||
use actix_http::TlsAcceptorConfig;
|
||||
|
||||
use crate::{config::AppConfig, Error};
|
||||
|
||||
struct Socket {
|
||||
|
@ -437,9 +435,8 @@ where
|
|||
.local_addr(addr);
|
||||
|
||||
if let Some(handler) = on_connect_fn.clone() {
|
||||
svc = svc.on_connect_ext(move |io: &_, ext: _| {
|
||||
(handler)(io as &dyn Any, ext)
|
||||
})
|
||||
svc =
|
||||
svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
|
||||
};
|
||||
|
||||
let fac = factory()
|
||||
|
@ -481,9 +478,8 @@ where
|
|||
.local_addr(addr);
|
||||
|
||||
if let Some(handler) = on_connect_fn.clone() {
|
||||
svc = svc.on_connect_ext(move |io: &_, ext: _| {
|
||||
(handler)(io as &dyn Any, ext)
|
||||
})
|
||||
svc =
|
||||
svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
|
||||
};
|
||||
|
||||
let fac = factory()
|
||||
|
@ -715,8 +711,7 @@ where
|
|||
.client_disconnect_timeout(c.client_disconnect_timeout);
|
||||
|
||||
if let Some(handler) = on_connect_fn.clone() {
|
||||
svc = svc
|
||||
.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
|
||||
svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
|
||||
}
|
||||
|
||||
let fac = factory()
|
||||
|
@ -759,10 +754,7 @@ where
|
|||
}
|
||||
|
||||
/// Bind TCP listeners to socket addresses resolved from `addrs` with options.
|
||||
fn bind_addrs(
|
||||
addrs: impl net::ToSocketAddrs,
|
||||
backlog: u32,
|
||||
) -> io::Result<Vec<net::TcpListener>> {
|
||||
fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
|
||||
let mut err = None;
|
||||
let mut success = false;
|
||||
let mut sockets = Vec::new();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue