mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into custom_headers_in_redirects
This commit is contained in:
commit
51583da584
|
@ -1,6 +1,6 @@
|
||||||
[alias]
|
[alias]
|
||||||
chk = "check --workspace --all-features --tests --examples --bins"
|
chk = "check --workspace --all-features --tests --examples --bins"
|
||||||
lint = "clippy --workspace --tests --examples"
|
lint = "clippy --workspace --all-features --tests --examples --bins"
|
||||||
ci-min = "hack check --workspace --no-default-features"
|
ci-min = "hack check --workspace --no-default-features"
|
||||||
ci-min-test = "hack check --workspace --no-default-features --tests --examples"
|
ci-min-test = "hack check --workspace --no-default-features --tests --examples"
|
||||||
ci-default = "check --workspace --bins --tests --examples"
|
ci-default = "check --workspace --bins --tests --examples"
|
||||||
|
|
|
@ -8,7 +8,7 @@ PR_TYPE
|
||||||
|
|
||||||
|
|
||||||
## PR Checklist
|
## PR Checklist
|
||||||
<!-- Check your PR fulfills the following items. ->>
|
<!-- Check your PR fulfills the following items. -->
|
||||||
<!-- For draft PRs check the boxes as you complete them. -->
|
<!-- For draft PRs check the boxes as you complete them. -->
|
||||||
|
|
||||||
- [ ] Tests for the changes have been added / updated.
|
- [ ] Tests for the changes have been added / updated.
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Added
|
||||||
|
* Re-export actix-service `ServiceFactory` in `dev` module. [#2325]
|
||||||
|
|
||||||
|
[#2325]: https://github.com/actix/actix-web/pull/2325
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.8 - 2021-06-26
|
## 4.0.0-beta.8 - 2021-06-26
|
||||||
|
|
|
@ -104,6 +104,8 @@ impl ServiceConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the local address that this server is bound to.
|
/// Returns the local address that this server is bound to.
|
||||||
|
///
|
||||||
|
/// Returns `None` for connections via UDS (Unix Domain Socket).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn local_addr(&self) -> Option<net::SocketAddr> {
|
pub fn local_addr(&self) -> Option<net::SocketAddr> {
|
||||||
self.0.local_addr
|
self.0.local_addr
|
||||||
|
|
|
@ -55,6 +55,8 @@ impl Error {
|
||||||
Self::new(Kind::Io)
|
Self::new(Kind::Io)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// used in encoder behind feature flag so ignore unused warning
|
||||||
|
#[allow(unused)]
|
||||||
pub(crate) fn new_encoder() -> Self {
|
pub(crate) fn new_encoder() -> Self {
|
||||||
Self::new(Kind::Encoder)
|
Self::new(Kind::Encoder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
HttpMessage,
|
HttpMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Request
|
/// An HTTP request.
|
||||||
pub struct Request<P = PayloadStream> {
|
pub struct Request<P = PayloadStream> {
|
||||||
pub(crate) payload: Payload<P>,
|
pub(crate) payload: Payload<P>,
|
||||||
pub(crate) head: Message<RequestHead>,
|
pub(crate) head: Message<RequestHead>,
|
||||||
|
|
25
src/dev.rs
25
src/dev.rs
|
@ -1,13 +1,7 @@
|
||||||
//! Lower level `actix-web` types.
|
//! Lower-level types and re-exports.
|
||||||
//!
|
//!
|
||||||
//! Most users will not have to interact with the types in this module,
|
//! Most users will not have to interact with the types in this module, but it is useful for those
|
||||||
//! but it is useful as a glob import for those writing middleware, developing libraries,
|
//! writing extractors, middleware and libraries, or interacting with the service API directly.
|
||||||
//! or interacting with the service API directly:
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! # #![allow(unused_imports)]
|
|
||||||
//! use actix_web::dev::*;
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
pub use crate::config::{AppConfig, AppService};
|
pub use crate::config::{AppConfig, AppService};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -24,26 +18,25 @@ pub use actix_http::body::{AnyBody, Body, BodySize, MessageBody, ResponseBody, S
|
||||||
|
|
||||||
#[cfg(feature = "__compress")]
|
#[cfg(feature = "__compress")]
|
||||||
pub use actix_http::encoding::Decoder as Decompress;
|
pub use actix_http::encoding::Decoder as Decompress;
|
||||||
pub use actix_http::ResponseBuilder as BaseHttpResponseBuilder;
|
|
||||||
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, ResponseHead};
|
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, ResponseHead};
|
||||||
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
||||||
pub use actix_server::Server;
|
pub use actix_server::Server;
|
||||||
pub use actix_service::{
|
pub use actix_service::{
|
||||||
always_ready, fn_factory, fn_service, forward_ready, Service, Transform,
|
always_ready, fn_factory, fn_service, forward_ready, Service, ServiceFactory, Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn insert_slash(mut patterns: Vec<String>) -> Vec<String> {
|
use crate::http::header::ContentEncoding;
|
||||||
|
use actix_http::{Response, ResponseBuilder};
|
||||||
|
|
||||||
|
pub(crate) fn insert_leading_slash(mut patterns: Vec<String>) -> Vec<String> {
|
||||||
for path in &mut patterns {
|
for path in &mut patterns {
|
||||||
if !path.is_empty() && !path.starts_with('/') {
|
if !path.is_empty() && !path.starts_with('/') {
|
||||||
path.insert(0, '/');
|
path.insert(0, '/');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
patterns
|
patterns
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::http::header::ContentEncoding;
|
|
||||||
use actix_http::{Response, ResponseBuilder};
|
|
||||||
|
|
||||||
struct Enc(ContentEncoding);
|
struct Enc(ContentEncoding);
|
||||||
|
|
||||||
/// Helper trait that allows to set specific encoding for response.
|
/// Helper trait that allows to set specific encoding for response.
|
||||||
|
|
10
src/info.rs
10
src/info.rs
|
@ -65,10 +65,10 @@ fn first_header_value<'a>(req: &'a RequestHead, name: &'_ HeaderName) -> Option<
|
||||||
/// [rfc7239-63]: https://datatracker.ietf.org/doc/html/rfc7239#section-6.3
|
/// [rfc7239-63]: https://datatracker.ietf.org/doc/html/rfc7239#section-6.3
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ConnectionInfo {
|
pub struct ConnectionInfo {
|
||||||
scheme: String,
|
|
||||||
host: String,
|
host: String,
|
||||||
realip_remote_addr: Option<String>,
|
scheme: String,
|
||||||
remote_addr: Option<String>,
|
remote_addr: Option<String>,
|
||||||
|
realip_remote_addr: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectionInfo {
|
impl ConnectionInfo {
|
||||||
|
@ -135,7 +135,7 @@ impl ConnectionInfo {
|
||||||
.or_else(|| first_header_value(req, &*X_FORWARDED_HOST))
|
.or_else(|| first_header_value(req, &*X_FORWARDED_HOST))
|
||||||
.or_else(|| req.headers.get(&header::HOST)?.to_str().ok())
|
.or_else(|| req.headers.get(&header::HOST)?.to_str().ok())
|
||||||
.or_else(|| req.uri.authority().map(Authority::as_str))
|
.or_else(|| req.uri.authority().map(Authority::as_str))
|
||||||
.unwrap_or(cfg.host())
|
.unwrap_or_else(|| cfg.host())
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let realip_remote_addr = realip_remote_addr
|
let realip_remote_addr = realip_remote_addr
|
||||||
|
@ -145,9 +145,9 @@ impl ConnectionInfo {
|
||||||
let remote_addr = req.peer_addr.map(|addr| addr.to_string());
|
let remote_addr = req.peer_addr.map(|addr| addr.to_string());
|
||||||
|
|
||||||
ConnectionInfo {
|
ConnectionInfo {
|
||||||
remote_addr,
|
|
||||||
scheme,
|
|
||||||
host,
|
host,
|
||||||
|
scheme,
|
||||||
|
remote_addr,
|
||||||
realip_remote_addr,
|
realip_remote_addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,10 @@ use crate::{
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
struct Cookies(Vec<Cookie<'static>>);
|
struct Cookies(Vec<Cookie<'static>>);
|
||||||
|
|
||||||
|
/// An incoming request.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
/// An HTTP Request
|
|
||||||
pub struct HttpRequest {
|
pub struct HttpRequest {
|
||||||
/// # Panics
|
/// # Invariant
|
||||||
/// `Rc<HttpRequestInner>` is used exclusively and NO `Weak<HttpRequestInner>`
|
/// `Rc<HttpRequestInner>` is used exclusively and NO `Weak<HttpRequestInner>`
|
||||||
/// is allowed anywhere in the code. Weak pointer is purposely ignored when
|
/// is allowed anywhere in the code. Weak pointer is purposely ignored when
|
||||||
/// doing `Rc`'s ref counter check. Expect panics if this invariant is violated.
|
/// doing `Rc`'s ref counter check. Expect panics if this invariant is violated.
|
||||||
|
|
|
@ -15,7 +15,7 @@ use futures_util::future::join_all;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::Data,
|
data::Data,
|
||||||
dev::{insert_slash, AppService, HttpServiceFactory, ResourceDef},
|
dev::{insert_leading_slash, AppService, HttpServiceFactory, ResourceDef},
|
||||||
guard::Guard,
|
guard::Guard,
|
||||||
handler::Handler,
|
handler::Handler,
|
||||||
responder::Responder,
|
responder::Responder,
|
||||||
|
@ -391,7 +391,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
||||||
ResourceDef::new(insert_slash(self.rdef.clone()))
|
ResourceDef::new(insert_leading_slash(self.rdef.clone()))
|
||||||
} else {
|
} else {
|
||||||
ResourceDef::new(self.rdef.clone())
|
ResourceDef::new(self.rdef.clone())
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,20 +24,14 @@ use {
|
||||||
|
|
||||||
use crate::{error::Error, HttpResponseBuilder};
|
use crate::{error::Error, HttpResponseBuilder};
|
||||||
|
|
||||||
/// An HTTP Response
|
/// An outgoing response.
|
||||||
pub struct HttpResponse<B = AnyBody> {
|
pub struct HttpResponse<B = AnyBody> {
|
||||||
res: Response<B>,
|
res: Response<B>,
|
||||||
pub(crate) error: Option<Error>,
|
pub(crate) error: Option<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpResponse<AnyBody> {
|
impl HttpResponse<AnyBody> {
|
||||||
/// Create HTTP response builder with specific status.
|
/// Constructs a response.
|
||||||
#[inline]
|
|
||||||
pub fn build(status: StatusCode) -> HttpResponseBuilder {
|
|
||||||
HttpResponseBuilder::new(status)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a response.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(status: StatusCode) -> Self {
|
pub fn new(status: StatusCode) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -46,6 +40,12 @@ impl HttpResponse<AnyBody> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a response builder with specific HTTP status.
|
||||||
|
#[inline]
|
||||||
|
pub fn build(status: StatusCode) -> HttpResponseBuilder {
|
||||||
|
HttpResponseBuilder::new(status)
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an error response.
|
/// Create an error response.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_error(error: impl Into<Error>) -> Self {
|
pub fn from_error(error: impl Into<Error>) -> Self {
|
||||||
|
|
|
@ -295,6 +295,7 @@ where
|
||||||
let mut svc = HttpService::build()
|
let mut svc = HttpService::build()
|
||||||
.keep_alive(c.keep_alive)
|
.keep_alive(c.keep_alive)
|
||||||
.client_timeout(c.client_timeout)
|
.client_timeout(c.client_timeout)
|
||||||
|
.client_disconnect(c.client_shutdown)
|
||||||
.local_addr(addr);
|
.local_addr(addr);
|
||||||
|
|
||||||
if let Some(handler) = on_connect_fn.clone() {
|
if let Some(handler) = on_connect_fn.clone() {
|
||||||
|
@ -352,7 +353,8 @@ where
|
||||||
let svc = HttpService::build()
|
let svc = HttpService::build()
|
||||||
.keep_alive(c.keep_alive)
|
.keep_alive(c.keep_alive)
|
||||||
.client_timeout(c.client_timeout)
|
.client_timeout(c.client_timeout)
|
||||||
.client_disconnect(c.client_shutdown);
|
.client_disconnect(c.client_shutdown)
|
||||||
|
.local_addr(addr);
|
||||||
|
|
||||||
let svc = if let Some(handler) = on_connect_fn.clone() {
|
let svc = if let Some(handler) = on_connect_fn.clone() {
|
||||||
svc.on_connect_ext(move |io: &_, ext: _| {
|
svc.on_connect_ext(move |io: &_, ext: _| {
|
||||||
|
@ -523,10 +525,11 @@ where
|
||||||
addr: socket_addr,
|
addr: socket_addr,
|
||||||
});
|
});
|
||||||
|
|
||||||
let addr = format!("actix-web-service-{:?}", lst.local_addr()?);
|
let addr = lst.local_addr()?;
|
||||||
|
let name = format!("actix-web-service-{:?}", addr);
|
||||||
let on_connect_fn = self.on_connect_fn.clone();
|
let on_connect_fn = self.on_connect_fn.clone();
|
||||||
|
|
||||||
self.builder = self.builder.listen_uds(addr, lst, move || {
|
self.builder = self.builder.listen_uds(name, lst, move || {
|
||||||
let c = cfg.lock().unwrap();
|
let c = cfg.lock().unwrap();
|
||||||
let config = AppConfig::new(
|
let config = AppConfig::new(
|
||||||
false,
|
false,
|
||||||
|
@ -537,7 +540,8 @@ where
|
||||||
fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
|
fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
|
||||||
let mut svc = HttpService::build()
|
let mut svc = HttpService::build()
|
||||||
.keep_alive(c.keep_alive)
|
.keep_alive(c.keep_alive)
|
||||||
.client_timeout(c.client_timeout);
|
.client_timeout(c.client_timeout)
|
||||||
|
.client_disconnect(c.client_shutdown);
|
||||||
|
|
||||||
if let Some(handler) = on_connect_fn.clone() {
|
if let Some(handler) = on_connect_fn.clone() {
|
||||||
svc = svc
|
svc = svc
|
||||||
|
@ -554,8 +558,8 @@ where
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
/// Start listening for incoming unix domain connections.
|
/// Start listening for incoming unix domain connections.
|
||||||
|
#[cfg(unix)]
|
||||||
pub fn bind_uds<A>(mut self, addr: A) -> io::Result<Self>
|
pub fn bind_uds<A>(mut self, addr: A) -> io::Result<Self>
|
||||||
where
|
where
|
||||||
A: AsRef<std::path::Path>,
|
A: AsRef<std::path::Path>,
|
||||||
|
@ -568,6 +572,7 @@ where
|
||||||
let factory = self.factory.clone();
|
let factory = self.factory.clone();
|
||||||
let socket_addr =
|
let socket_addr =
|
||||||
net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||||
|
|
||||||
self.sockets.push(Socket {
|
self.sockets.push(Socket {
|
||||||
scheme: "http",
|
scheme: "http",
|
||||||
addr: socket_addr,
|
addr: socket_addr,
|
||||||
|
@ -592,6 +597,7 @@ where
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.keep_alive(c.keep_alive)
|
.keep_alive(c.keep_alive)
|
||||||
.client_timeout(c.client_timeout)
|
.client_timeout(c.client_timeout)
|
||||||
|
.client_disconnect(c.client_shutdown)
|
||||||
.finish(map_config(fac, move |_| config.clone())),
|
.finish(map_config(fac, move |_| config.clone())),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ use cookie::{Cookie, ParseError as CookieParseError};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{AppConfig, AppService},
|
config::{AppConfig, AppService},
|
||||||
dev::insert_slash,
|
dev::insert_leading_slash,
|
||||||
guard::Guard,
|
guard::Guard,
|
||||||
info::ConnectionInfo,
|
info::ConnectionInfo,
|
||||||
rmap::ResourceMap,
|
rmap::ResourceMap,
|
||||||
|
@ -59,9 +59,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An service http request
|
/// A service level request wrapper.
|
||||||
///
|
///
|
||||||
/// ServiceRequest allows mutable access to request's internal structures
|
/// Allows mutable access to request's internal structures.
|
||||||
pub struct ServiceRequest {
|
pub struct ServiceRequest {
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
payload: Payload,
|
payload: Payload,
|
||||||
|
@ -325,6 +325,7 @@ impl fmt::Debug for ServiceRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A service level response wrapper.
|
||||||
pub struct ServiceResponse<B = AnyBody> {
|
pub struct ServiceResponse<B = AnyBody> {
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
response: HttpResponse<B>,
|
response: HttpResponse<B>,
|
||||||
|
@ -550,7 +551,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
||||||
ResourceDef::new(insert_slash(self.rdef))
|
ResourceDef::new(insert_leading_slash(self.rdef))
|
||||||
} else {
|
} else {
|
||||||
ResourceDef::new(self.rdef)
|
ResourceDef::new(self.rdef)
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl std::fmt::Display for MyError {
|
||||||
|
|
||||||
#[get("/test")]
|
#[get("/test")]
|
||||||
async fn test() -> Result<actix_web::HttpResponse, actix_web::error::Error> {
|
async fn test() -> Result<actix_web::HttpResponse, actix_web::error::Error> {
|
||||||
return Err(MyError.into());
|
Err(MyError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
Loading…
Reference in New Issue