"]
description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust"
readme = "README.md"
diff --git a/README.md b/README.md
index b11a8ee7c..c1d857f81 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,10 @@
[](https://crates.io/crates/actix-web)
-[](https://docs.rs/actix-web/3.2.0)
+[](https://docs.rs/actix-web/3.3.0)
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)

-[](https://deps.rs/crate/actix-web/3.2.0)
+[](https://deps.rs/crate/actix-web/3.3.0)
[](https://travis-ci.org/actix/actix-web)
[](https://codecov.io/gh/actix/actix-web)
diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md
index 978d1c69d..c4d56010f 100644
--- a/actix-files/CHANGES.md
+++ b/actix-files/CHANGES.md
@@ -3,6 +3,10 @@
## Unreleased - 2020-xx-xx
+## 0.4.1 - 2020-11-24
+* Clarify order of parameters in `Files::new` and improve docs.
+
+
## 0.4.0 - 2020-10-06
* Add `Files::prefer_utf8` option that adds UTF-8 charset on certain response types. [#1714]
diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml
index c829887ba..f7d32f8ec 100644
--- a/actix-files/Cargo.toml
+++ b/actix-files/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "actix-files"
-version = "0.4.0"
+version = "0.4.1"
authors = ["Nikolay Kim "]
description = "Static file serving for Actix Web"
readme = "README.md"
@@ -21,14 +21,14 @@ actix-web = { version = "3.0.0", default-features = false }
actix-service = "1.0.6"
bitflags = "1"
bytes = "0.5.3"
-futures-core = { version = "0.3.5", default-features = false }
-futures-util = { version = "0.3.5", default-features = false }
+futures-core = { version = "0.3.7", default-features = false }
+futures-util = { version = "0.3.7", default-features = false }
derive_more = "0.99.2"
log = "0.4"
mime = "0.3"
mime_guess = "2.0.1"
percent-encoding = "2.1"
-v_htmlescape = "0.10"
+v_htmlescape = "0.11"
[dev-dependencies]
actix-rt = "1.0.0"
diff --git a/actix-files/README.md b/actix-files/README.md
index d31439361..685e5dbe5 100644
--- a/actix-files/README.md
+++ b/actix-files/README.md
@@ -2,12 +2,12 @@
> Static file serving for Actix Web
-[](https://crates.io/crates/actix-files)
-[](https://docs.rs/actix-files)
+[](https://crates.io/crates/actix-files)
+[](https://docs.rs/actix-files/0.4.1)
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)

-[](https://deps.rs/crate/actix-files/0.4.0)
+[](https://deps.rs/crate/actix-files/0.4.1)
[](https://crates.io/crates/actix-files)
[](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs
index 5a783e2dd..a99b4699e 100644
--- a/actix-files/src/files.rs
+++ b/actix-files/src/files.rs
@@ -65,13 +65,25 @@ impl Clone for Files {
}
impl Files {
- /// Create new `Files` instance for specified base directory.
+ /// Create new `Files` instance for a specified base directory.
///
- /// `File` uses `ThreadPool` for blocking filesystem operations.
- /// By default pool with 5x threads of available cpus is used.
- /// Pool size can be changed by setting ACTIX_THREADPOOL environment variable.
- pub fn new>(path: &str, dir: T) -> Files {
- let orig_dir = dir.into();
+ /// # Argument Order
+ /// The first argument (`mount_path`) is the root URL at which the static files are served.
+ /// For example, `/assets` will serve files at `example.com/assets/...`.
+ ///
+ /// The second argument (`serve_from`) is the location on disk at which files are loaded.
+ /// This can be a relative path. For example, `./` would serve files from the current
+ /// working directory.
+ ///
+ /// # Implementation Notes
+ /// If the mount path is set as the root path `/`, services registered after this one will
+ /// be inaccessible. Register more specific handlers and services first.
+ ///
+ /// `Files` uses a threadpool for blocking filesystem operations. By default, the pool uses a
+ /// number of threads equal to 5x the number of available logical CPUs. Pool size can be changed
+ /// by setting ACTIX_THREADPOOL environment variable.
+ pub fn new>(mount_path: &str, serve_from: T) -> Files {
+ let orig_dir = serve_from.into();
let dir = match orig_dir.canonicalize() {
Ok(canon_dir) => canon_dir,
Err(_) => {
@@ -81,7 +93,7 @@ impl Files {
};
Files {
- path: path.to_string(),
+ path: mount_path.to_owned(),
directory: dir,
index: None,
show_index: false,
diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index eeed4e14b..c602ab2e1 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -1,17 +1,25 @@
# Changes
## Unreleased - 2020-xx-xx
+
+
+## 2.2.0 - 2020-11-25
### Added
* HttpResponse builders for 1xx status codes. [#1768]
+* `Accept::mime_precedence` and `Accept::mime_preference`. [#1793]
+* `TryFrom` and `TryFrom` for `http::header::Quality`. [#1797]
### Fixed
* Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767]
### Changed
-* Upgrade `serde_urlencoded` to `0.7`.
+* Upgrade `serde_urlencoded` to `0.7`. [#1773]
+[#1773]: https://github.com/actix/actix-web/pull/1773
[#1767]: https://github.com/actix/actix-web/pull/1767
[#1768]: https://github.com/actix/actix-web/pull/1768
+[#1793]: https://github.com/actix/actix-web/pull/1793
+[#1797]: https://github.com/actix/actix-web/pull/1797
## 2.1.0 - 2020-10-30
diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml
index 31495e395..7375c6eb3 100644
--- a/actix-http/Cargo.toml
+++ b/actix-http/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "actix-http"
-version = "2.1.0"
+version = "2.2.0"
authors = ["Nikolay Kim "]
description = "HTTP primitives for the Actix ecosystem"
readme = "README.md"
diff --git a/actix-http/README.md b/actix-http/README.md
index e536276ca..9103cd184 100644
--- a/actix-http/README.md
+++ b/actix-http/README.md
@@ -3,14 +3,14 @@
> HTTP primitives for the Actix ecosystem.
[](https://crates.io/crates/actix-http)
-[](https://docs.rs/actix-http/2.1.0)
+[](https://docs.rs/actix-http/2.2.0)

-[](https://deps.rs/crate/actix-http/2.1.0)
+[](https://deps.rs/crate/actix-http/2.2.0)
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Documentation & Resources
-- [API Documentation](https://docs.rs/actix-http/2.1.0)
+- [API Documentation](https://docs.rs/actix-http)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum Supported Rust Version (MSRV): 1.42.0
diff --git a/actix-http/src/header/common/accept.rs b/actix-http/src/header/common/accept.rs
index d52eba241..da26b0261 100644
--- a/actix-http/src/header/common/accept.rs
+++ b/actix-http/src/header/common/accept.rs
@@ -1,3 +1,5 @@
+use std::cmp::Ordering;
+
use mime::Mime;
use crate::header::{qitem, QualityItem};
@@ -7,7 +9,7 @@ header! {
/// `Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2)
///
/// The `Accept` header field can be used by user agents to specify
- /// response media types that are acceptable. Accept header fields can
+ /// response media types that are acceptable. Accept header fields can
/// be used to indicate that the request is specifically limited to a
/// small set of desired types, as in the case of a request for an
/// in-line image
@@ -97,14 +99,14 @@ header! {
test_header!(
test1,
vec![b"audio/*; q=0.2, audio/basic"],
- Some(HeaderField(vec![
+ Some(Accept(vec![
QualityItem::new("audio/*".parse().unwrap(), q(200)),
qitem("audio/basic".parse().unwrap()),
])));
test_header!(
test2,
vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
- Some(HeaderField(vec![
+ Some(Accept(vec![
QualityItem::new(mime::TEXT_PLAIN, q(500)),
qitem(mime::TEXT_HTML),
QualityItem::new(
@@ -138,23 +140,148 @@ header! {
}
impl Accept {
- /// A constructor to easily create `Accept: */*`.
+ /// Construct `Accept: */*`.
pub fn star() -> Accept {
Accept(vec![qitem(mime::STAR_STAR)])
}
- /// A constructor to easily create `Accept: application/json`.
+ /// Construct `Accept: application/json`.
pub fn json() -> Accept {
Accept(vec![qitem(mime::APPLICATION_JSON)])
}
- /// A constructor to easily create `Accept: text/*`.
+ /// Construct `Accept: text/*`.
pub fn text() -> Accept {
Accept(vec![qitem(mime::TEXT_STAR)])
}
- /// A constructor to easily create `Accept: image/*`.
+ /// Construct `Accept: image/*`.
pub fn image() -> Accept {
Accept(vec![qitem(mime::IMAGE_STAR)])
}
+
+ /// Construct `Accept: text/html`.
+ pub fn html() -> Accept {
+ Accept(vec![qitem(mime::TEXT_HTML)])
+ }
+
+ /// Returns a sorted list of mime types from highest to lowest preference, accounting for
+ /// [q-factor weighting] and specificity.
+ ///
+ /// [q-factor weighting]: https://tools.ietf.org/html/rfc7231#section-5.3.2
+ pub fn mime_precedence(&self) -> Vec {
+ let mut types = self.0.clone();
+
+ // use stable sort so items with equal q-factor and specificity retain listed order
+ types.sort_by(|a, b| {
+ // sort by q-factor descending
+ b.quality.cmp(&a.quality).then_with(|| {
+ // use specificity rules on mime types with
+ // same q-factor (eg. text/html > text/* > */*)
+
+ // subtypes are not comparable if main type is star, so return
+ match (a.item.type_(), b.item.type_()) {
+ (mime::STAR, mime::STAR) => return Ordering::Equal,
+
+ // a is sorted after b
+ (mime::STAR, _) => return Ordering::Greater,
+
+ // a is sorted before b
+ (_, mime::STAR) => return Ordering::Less,
+
+ _ => {}
+ }
+
+ // in both these match expressions, the returned ordering appears
+ // inverted because sort is high-to-low ("descending") precedence
+ match (a.item.subtype(), b.item.subtype()) {
+ (mime::STAR, mime::STAR) => Ordering::Equal,
+
+ // a is sorted after b
+ (mime::STAR, _) => Ordering::Greater,
+
+ // a is sorted before b
+ (_, mime::STAR) => Ordering::Less,
+
+ _ => Ordering::Equal,
+ }
+ })
+ });
+
+ types.into_iter().map(|qitem| qitem.item).collect()
+ }
+
+ /// Extracts the most preferable mime type, accounting for [q-factor weighting].
+ ///
+ /// If no q-factors are provided, the first mime type is chosen. Note that items without
+ /// q-factors are given the maximum preference value.
+ ///
+ /// Returns `None` if contained list is empty.
+ ///
+ /// [q-factor weighting]: https://tools.ietf.org/html/rfc7231#section-5.3.2
+ pub fn mime_preference(&self) -> Option {
+ let types = self.mime_precedence();
+ types.first().cloned()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::header::q;
+
+ #[test]
+ fn test_mime_precedence() {
+ let test = Accept(vec![]);
+ assert!(test.mime_precedence().is_empty());
+
+ let test = Accept(vec![qitem(mime::APPLICATION_JSON)]);
+ assert_eq!(test.mime_precedence(), vec!(mime::APPLICATION_JSON));
+
+ let test = Accept(vec![
+ qitem(mime::TEXT_HTML),
+ "application/xhtml+xml".parse().unwrap(),
+ QualityItem::new("application/xml".parse().unwrap(), q(0.9)),
+ QualityItem::new(mime::STAR_STAR, q(0.8)),
+ ]);
+ assert_eq!(
+ test.mime_precedence(),
+ vec![
+ mime::TEXT_HTML,
+ "application/xhtml+xml".parse().unwrap(),
+ "application/xml".parse().unwrap(),
+ mime::STAR_STAR,
+ ]
+ );
+
+ let test = Accept(vec![
+ qitem(mime::STAR_STAR),
+ qitem(mime::IMAGE_STAR),
+ qitem(mime::IMAGE_PNG),
+ ]);
+ assert_eq!(
+ test.mime_precedence(),
+ vec![mime::IMAGE_PNG, mime::IMAGE_STAR, mime::STAR_STAR]
+ );
+ }
+
+ #[test]
+ fn test_mime_preference() {
+ let test = Accept(vec![
+ qitem(mime::TEXT_HTML),
+ "application/xhtml+xml".parse().unwrap(),
+ QualityItem::new("application/xml".parse().unwrap(), q(0.9)),
+ QualityItem::new(mime::STAR_STAR, q(0.8)),
+ ]);
+ assert_eq!(test.mime_preference(), Some(mime::TEXT_HTML));
+
+ let test = Accept(vec![
+ QualityItem::new("video/*".parse().unwrap(), q(0.8)),
+ qitem(mime::IMAGE_PNG),
+ QualityItem::new(mime::STAR_STAR, q(0.5)),
+ qitem(mime::IMAGE_SVG),
+ QualityItem::new(mime::IMAGE_STAR, q(0.8)),
+ ]);
+ assert_eq!(test.mime_preference(), Some(mime::IMAGE_PNG));
+ }
}
diff --git a/actix-http/src/header/mod.rs b/actix-http/src/header/mod.rs
index 46fb31a62..0f87516eb 100644
--- a/actix-http/src/header/mod.rs
+++ b/actix-http/src/header/mod.rs
@@ -370,9 +370,7 @@ impl fmt::Display for ExtendedValue {
}
/// Percent encode a sequence of bytes with a character set defined in
-/// [https://tools.ietf.org/html/rfc5987#section-3.2][url]
-///
-/// [url]: https://tools.ietf.org/html/rfc5987#section-3.2
+///
pub fn http_percent_encode(f: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result {
let encoded = percent_encoding::percent_encode(bytes, HTTP_VALUE);
fmt::Display::fmt(&encoded, f)
diff --git a/actix-http/src/header/shared/charset.rs b/actix-http/src/header/shared/charset.rs
index 00e7309d4..36bdbf7e2 100644
--- a/actix-http/src/header/shared/charset.rs
+++ b/actix-http/src/header/shared/charset.rs
@@ -7,9 +7,7 @@ use self::Charset::*;
///
/// The string representation is normalized to upper case.
///
-/// See [http://www.iana.org/assignments/character-sets/character-sets.xhtml][url].
-///
-/// [url]: http://www.iana.org/assignments/character-sets/character-sets.xhtml
+/// See .
#[derive(Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
pub enum Charset {
diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs
index 98230dec1..01a3b988a 100644
--- a/actix-http/src/header/shared/quality_item.rs
+++ b/actix-http/src/header/shared/quality_item.rs
@@ -1,10 +1,17 @@
-use std::{cmp, fmt, str};
+use std::{
+ cmp,
+ convert::{TryFrom, TryInto},
+ fmt, str,
+};
-use self::internal::IntoQuality;
+use derive_more::{Display, Error};
+
+const MAX_QUALITY: u16 = 1000;
+const MAX_FLOAT_QUALITY: f32 = 1.0;
/// Represents a quality used in quality values.
///
-/// Can be created with the `q` function.
+/// Can be created with the [`q`] function.
///
/// # Implementation notes
///
@@ -18,12 +25,54 @@ use self::internal::IntoQuality;
///
/// [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1)
/// gives more information on quality values in HTTP header fields.
-#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Quality(u16);
+impl Quality {
+ /// # Panics
+ /// Panics in debug mode when value is not in the range 0.0 <= n <= 1.0.
+ fn from_f32(value: f32) -> Self {
+ // Check that `value` is within range should be done before calling this method.
+ // Just in case, this debug_assert should catch if we were forgetful.
+ debug_assert!(
+ (0.0f32..=1.0f32).contains(&value),
+ "q value must be between 0.0 and 1.0"
+ );
+
+ Quality((value * MAX_QUALITY as f32) as u16)
+ }
+}
+
impl Default for Quality {
fn default() -> Quality {
- Quality(1000)
+ Quality(MAX_QUALITY)
+ }
+}
+
+#[derive(Debug, Clone, Display, Error)]
+pub struct QualityOutOfBounds;
+
+impl TryFrom for Quality {
+ type Error = QualityOutOfBounds;
+
+ fn try_from(value: u16) -> Result {
+ if (0..=MAX_QUALITY).contains(&value) {
+ Ok(Quality(value))
+ } else {
+ Err(QualityOutOfBounds)
+ }
+ }
+}
+
+impl TryFrom for Quality {
+ type Error = QualityOutOfBounds;
+
+ fn try_from(value: f32) -> Result {
+ if (0.0..=MAX_FLOAT_QUALITY).contains(&value) {
+ Ok(Quality::from_f32(value))
+ } else {
+ Err(QualityOutOfBounds)
+ }
}
}
@@ -55,8 +104,9 @@ impl cmp::PartialOrd for QualityItem {
impl fmt::Display for QualityItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.item, f)?;
+
match self.quality.0 {
- 1000 => Ok(()),
+ MAX_QUALITY => Ok(()),
0 => f.write_str("; q=0"),
x => write!(f, "; q=0.{}", format!("{:03}", x).trim_end_matches('0')),
}
@@ -66,105 +116,79 @@ impl fmt::Display for QualityItem {
impl str::FromStr for QualityItem {
type Err = crate::error::ParseError;
- fn from_str(s: &str) -> Result, crate::error::ParseError> {
- if !s.is_ascii() {
+ fn from_str(qitem_str: &str) -> Result, crate::error::ParseError> {
+ if !qitem_str.is_ascii() {
return Err(crate::error::ParseError::Header);
}
+
// Set defaults used if parsing fails.
- let mut raw_item = s;
+ let mut raw_item = qitem_str;
let mut quality = 1f32;
- let parts: Vec<&str> = s.rsplitn(2, ';').map(|x| x.trim()).collect();
+ let parts: Vec<_> = qitem_str.rsplitn(2, ';').map(str::trim).collect();
+
if parts.len() == 2 {
+ // example for item with q-factor:
+ //
+ // gzip; q=0.65
+ // ^^^^^^ parts[0]
+ // ^^ start
+ // ^^^^ q_val
+ // ^^^^ parts[1]
+
if parts[0].len() < 2 {
+ // Can't possibly be an attribute since an attribute needs at least a name followed
+ // by an equals sign. And bare identifiers are forbidden.
return Err(crate::error::ParseError::Header);
}
+
let start = &parts[0][0..2];
+
if start == "q=" || start == "Q=" {
- let q_part = &parts[0][2..parts[0].len()];
- if q_part.len() > 5 {
+ let q_val = &parts[0][2..];
+ if q_val.len() > 5 {
+ // longer than 5 indicates an over-precise q-factor
return Err(crate::error::ParseError::Header);
}
- match q_part.parse::() {
- Ok(q_value) => {
- if 0f32 <= q_value && q_value <= 1f32 {
- quality = q_value;
- raw_item = parts[1];
- } else {
- return Err(crate::error::ParseError::Header);
- }
- }
- Err(_) => return Err(crate::error::ParseError::Header),
+
+ let q_value = q_val
+ .parse::()
+ .map_err(|_| crate::error::ParseError::Header)?;
+
+ if (0f32..=1f32).contains(&q_value) {
+ quality = q_value;
+ raw_item = parts[1];
+ } else {
+ return Err(crate::error::ParseError::Header);
}
}
}
- match raw_item.parse::() {
- // we already checked above that the quality is within range
- Ok(item) => Ok(QualityItem::new(item, from_f32(quality))),
- Err(_) => Err(crate::error::ParseError::Header),
- }
- }
-}
-#[inline]
-fn from_f32(f: f32) -> Quality {
- // this function is only used internally. A check that `f` is within range
- // should be done before calling this method. Just in case, this
- // debug_assert should catch if we were forgetful
- debug_assert!(
- f >= 0f32 && f <= 1f32,
- "q value must be between 0.0 and 1.0"
- );
- Quality((f * 1000f32) as u16)
+ let item = raw_item
+ .parse::()
+ .map_err(|_| crate::error::ParseError::Header)?;
+
+ // we already checked above that the quality is within range
+ Ok(QualityItem::new(item, Quality::from_f32(quality)))
+ }
}
/// Convenience function to wrap a value in a `QualityItem`
/// Sets `q` to the default 1.0
pub fn qitem(item: T) -> QualityItem {
- QualityItem::new(item, Default::default())
+ QualityItem::new(item, Quality::default())
}
/// Convenience function to create a `Quality` from a float or integer.
///
/// Implemented for `u16` and `f32`. Panics if value is out of range.
-pub fn q(val: T) -> Quality {
- val.into_quality()
-}
-
-mod internal {
- use super::Quality;
-
- // TryFrom is probably better, but it's not stable. For now, we want to
- // keep the functionality of the `q` function, while allowing it to be
- // generic over `f32` and `u16`.
- //
- // `q` would panic before, so keep that behavior. `TryFrom` can be
- // introduced later for a non-panicking conversion.
-
- pub trait IntoQuality: Sealed + Sized {
- fn into_quality(self) -> Quality;
- }
-
- impl IntoQuality for f32 {
- fn into_quality(self) -> Quality {
- assert!(
- self >= 0f32 && self <= 1f32,
- "float must be between 0.0 and 1.0"
- );
- super::from_f32(self)
- }
- }
-
- impl IntoQuality for u16 {
- fn into_quality(self) -> Quality {
- assert!(self <= 1000, "u16 must be between 0 and 1000");
- Quality(self)
- }
- }
-
- pub trait Sealed {}
- impl Sealed for u16 {}
- impl Sealed for f32 {}
+pub fn q(val: T) -> Quality
+where
+ T: TryInto,
+ T::Error: fmt::Debug,
+{
+ // TODO: on next breaking change, handle unwrap differently
+ val.try_into().unwrap()
}
#[cfg(test)]
@@ -270,15 +294,13 @@ mod tests {
}
#[test]
- #[should_panic] // FIXME - 32-bit msvc unwinding broken
- #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
+ #[should_panic]
fn test_quality_invalid() {
q(-1.0);
}
#[test]
- #[should_panic] // FIXME - 32-bit msvc unwinding broken
- #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
+ #[should_panic]
fn test_quality_invalid2() {
q(2.0);
}
diff --git a/awc/CHANGES.md b/awc/CHANGES.md
index e184dfbd1..3745079cd 100644
--- a/awc/CHANGES.md
+++ b/awc/CHANGES.md
@@ -1,8 +1,14 @@
# Changes
## Unreleased - 2020-xx-xx
+
+
+## 2.0.2 - 2020-11-25
### Changed
-* Upgrade `serde_urlencoded` to `0.7`.
+* Upgrade `serde_urlencoded` to `0.7`. [#1773]
+
+[#1773]: https://github.com/actix/actix-web/pull/1773
+
## 2.0.1 - 2020-10-30
### Changed
diff --git a/awc/Cargo.toml b/awc/Cargo.toml
index d92996fb9..d5b632a51 100644
--- a/awc/Cargo.toml
+++ b/awc/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "awc"
-version = "2.0.1"
+version = "2.0.2"
authors = ["Nikolay Kim "]
description = "Async HTTP and WebSocket client library built on the Actix ecosystem"
readme = "README.md"
diff --git a/awc/README.md b/awc/README.md
index cbe299aaf..d14dd82dd 100644
--- a/awc/README.md
+++ b/awc/README.md
@@ -3,14 +3,14 @@
> Async HTTP and WebSocket client library.
[](https://crates.io/crates/awc)
-[](https://docs.rs/awc/2.0.1)
+[](https://docs.rs/awc/2.0.2)

-[](https://deps.rs/crate/awc/2.0.1)
+[](https://deps.rs/crate/awc/2.0.2)
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Documentation & Resources
-- [API Documentation](https://docs.rs/awc/2.0.1)
+- [API Documentation](https://docs.rs/awc)
- [Example Project](https://github.com/actix/examples/tree/HEAD/awc_https)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum Supported Rust Version (MSRV): 1.42.0
diff --git a/docs/graphs/web-focus.dot b/docs/graphs/web-focus.dot
index 7abd51268..bcae36616 100644
--- a/docs/graphs/web-focus.dot
+++ b/docs/graphs/web-focus.dot
@@ -2,29 +2,31 @@ digraph {
subgraph cluster_web {
label="actix/actix-web"
"awc"
- "actix-web"
- "actix-files"
- "actix-http"
- "actix-multipart"
- "actix-web-actors"
- "actix-web-codegen"
+ "web"
+ "files"
+ "http"
+ "multipart"
+ "web-actors"
+ "codegen"
+ "http-test"
}
- "actix-web" -> { "actix-codec" "actix-service" "actix-utils" "actix-router" "actix-rt" "actix-server" "actix-testing" "actix-macros" "actix-threadpool" "actix-tls" "actix-web-codegen" "actix-http" "awc" }
- "awc" -> { "actix-codec" "actix-service" "actix-http" "actix-rt" }
- "actix-web-actors" -> { "actix" "actix-web" "actix-http" "actix-codec" }
- "actix-multipart" -> { "actix-web" "actix-service" "actix-utils" }
- "actix-http" -> { "actix-service" "actix-codec" "actix-connect" "actix-utils" "actix-rt" "actix-threadpool" }
- "actix-http" -> { "actix" "actix-tls" }[color=blue] // optional
- "actix-files" -> { "actix-web" "actix-http" }
+ "web" -> { "codec" "service" "utils" "router" "rt" "server" "testing" "macros" "threadpool" "tls" "codegen" "http" "awc" }
+ "awc" -> { "codec" "service" "http" "rt" }
+ "web-actors" -> { "actix" "web" "http" "codec" }
+ "multipart" -> { "web" "service" "utils" }
+ "http" -> { "service" "codec" "connect" "utils" "rt" "threadpool" }
+ "http" -> { "actix" "tls" }[color=blue] // optional
+ "files" -> { "web" "http" }
+ "http-test" -> { "service" "codec" "connect" "utils" "rt" "server" "testing" "awc" }
// net
- "actix-utils" -> { "actix-service" "actix-rt" "actix-codec" }
- "actix-tracing" -> { "actix-service" }
- "actix-tls" -> { "actix-service" "actix-codec" "actix-utils" }
- "actix-testing" -> { "actix-rt" "actix-macros" "actix-server" "actix-service" }
- "actix-server" -> { "actix-service" "actix-rt" "actix-codec" "actix-utils" }
- "actix-rt" -> { "actix-macros" "actix-threadpool" }
- "actix-connect" -> { "actix-service" "actix-codec" "actix-utils" "actix-rt" }
+ "utils" -> { "service" "rt" "codec" }
+ "tracing" -> { "service" }
+ "tls" -> { "service" "codec" "utils" }
+ "testing" -> { "rt" "macros" "server" "service" }
+ "server" -> { "service" "rt" "codec" "utils" }
+ "rt" -> { "macros" "threadpool" }
+ "connect" -> { "service" "codec" "utils" "rt" }
}
diff --git a/docs/graphs/web-only.dot b/docs/graphs/web-only.dot
index 6e41fdc27..ee653e33b 100644
--- a/docs/graphs/web-only.dot
+++ b/docs/graphs/web-only.dot
@@ -8,6 +8,7 @@ digraph {
"actix-multipart"
"actix-web-actors"
"actix-web-codegen"
+ "actix-http-test"
}
"actix-web" -> { "actix-web-codegen" "actix-http" "awc" }
@@ -16,4 +17,5 @@ digraph {
"actix-multipart" -> { "actix-web" }
"actix-http" -> { "actix" }[color=blue] // optional
"actix-files" -> { "actix-web" "actix-http" }
+ "actix-http-test" -> { "awc" }
}
diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md
index 845b6e2dc..835b75ddc 100644
--- a/test-server/CHANGES.md
+++ b/test-server/CHANGES.md
@@ -2,15 +2,20 @@
## Unreleased - 2020-xx-xx
-* add ability to set address for `TestServer` [#1645]
-* Upgrade `base64` to `0.13`.
-* Upgrade `serde_urlencoded` to `0.7`.
+## 2.1.0 - 2020-11-25
+* Add ability to set address for `TestServer`. [#1645]
+* Upgrade `base64` to `0.13`.
+* Upgrade `serde_urlencoded` to `0.7`. [#1773]
+
+[#1773]: https://github.com/actix/actix-web/pull/1773
[#1645]: https://github.com/actix/actix-web/pull/1645
+
## 2.0.0 - 2020-09-11
* Update actix-codec and actix-utils dependencies.
+
## 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
@@ -20,74 +25,56 @@
* Update `base64` dependency to 0.12
* Update `env_logger` dependency to 0.7
-## [1.0.0] - 2019-12-13
-
-### Changed
-
+## 1.0.0 - 2019-12-13
* Replaced `TestServer::start()` with `test_server()`
-## [1.0.0-alpha.3] - 2019-12-07
-
-### Changed
-
+## 1.0.0-alpha.3 - 2019-12-07
* Migrate to `std::future`
-## [0.2.5] - 2019-09-17
-
-### Changed
-
+## 0.2.5 - 2019-09-17
* Update serde_urlencoded to "0.6.1"
* Increase TestServerRuntime timeouts from 500ms to 3000ms
-
-### Fixed
-
* Do not override current `System`
-## [0.2.4] - 2019-07-18
-
+## 0.2.4 - 2019-07-18
* Update actix-server to 0.6
-## [0.2.3] - 2019-07-16
+## 0.2.3 - 2019-07-16
* Add `delete`, `options`, `patch` methods to `TestServerRunner`
-## [0.2.2] - 2019-06-16
+## 0.2.2 - 2019-06-16
* Add .put() and .sput() methods
-## [0.2.1] - 2019-06-05
+## 0.2.1 - 2019-06-05
* Add license files
-## [0.2.0] - 2019-05-12
+## 0.2.0 - 2019-05-12
* Update awc and actix-http deps
-## [0.1.1] - 2019-04-24
+## 0.1.1 - 2019-04-24
* Always make new connection for http client
-## [0.1.0] - 2019-04-16
-
+## 0.1.0 - 2019-04-16
* No changes
-## [0.1.0-alpha.3] - 2019-04-02
-
+## 0.1.0-alpha.3 - 2019-04-02
* Request functions accept path #743
-## [0.1.0-alpha.2] - 2019-03-29
-
+## 0.1.0-alpha.2 - 2019-03-29
* Added TestServerRuntime::load_body() method
-
* Update actix-http and awc libraries
-## [0.1.0-alpha.1] - 2019-03-28
-
+## 0.1.0-alpha.1 - 2019-03-28
* Initial impl
diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml
index 87db93469..8b23bef1c 100644
--- a/test-server/Cargo.toml
+++ b/test-server/Cargo.toml
@@ -1,8 +1,8 @@
[package]
name = "actix-http-test"
-version = "2.0.0"
+version = "2.1.0"
authors = ["Nikolay Kim "]
-description = "Actix HTTP test server"
+description = "Various helpers for Actix applications to use during testing"
readme = "README.md"
keywords = ["http", "web", "framework", "async", "futures"]
homepage = "https://actix.rs"
diff --git a/test-server/README.md b/test-server/README.md
index db0791db7..c847c8515 100644
--- a/test-server/README.md
+++ b/test-server/README.md
@@ -1,9 +1,15 @@
-# Actix http test server [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-http-test) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+# actix-http-test
-## Documentation & community resources
+> Various helpers for Actix applications to use during testing.
-* [User Guide](https://actix.rs/docs/)
-* [API Documentation](https://docs.rs/actix-http-test/)
-* [Chat on gitter](https://gitter.im/actix/actix)
-* Cargo package: [actix-http-test](https://crates.io/crates/actix-http-test)
-* Minimum supported Rust version: 1.40 or later
+[](https://crates.io/crates/actix-http-test)
+[](https://docs.rs/actix-http-test/2.1.0)
+
+[](https://deps.rs/crate/actix-http-test/2.1.0)
+[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+## Documentation & Resources
+
+- [API Documentation](https://docs.rs/actix-http-test)
+- [Chat on Gitter](https://gitter.im/actix/actix-web)
+- Minimum Supported Rust Version (MSRV): 1.42.0
diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs
index 4159c8d86..f881dfb4c 100644
--- a/test-server/src/lib.rs
+++ b/test-server/src/lib.rs
@@ -1,4 +1,9 @@
//! Various helpers for Actix applications to use during testing.
+
+#![deny(rust_2018_idioms)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
use std::sync::mpsc;
use std::{net, thread, time};