mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-26 06:57:43 +02:00
apply standard formatting
This commit is contained in:
@ -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,11 +90,9 @@ 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(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut sess =
|
||||
rustls::ClientConnection::new(Arc::new(config), ServerName::try_from("localhost").unwrap())
|
||||
.unwrap();
|
||||
|
||||
let mut sock = StdTcpStream::connect(addr).unwrap();
|
||||
let mut stream = rustls::Stream::new(&mut sess, &mut sock);
|
||||
|
@ -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" => {
|
||||
|
Reference in New Issue
Block a user