mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into asonix/awc-rustls-0.23
This commit is contained in:
commit
52edb37bf3
|
@ -12,11 +12,12 @@
|
|||
//! Protocol: HTTP/1.1
|
||||
//! ```
|
||||
|
||||
extern crate tls_rustls_023 as rustls;
|
||||
|
||||
use std::io;
|
||||
|
||||
use actix_http::{Error, HttpService, Request, Response};
|
||||
use actix_utils::future::ok;
|
||||
use tls_rustls_023 as rustls;
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
|
|
|
@ -14,3 +14,65 @@
|
|||
[](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
Dependencies:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
actix-multipart = "0.6"
|
||||
actix-web = "4.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
```
|
||||
|
||||
Code:
|
||||
|
||||
```rust
|
||||
use actix_web::{post, App, HttpServer, Responder};
|
||||
|
||||
use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Metadata {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, MultipartForm)]
|
||||
struct UploadForm {
|
||||
#[multipart(limit = "100MB")]
|
||||
file: TempFile,
|
||||
json: MPJson<Metadata>,
|
||||
}
|
||||
|
||||
#[post("/videos")]
|
||||
pub async fn post_video(MultipartForm(form): MultipartForm<UploadForm>) -> impl Responder {
|
||||
format!(
|
||||
"Uploaded file {}, with size: {}",
|
||||
form.json.name, form.file.size
|
||||
)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(move || App::new().service(post_video))
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
```
|
||||
|
||||
Curl request :
|
||||
```bash
|
||||
curl -v --request POST \
|
||||
--url http://localhost:8080/videos \
|
||||
-F 'json={"name": "Cargo.lock"};type=application/json' \
|
||||
-F file=@./Cargo.lock
|
||||
```
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
https://github.com/actix/examples/tree/master/forms/multipart
|
|
@ -1,4 +1,39 @@
|
|||
//! Multipart form support for Actix Web.
|
||||
//! # Examples
|
||||
//! ```no_run
|
||||
//! use actix_web::{post, App, HttpServer, Responder};
|
||||
//!
|
||||
//! use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm};
|
||||
//! use serde::Deserialize;
|
||||
//!
|
||||
//! #[derive(Debug, Deserialize)]
|
||||
//! struct Metadata {
|
||||
//! name: String,
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Debug, MultipartForm)]
|
||||
//! struct UploadForm {
|
||||
//! #[multipart(limit = "100MB")]
|
||||
//! file: TempFile,
|
||||
//! json: MPJson<Metadata>,
|
||||
//! }
|
||||
//!
|
||||
//! #[post("/videos")]
|
||||
//! pub async fn post_video(MultipartForm(form): MultipartForm<UploadForm>) -> impl Responder {
|
||||
//! format!(
|
||||
//! "Uploaded file {}, with size: {}",
|
||||
//! form.json.name, form.file.size
|
||||
//! )
|
||||
//! }
|
||||
//!
|
||||
//! #[actix_web::main]
|
||||
//! async fn main() -> std::io::Result<()> {
|
||||
//! HttpServer::new(move || App::new().service(post_video))
|
||||
//! .bind(("127.0.0.1", 8080))?
|
||||
//! .run()
|
||||
//! .await
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible)]
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.72.
|
||||
- Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature.
|
||||
- Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported.
|
||||
- Minimum supported Rust version (MSRV) is now 1.72.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ rustls-0_20 = ["tls-rustls-0_20", "actix-http/rustls-0_20", "awc/rustls-0_20"]
|
|||
rustls-0_21 = ["tls-rustls-0_21", "actix-http/rustls-0_21", "awc/rustls-0_21"]
|
||||
# TLS via Rustls v0.22
|
||||
rustls-0_22 = ["tls-rustls-0_22", "actix-http/rustls-0_22", "awc/rustls-0_22-webpki-roots"]
|
||||
# TLS via Rustls v0.22
|
||||
# TLS via Rustls v0.23
|
||||
rustls-0_23 = ["tls-rustls-0_23", "actix-http/rustls-0_23", "awc/rustls-0_23-webpki-roots"]
|
||||
|
||||
# TLS via OpenSSL
|
||||
|
|
|
@ -52,7 +52,7 @@ use actix_web::{
|
|||
rt::{self, System},
|
||||
web, Error,
|
||||
};
|
||||
use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector};
|
||||
pub use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector};
|
||||
use futures_core::Stream;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
|
@ -583,7 +583,7 @@ impl TestServerConfig {
|
|||
self
|
||||
}
|
||||
|
||||
/// Accepts secure connections via Rustls v0.22.
|
||||
/// Accepts secure connections via Rustls v0.23.
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub fn rustls_0_23(mut self, config: tls_rustls_0_23::ServerConfig) -> Self {
|
||||
self.stream = StreamType::Rustls023(config);
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
### Added
|
||||
|
||||
- Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size.
|
||||
- Add `rustls-0_23` crate feature.
|
||||
- Add `HttpServer::{bind_rustls_0_23, listen_rustls_0_23}()` builder methods.
|
||||
- Add `HttpServer::tls_handshake_timeout()` builder method for `rustls-0_22` and `rustls-0_23`.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ features = [
|
|||
"rustls-0_20",
|
||||
"rustls-0_21",
|
||||
"rustls-0_22",
|
||||
"rustls-0_23",
|
||||
"compress-brotli",
|
||||
"compress-gzip",
|
||||
"compress-zstd",
|
||||
|
@ -71,6 +72,8 @@ rustls-0_20 = ["http2", "actix-http/rustls-0_20", "actix-tls/accept", "actix-tls
|
|||
rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"]
|
||||
# TLS via Rustls v0.22
|
||||
rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"]
|
||||
# TLS via Rustls v0.23
|
||||
rustls-0_23 = ["http2", "actix-http/rustls-0_23", "actix-tls/accept", "actix-tls/rustls-0_23"]
|
||||
|
||||
# Full unicode support
|
||||
unicode = ["dep:regex", "actix-router/unicode"]
|
||||
|
@ -122,7 +125,7 @@ url = "2.1"
|
|||
|
||||
[dev-dependencies]
|
||||
actix-files = "0.6"
|
||||
actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] }
|
||||
actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] }
|
||||
awc = { version = "3", features = ["openssl"] }
|
||||
|
||||
brotli = "6"
|
||||
|
@ -137,7 +140,7 @@ rustls-pemfile = "2"
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
static_assertions = "1"
|
||||
tls-openssl = { package = "openssl", version = "0.10.55" }
|
||||
tls-rustls = { package = "rustls", version = "0.22" }
|
||||
tls-rustls = { package = "rustls", version = "0.23" }
|
||||
tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] }
|
||||
zstd = "0.13"
|
||||
|
||||
|
|
|
@ -64,7 +64,10 @@
|
|||
//! - `compress-gzip` - gzip and deflate content encoding compression support (enabled by default)
|
||||
//! - `compress-zstd` - zstd content encoding compression support (enabled by default)
|
||||
//! - `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2`
|
||||
//! - `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
|
||||
//! - `rustls` - HTTPS support via `rustls` 0.20 crate, supports `HTTP/2`
|
||||
//! - `rustls-0_21` - HTTPS support via `rustls` 0.21 crate, supports `HTTP/2`
|
||||
//! - `rustls-0_22` - HTTPS support via `rustls` 0.22 crate, supports `HTTP/2`
|
||||
//! - `rustls-0_23` - HTTPS support via `rustls` 0.23 crate, supports `HTTP/2`
|
||||
//! - `secure-cookies` - secure cookies support
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::{
|
|||
feature = "rustls-0_20",
|
||||
feature = "rustls-0_21",
|
||||
feature = "rustls-0_22",
|
||||
feature = "rustls-0_23",
|
||||
))]
|
||||
use actix_http::TlsAcceptorConfig;
|
||||
use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
|
||||
|
@ -242,7 +243,13 @@ where
|
|||
/// time, the connection is closed.
|
||||
///
|
||||
/// By default, the handshake timeout is 3 seconds.
|
||||
#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))]
|
||||
#[cfg(any(
|
||||
feature = "openssl",
|
||||
feature = "rustls-0_20",
|
||||
feature = "rustls-0_21",
|
||||
feature = "rustls-0_22",
|
||||
feature = "rustls-0_23",
|
||||
))]
|
||||
pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
|
||||
self.config
|
||||
.lock()
|
||||
|
@ -270,6 +277,10 @@ where
|
|||
/// Rustls v0.20.
|
||||
/// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using
|
||||
/// Rustls v0.21.
|
||||
/// - `actix_tls::accept::rustls_0_22::TlsStream<actix_web::rt::net::TcpStream>` when using
|
||||
/// Rustls v0.22.
|
||||
/// - `actix_tls::accept::rustls_0_23::TlsStream<actix_web::rt::net::TcpStream>` when using
|
||||
/// Rustls v0.23.
|
||||
/// - `actix_web::rt::net::TcpStream` when no encryption is used.
|
||||
///
|
||||
/// See the `on_connect` example for additional details.
|
||||
|
@ -466,6 +477,25 @@ where
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
/// Resolves socket address(es) and binds server to created listener(s) for TLS connections
|
||||
/// using Rustls v0.23.
|
||||
///
|
||||
/// See [`bind()`](Self::bind()) for more details on `addrs` argument.
|
||||
///
|
||||
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
|
||||
mut self,
|
||||
addrs: A,
|
||||
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
|
||||
) -> io::Result<Self> {
|
||||
let sockets = bind_addrs(addrs, self.backlog)?;
|
||||
for lst in sockets {
|
||||
self = self.listen_rustls_0_23_inner(lst, config.clone())?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Resolves socket address(es) and binds server to created listener(s) for TLS connections
|
||||
/// using OpenSSL.
|
||||
///
|
||||
|
@ -595,7 +625,7 @@ where
|
|||
/// Binds to existing listener for accepting incoming TLS connection requests using Rustls
|
||||
/// v0.21.
|
||||
///
|
||||
/// See [`listen()`](Self::listen) for more details on the `lst` argument.
|
||||
/// See [`listen()`](Self::listen()) for more details on the `lst` argument.
|
||||
///
|
||||
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
|
||||
#[cfg(feature = "rustls-0_21")]
|
||||
|
@ -712,7 +742,7 @@ where
|
|||
/// Binds to existing listener for accepting incoming TLS connection requests using Rustls
|
||||
/// v0.22.
|
||||
///
|
||||
/// See [`listen()`](Self::listen) for more details on the `lst` argument.
|
||||
/// See [`listen()`](Self::listen()) for more details on the `lst` argument.
|
||||
///
|
||||
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
|
||||
#[cfg(feature = "rustls-0_22")]
|
||||
|
@ -775,6 +805,72 @@ where
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds to existing listener for accepting incoming TLS connection requests using Rustls
|
||||
/// v0.23.
|
||||
///
|
||||
/// See [`listen()`](Self::listen()) for more details on the `lst` argument.
|
||||
///
|
||||
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub fn listen_rustls_0_23(
|
||||
self,
|
||||
lst: net::TcpListener,
|
||||
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
|
||||
) -> io::Result<Self> {
|
||||
self.listen_rustls_0_23_inner(lst, config)
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
fn listen_rustls_0_23_inner(
|
||||
mut self,
|
||||
lst: net::TcpListener,
|
||||
config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
|
||||
) -> io::Result<Self> {
|
||||
let factory = self.factory.clone();
|
||||
let cfg = self.config.clone();
|
||||
let addr = lst.local_addr().unwrap();
|
||||
self.sockets.push(Socket {
|
||||
addr,
|
||||
scheme: "https",
|
||||
});
|
||||
|
||||
let on_connect_fn = self.on_connect_fn.clone();
|
||||
|
||||
self.builder =
|
||||
self.builder
|
||||
.listen(format!("actix-web-service-{}", addr), lst, move || {
|
||||
let c = cfg.lock().unwrap();
|
||||
let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
|
||||
|
||||
let svc = HttpService::build()
|
||||
.keep_alive(c.keep_alive)
|
||||
.client_request_timeout(c.client_request_timeout)
|
||||
.client_disconnect_timeout(c.client_disconnect_timeout);
|
||||
|
||||
let svc = if let Some(handler) = on_connect_fn.clone() {
|
||||
svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
|
||||
} else {
|
||||
svc
|
||||
};
|
||||
|
||||
let fac = factory()
|
||||
.into_factory()
|
||||
.map_err(|err| err.into().error_response());
|
||||
|
||||
let acceptor_config = match c.tls_handshake_timeout {
|
||||
Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
|
||||
None => TlsAcceptorConfig::default(),
|
||||
};
|
||||
|
||||
svc.finish(map_config(fac, move |_| {
|
||||
AppConfig::new(true, host.clone(), addr)
|
||||
}))
|
||||
.rustls_0_23_with_config(config.clone(), acceptor_config)
|
||||
})?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL.
|
||||
///
|
||||
/// See [`listen()`](Self::listen) for more details on the `lst` argument.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(feature = "openssl")]
|
||||
extern crate tls_openssl as openssl;
|
||||
#[cfg(feature = "rustls-0_22")]
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
extern crate tls_rustls as rustls;
|
||||
|
||||
use std::{
|
||||
|
@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() {
|
|||
srv.stop().await;
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-0_22")]
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
mod plus_rustls {
|
||||
use std::io::BufReader;
|
||||
|
||||
|
@ -740,7 +740,7 @@ mod plus_rustls {
|
|||
.map(char::from)
|
||||
.collect::<String>();
|
||||
|
||||
let srv = actix_test::start_with(actix_test::config().rustls_0_22(tls_config()), || {
|
||||
let srv = actix_test::start_with(actix_test::config().rustls_0_23(tls_config()), || {
|
||||
App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async {
|
||||
// echo decompressed request body back in response
|
||||
HttpResponse::Ok()
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features.
|
||||
- Add `awc::Connector::rustls_0_23()` constructor.
|
||||
- Fix `rustls-0_22-native-roots` root store lookup
|
||||
- Update `brotli` dependency to `6`.
|
||||
- Minimum supported Rust version (MSRV) is now 1.72.
|
||||
- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features.
|
||||
|
|
|
@ -42,7 +42,7 @@ impl ClientBuilder {
|
|||
/// Note: If the `rustls-0_23` feature is enabled and neither `rustls-0_23-native-roots` nor
|
||||
/// `rustls-0_23-webpki-roots` are enabled, this ClientBuilder will build without TLS. In order
|
||||
/// to enable TLS in this scenario, a custom `Connector` _must_ be added to the builder before
|
||||
/// finishing constrution.
|
||||
/// finishing construction.
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new() -> ClientBuilder<
|
||||
impl Service<
|
||||
|
|
|
@ -86,9 +86,10 @@ pub struct Connector<T> {
|
|||
impl Connector<()> {
|
||||
/// Create a new connector with default TLS settings
|
||||
///
|
||||
/// Panicking:
|
||||
/// # Panics
|
||||
///
|
||||
/// - When the `rustls-0_23-webpki-roots` or `rustls-0_23-native-roots` features are enabled
|
||||
/// and no default cyrpto provider has been loaded, this method will panic.
|
||||
/// and no default crypto provider has been loaded, this method will panic.
|
||||
/// - When the `rustls-0_23-native-roots` or `rustls-0_22-native-roots` features are enabled
|
||||
/// and the runtime system has no native root certificates, this method will panic.
|
||||
#[allow(clippy::new_ret_no_self, clippy::let_unit_value)]
|
||||
|
@ -200,8 +201,8 @@ impl Connector<()> {
|
|||
OurTlsConnector::OpensslBuilder(ssl)
|
||||
}
|
||||
} else {
|
||||
/// Provides an empty TLS connector when no TLS feature is enabled, or when
|
||||
/// rustls-0_23 is enabled.
|
||||
/// Provides an empty TLS connector when no TLS feature is enabled, or when only the
|
||||
/// `rustls-0_23` crate feature is enabled.
|
||||
fn build_tls(_: Vec<Vec<u8>>) -> OurTlsConnector {
|
||||
OurTlsConnector::None
|
||||
}
|
||||
|
@ -316,8 +317,10 @@ where
|
|||
///
|
||||
/// In order to enable ALPN, set the `.alpn_protocols` field on the ClientConfig to the
|
||||
/// following:
|
||||
/// ```rust,ignore
|
||||
///
|
||||
/// ```no_run
|
||||
/// vec![b"h2".to_vec(), b"http/1.1".to_vec()]
|
||||
/// # ;
|
||||
/// ```
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub fn rustls_0_23(
|
||||
|
|
Loading…
Reference in New Issue