diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3e62958d8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Gitter channel (actix-web) + url: https://gitter.im/actix/actix-web + about: Please ask and answer questions about the actix-web here. + - name: Gitter channel (actix) + url: https://gitter.im/actix/actix + about: Please ask and answer questions about the actix here. diff --git a/CHANGES.md b/CHANGES.md index d5f36a9cb..739f1b13c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [Unreleased] +## [3.0.0-alpha.3] - 2020-05-21 ### Added diff --git a/Cargo.toml b/Cargo.toml index a7b6e70d6..74aa284e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "3.0.0-alpha.2" +version = "3.0.0-alpha.3" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -77,9 +77,9 @@ actix-macros = "0.1.0" actix-threadpool = "0.3.1" actix-tls = "2.0.0-alpha.1" -actix-web-codegen = "0.2.0" -actix-http = "2.0.0-alpha.3" -awc = { version = "2.0.0-alpha.1", default-features = false } +actix-web-codegen = "0.2.2" +actix-http = "2.0.0-alpha.4" +awc = { version = "2.0.0-alpha.2", default-features = false } bytes = "0.5.3" derive_more = "0.99.2" diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 22c98d7c5..abf143997 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,9 +1,13 @@ # Changes -## [Unreleased] - 2020-xx-xx +## [0.3.0-alpha.1] - 2020-05-23 +* Update `actix-web` and `actix-http` dependencies to alpha +* Fix some typos in the docs * Bump minimum supported Rust version to 1.40 -* Support sending Content-Length when Content-Range is specified #1384 +* Support sending Content-Length when Content-Range is specified [#1384] + +[#1384]: https://github.com/actix/actix-web/pull/1384 ## [0.2.1] - 2019-12-22 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index ead2b51f5..356c7a413 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.2.1" +version = "0.3.0-alpha.1" authors = ["Nikolay Kim "] description = "Static files support for actix web." readme = "README.md" @@ -18,8 +18,8 @@ name = "actix_files" path = "src/lib.rs" [dependencies] -actix-web = { version = "3.0.0-alpha.2", default-features = false } -actix-http = "2.0.0-alpha.3" +actix-web = { version = "3.0.0-alpha.3", default-features = false } +actix-http = "2.0.0-alpha.4" actix-service = "1.0.1" bitflags = "1" bytes = "0.5.3" @@ -34,4 +34,4 @@ v_htmlescape = "0.4" [dev-dependencies] actix-rt = "1.0.0" -actix-web = { version = "3.0.0-alpha.2", features = ["openssl"] } +actix-web = { version = "3.0.0-alpha.3", features = ["openssl"] } diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index ba7a01e0c..494dd6f42 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -23,7 +23,7 @@ actix-codec = "0.2.0" actix-service = "1.0.1" actix-router = "0.2.1" actix-rt = "1.0.0" -actix-http = "2.0.0-alpha.3" +actix-http = "2.0.0-alpha.4" bytes = "0.5.3" futures-util = { version = "0.3.5", default-features = false } @@ -32,6 +32,6 @@ log = "0.4" [dev-dependencies] actix-server = "1.0.0" -actix-connect = { version = "2.0.0-alpha.2", features=["openssl"] } -actix-http-test = { version = "1.0.0", features=["openssl"] } +actix-connect = { version = "2.0.0-alpha.2", features = ["openssl"] } +actix-http-test = { version = "2.0.0-alpha.1", features = ["openssl"] } actix-utils = "1.0.3" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 636c9e330..c19e40e4c 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [Unreleased] +## [2.0.0-alpha.4] - 2020-05-21 ### Changed diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 3ddc5181c..edd8201d5 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "2.0.0-alpha.3" +version = "2.0.0-alpha.4" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" @@ -64,6 +64,7 @@ h2 = "0.2.1" http = "0.2.0" httparse = "1.3" indexmap = "1.3" +itoa = "0.4" lazy_static = "1.4" language-tags = "0.2" log = "0.4" @@ -89,7 +90,7 @@ flate2 = { version = "1.0.13", optional = true } [dev-dependencies] actix-server = "1.0.1" actix-connect = { version = "2.0.0-alpha.2", features = ["openssl"] } -actix-http-test = { version = "1.0.0", features = ["openssl"] } +actix-http-test = { version = "2.0.0-alpha.1", features = ["openssl"] } actix-tls = { version = "2.0.0-alpha.1", features = ["openssl"] } criterion = "0.3" env_logger = "0.7" diff --git a/actix-http/benches/content-length.rs b/actix-http/benches/content-length.rs index b001b3931..18a55a33b 100644 --- a/actix-http/benches/content-length.rs +++ b/actix-http/benches/content-length.rs @@ -25,6 +25,13 @@ fn bench_write_content_length(c: &mut Criterion) { _new::write_content_length(i, &mut b) }) }); + + group.bench_with_input(BenchmarkId::new("itoa", i), i, |b, &i| { + b.iter(|| { + let mut b = BytesMut::with_capacity(35); + _itoa::write_content_length(i, &mut b) + }) + }); } group.finish(); @@ -33,6 +40,23 @@ fn bench_write_content_length(c: &mut Criterion) { criterion_group!(benches, bench_write_content_length); criterion_main!(benches); +mod _itoa { + use bytes::{BufMut, BytesMut}; + + pub fn write_content_length(n: usize, bytes: &mut BytesMut) { + if n == 0 { + bytes.put_slice(b"\r\ncontent-length: 0\r\n"); + return; + } + + let mut buf = itoa::Buffer::new(); + + bytes.put_slice(b"\r\ncontent-length: "); + bytes.put_slice(buf.format(n).as_bytes()); + bytes.put_slice(b"\r\n"); + } +} + mod _new { use bytes::{BufMut, BytesMut}; diff --git a/actix-http/src/helpers.rs b/actix-http/src/helpers.rs index 5ac6c9be5..bbf358b66 100644 --- a/actix-http/src/helpers.rs +++ b/actix-http/src/helpers.rs @@ -31,103 +31,18 @@ pub(crate) fn write_status_line(version: Version, n: u16, bytes: &mut BytesMut) /// NOTE: bytes object has to contain enough space pub fn write_content_length(n: u64, bytes: &mut BytesMut) { + if n == 0 { + bytes.put_slice(b"\r\ncontent-length: 0\r\n"); + return; + } + + let mut buf = itoa::Buffer::new(); + bytes.put_slice(b"\r\ncontent-length: "); - - if n < 10 { - bytes.put_u8(DIGITS_START + (n as u8)); - } else if n < 100 { - let n = n as u8; - - let d10 = n / 10; - let d1 = n % 10; - - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - } else if n < 1000 { - let n = n as u16; - - let d100 = (n / 100) as u8; - let d10 = ((n / 10) % 10) as u8; - let d1 = (n % 10) as u8; - - bytes.put_u8(DIGITS_START + d100); - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - } else if n < 10_000 { - let n = n as u16; - - let d1000 = (n / 1000) as u8; - let d100 = ((n / 100) % 10) as u8; - let d10 = ((n / 10) % 10) as u8; - let d1 = (n % 10) as u8; - - bytes.put_u8(DIGITS_START + d1000); - bytes.put_u8(DIGITS_START + d100); - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - } else if n < 100_000 { - let n = n as u32; - - let d10000 = (n / 10000) as u8; - let d1000 = ((n / 1000) % 10) as u8; - let d100 = ((n / 100) % 10) as u8; - let d10 = ((n / 10) % 10) as u8; - let d1 = (n % 10) as u8; - - bytes.put_u8(DIGITS_START + d10000); - bytes.put_u8(DIGITS_START + d1000); - bytes.put_u8(DIGITS_START + d100); - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - } else if n < 1_000_000 { - let n = n as u32; - - let d100000 = (n / 100_000) as u8; - let d10000 = ((n / 10000) % 10) as u8; - let d1000 = ((n / 1000) % 10) as u8; - let d100 = ((n / 100) % 10) as u8; - let d10 = ((n / 10) % 10) as u8; - let d1 = (n % 10) as u8; - - bytes.put_u8(DIGITS_START + d100000); - bytes.put_u8(DIGITS_START + d10000); - bytes.put_u8(DIGITS_START + d1000); - bytes.put_u8(DIGITS_START + d100); - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - } else { - write_u64(n, bytes); - } - + bytes.put_slice(buf.format(n).as_bytes()); bytes.put_slice(b"\r\n"); } -pub(crate) fn write_u64(n: u64, bytes: &mut BytesMut) { - let mut n = n; - - // 20 chars is max length of a u64 (2^64) - // digits will be added to the buffer from lsd to msd - let mut buf = BytesMut::with_capacity(20); - - while n > 9 { - // "pop" the least-significant digit - let lsd = (n % 10) as u8; - - // remove the lsd from n - n /= 10; - - buf.put_u8(DIGITS_START + lsd); - } - - // put msd to result buffer - bytes.put_u8(DIGITS_START + (n as u8)); - - // put, in reverse (msd to lsd), remaining digits to buffer - for i in (0..buf.len()).rev() { - bytes.put_u8(buf[i]); - } -} - pub(crate) struct Writer<'a>(pub &'a mut BytesMut); impl<'a> io::Write for Writer<'a> { diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 2fed60d33..e12c07bf1 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -16,7 +16,7 @@ name = "actix_multipart" path = "src/lib.rs" [dependencies] -actix-web = { version = "3.0.0-alpha.2", default-features = false } +actix-web = { version = "3.0.0-alpha.3", default-features = false } actix-service = "1.0.1" actix-utils = "1.0.3" bytes = "0.5.3" @@ -29,4 +29,4 @@ twoway = "0.2" [dev-dependencies] actix-rt = "1.0.0" -actix-http = "2.0.0-alpha.3" +actix-http = "2.0.0-alpha.4" diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index b62616958..20fd3743d 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -17,8 +17,8 @@ path = "src/lib.rs" [dependencies] actix = "0.10.0-alpha.2" -actix-web = "3.0.0-alpha.2" -actix-http = "2.0.0-alpha.3" +actix-web = "3.0.0-alpha.3" +actix-http = "2.0.0-alpha.4" actix-codec = "0.2.0" bytes = "0.5.2" futures-channel = { version = "0.3.5", default-features = false } diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index da2faee38..b2e80591f 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,8 +1,10 @@ # Changes -## [Unreleased] - 2020-xx-xx +## [0.2.2] - 2020-05-23 -* Bump minimum supported Rust version to 1.40 +* Add resource middleware on actix-web-codegen [#1467] + +[#1467]: https://github.com/actix/actix-web/pull/1467 ## [0.2.1] - 2020-02-25 diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index c7b06e311..3b2cdad3b 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "0.2.1" +version = "0.2.2" description = "Actix web proc macros" readme = "README.md" authors = ["Nikolay Kim "] @@ -12,11 +12,11 @@ workspace = ".." proc-macro = true [dependencies] -quote = "^1" -syn = { version = "^1", features = ["full", "parsing"] } -proc-macro2 = "^1" +quote = "1" +syn = { version = "1", features = ["full", "parsing"] } +proc-macro2 = "1" [dev-dependencies] actix-rt = "1.0.0" -actix-web = "3.0.0-alpha.2" +actix-web = "3.0.0-alpha.3" futures-util = { version = "0.3.5", default-features = false } diff --git a/awc/CHANGES.md b/awc/CHANGES.md index f501674ee..6d5a81b5e 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [Unreleased] +## [2.0.0-alpha.2] - 2020-05-21 ### Changed diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 894674c90..b36e735ca 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "2.0.0-alpha.1" +version = "2.0.0-alpha.2" authors = ["Nikolay Kim "] description = "Actix http client." readme = "README.md" @@ -36,7 +36,7 @@ compress = ["actix-http/compress"] [dependencies] actix-codec = "0.2.0" actix-service = "1.0.1" -actix-http = "2.0.0-alpha.3" +actix-http = "2.0.0-alpha.4" actix-rt = "1.0.0" base64 = "0.12" @@ -55,9 +55,9 @@ rust-tls = { version = "0.17.0", package = "rustls", optional = true, features = [dev-dependencies] actix-connect = { version = "2.0.0-alpha.2", features = ["openssl"] } -actix-web = { version = "3.0.0-alpha.2", features = ["openssl"] } -actix-http = { version = "2.0.0-alpha.3", features = ["openssl"] } -actix-http-test = { version = "1.0.0", features = ["openssl"] } +actix-web = { version = "3.0.0-alpha.3", features = ["openssl"] } +actix-http = { version = "2.0.0-alpha.4", features = ["openssl"] } +actix-http-test = { version = "2.0.0-alpha.1", features = ["openssl"] } actix-utils = "1.0.3" actix-server = "1.0.0" actix-tls = { version = "2.0.0-alpha.1", features = ["openssl", "rustls"] } diff --git a/src/app.rs b/src/app.rs index 9e38f5bc9..8178d57fe 100644 --- a/src/app.rs +++ b/src/app.rs @@ -474,13 +474,15 @@ where mod tests { use actix_service::Service; use bytes::Bytes; - use futures_util::future::{ok, err}; + use futures_util::future::{err, ok}; use super::*; use crate::http::{header, HeaderValue, Method, StatusCode}; use crate::middleware::DefaultHeaders; use crate::service::ServiceRequest; - use crate::test::{call_service, init_service, try_init_service, read_body, TestRequest}; + use crate::test::{ + call_service, init_service, read_body, try_init_service, TestRequest, + }; use crate::{web, HttpRequest, HttpResponse}; #[actix_rt::test] @@ -556,7 +558,7 @@ mod tests { web::resource("/").to(|_: web::Data| HttpResponse::Ok()), )) .await; - + assert!(srv.is_err()); } diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index e63efc832..8b881c0a4 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -273,13 +273,15 @@ impl PinnedDrop for StreamLog { } } - impl MessageBody for StreamLog { fn size(&self) -> BodySize { self.body.size() } - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { + fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { let this = self.project(); match this.body.poll_next(cx) { Poll::Ready(Some(Ok(chunk))) => { @@ -324,11 +326,13 @@ impl Format { if let Some(key) = cap.get(2) { results.push(match cap.get(3).unwrap().as_str() { - "a" => if key.as_str() == "r" { - FormatText::RealIPRemoteAddr - } else { - unreachable!() - }, + "a" => { + if key.as_str() == "r" { + FormatText::RealIPRemoteAddr + } else { + unreachable!() + } + } "i" => FormatText::RequestHeader( HeaderName::try_from(key.as_str()).unwrap(), ), @@ -481,7 +485,8 @@ impl FormatText { *self = s; } FormatText::RealIPRemoteAddr => { - let s = if let Some(remote) = req.connection_info().realip_remote_addr() { + let s = if let Some(remote) = req.connection_info().realip_remote_addr() + { FormatText::Str(remote.to_string()) } else { FormatText::Str("-".to_string()) @@ -630,7 +635,9 @@ mod tests { let req = TestRequest::with_header( header::FORWARDED, - header::HeaderValue::from_static("for=192.0.2.60;proto=http;by=203.0.113.43"), + header::HeaderValue::from_static( + "for=192.0.2.60;proto=http;by=203.0.113.43", + ), ) .to_srv_request(); diff --git a/src/middleware/normalize.rs b/src/middleware/normalize.rs index 139ec892e..d23f03445 100644 --- a/src/middleware/normalize.rs +++ b/src/middleware/normalize.rs @@ -74,7 +74,7 @@ where fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let head = req.head_mut(); - + // always add trailing slash, might be an extra one let path = head.uri.path().to_string() + "/"; let original_len = path.len(); @@ -177,7 +177,7 @@ mod tests { assert!(res.status().is_success()); } - #[actix_rt::test] + #[actix_rt::test] async fn should_normalize_nothing_notrail() { const URI: &str = "/v1/something"; diff --git a/src/route.rs b/src/route.rs index 8da9aec1b..2763f3b1a 100644 --- a/src/route.rs +++ b/src/route.rs @@ -362,31 +362,23 @@ mod tests { .service( web::resource("/test") .route(web::get().to(|| HttpResponse::Ok())) - .route(web::put().to(|| { - async { - Err::(error::ErrorBadRequest("err")) - } + .route(web::put().to(|| async { + Err::(error::ErrorBadRequest("err")) })) - .route(web::post().to(|| { - async { - delay_for(Duration::from_millis(100)).await; - HttpResponse::Created() - } + .route(web::post().to(|| async { + delay_for(Duration::from_millis(100)).await; + HttpResponse::Created() })) - .route(web::delete().to(|| { - async { - delay_for(Duration::from_millis(100)).await; - Err::(error::ErrorBadRequest("err")) - } + .route(web::delete().to(|| async { + delay_for(Duration::from_millis(100)).await; + Err::(error::ErrorBadRequest("err")) })), ) - .service(web::resource("/json").route(web::get().to(|| { - async { - delay_for(Duration::from_millis(25)).await; - web::Json(MyObject { - name: "test".to_string(), - }) - } + .service(web::resource("/json").route(web::get().to(|| async { + delay_for(Duration::from_millis(25)).await; + web::Json(MyObject { + name: "test".to_string(), + }) }))), ) .await; diff --git a/src/test.rs b/src/test.rs index 684e9c116..a64ec3a73 100644 --- a/src/test.rs +++ b/src/test.rs @@ -89,7 +89,9 @@ where >, S::InitError: std::fmt::Debug, { - try_init_service(app).await.expect("service initilization failed") + try_init_service(app) + .await + .expect("service initilization failed") } /// Fallible version of init_service that allows testing data factory errors. @@ -913,7 +915,8 @@ impl TestServerConfig { /// Get first available unused address pub fn unused_addr() -> net::SocketAddr { let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap(); - let socket = Socket::new(Domain::ipv4(), Type::stream(), Some(Protocol::tcp())).unwrap(); + let socket = + Socket::new(Domain::ipv4(), Type::stream(), Some(Protocol::tcp())).unwrap(); socket.bind(&addr.into()).unwrap(); socket.set_reuse_address(true).unwrap(); let tcp = socket.into_tcp_listener(); diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index e97ee5d6f..079cad74a 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [Unreleased] - 2020-xx-xx +## [2.0.0-alpha.1] - 2020-05-23 * Update the `time` dependency to 0.2.7 * Update `actix-connect` dependency to 2.0.0-alpha.2 diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index f4b02353c..8a8c0c8f0 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "1.0.0" +version = "2.0.0-alpha.1" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -37,7 +37,7 @@ actix-utils = "1.0.3" actix-rt = "1.0.0" actix-server = "1.0.0" actix-testing = "1.0.0" -awc = "2.0.0-alpha.1" +awc = "2.0.0-alpha.2" base64 = "0.12" bytes = "0.5.3" @@ -55,5 +55,5 @@ time = { version = "0.2.7", default-features = false, features = ["std"] } open-ssl = { version = "0.10", package = "openssl", optional = true } [dev-dependencies] -actix-web = "3.0.0-alpha.2" -actix-http = "2.0.0-alpha.3" +actix-web = "3.0.0-alpha.3" +actix-http = "2.0.0-alpha.4" diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 265d9a771..f6c1183b4 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -104,7 +104,8 @@ pub async fn test_server>(factory: F) -> TestServer /// Get first available unused address pub fn unused_addr() -> net::SocketAddr { let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap(); - let socket = Socket::new(Domain::ipv4(), Type::stream(), Some(Protocol::tcp())).unwrap(); + let socket = + Socket::new(Domain::ipv4(), Type::stream(), Some(Protocol::tcp())).unwrap(); socket.bind(&addr.into()).unwrap(); socket.set_reuse_address(true).unwrap(); let tcp = socket.into_tcp_listener(); diff --git a/tests/test_server.rs b/tests/test_server.rs index 926b211ee..0ac4b0232 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -349,9 +349,10 @@ async fn test_body_br_streaming() { #[actix_rt::test] async fn test_head_binary() { let srv = test::start_with(test::config().h1(), || { - App::new().service(web::resource("/").route( - web::head().to(move || HttpResponse::Ok().body(STR)), - )) + App::new().service( + web::resource("/") + .route(web::head().to(move || HttpResponse::Ok().body(STR))), + ) }); let mut response = srv.head("/").send().await.unwrap();