mirror of https://github.com/fafhrd91/actix-web
commit
145bfca6d9
|
@ -30,7 +30,7 @@ jobs:
|
||||||
run: echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html
|
run: echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: JamesIves/github-pages-deploy-action@3.5.8
|
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
BRANCH: gh-pages
|
BRANCH: gh-pages
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 3.3.0 - 2020-11-25
|
||||||
### Added
|
### Added
|
||||||
* Add `Either<A, B>` extractor helper. [#1788]
|
* Add `Either<A, B>` extractor helper. [#1788]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Upgrade `serde_urlencoded` to `0.7`.
|
* Upgrade `serde_urlencoded` to `0.7`. [#1773]
|
||||||
|
|
||||||
|
[#1773]: https://github.com/actix/actix-web/pull/1773
|
||||||
[#1788]: https://github.com/actix/actix-web/pull/1788
|
[#1788]: https://github.com/actix/actix-web/pull/1788
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-web"
|
name = "actix-web"
|
||||||
version = "3.2.0"
|
version = "3.3.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust"
|
description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-web)
|
[](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://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)
|
||||||
<br />
|
<br />
|
||||||
[](https://travis-ci.org/actix/actix-web)
|
[](https://travis-ci.org/actix/actix-web)
|
||||||
[](https://codecov.io/gh/actix/actix-web)
|
[](https://codecov.io/gh/actix/actix-web)
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
## Unreleased - 2020-xx-xx
|
## 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
|
## 0.4.0 - 2020-10-06
|
||||||
* Add `Files::prefer_utf8` option that adds UTF-8 charset on certain response types. [#1714]
|
* Add `Files::prefer_utf8` option that adds UTF-8 charset on certain response types. [#1714]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-files"
|
name = "actix-files"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Static file serving for Actix Web"
|
description = "Static file serving for Actix Web"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -21,14 +21,14 @@ actix-web = { version = "3.0.0", default-features = false }
|
||||||
actix-service = "1.0.6"
|
actix-service = "1.0.6"
|
||||||
bitflags = "1"
|
bitflags = "1"
|
||||||
bytes = "0.5.3"
|
bytes = "0.5.3"
|
||||||
futures-core = { version = "0.3.5", default-features = false }
|
futures-core = { version = "0.3.7", default-features = false }
|
||||||
futures-util = { version = "0.3.5", default-features = false }
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
derive_more = "0.99.2"
|
derive_more = "0.99.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
mime_guess = "2.0.1"
|
mime_guess = "2.0.1"
|
||||||
percent-encoding = "2.1"
|
percent-encoding = "2.1"
|
||||||
v_htmlescape = "0.10"
|
v_htmlescape = "0.11"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "1.0.0"
|
actix-rt = "1.0.0"
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
> Static file serving for Actix Web
|
> Static file serving for Actix Web
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-files)
|
[](https://crates.io/crates/actix-files)
|
||||||
[](https://docs.rs/actix-files)
|
[](https://docs.rs/actix-files/0.4.1)
|
||||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
|
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
|
||||||

|

|
||||||
<br />
|
<br />
|
||||||
[](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://crates.io/crates/actix-files)
|
||||||
[](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
|
|
@ -65,13 +65,25 @@ impl Clone for Files {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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.
|
/// # Argument Order
|
||||||
/// By default pool with 5x threads of available cpus is used.
|
/// The first argument (`mount_path`) is the root URL at which the static files are served.
|
||||||
/// Pool size can be changed by setting ACTIX_THREADPOOL environment variable.
|
/// For example, `/assets` will serve files at `example.com/assets/...`.
|
||||||
pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files {
|
///
|
||||||
let orig_dir = dir.into();
|
/// 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<T: Into<PathBuf>>(mount_path: &str, serve_from: T) -> Files {
|
||||||
|
let orig_dir = serve_from.into();
|
||||||
let dir = match orig_dir.canonicalize() {
|
let dir = match orig_dir.canonicalize() {
|
||||||
Ok(canon_dir) => canon_dir,
|
Ok(canon_dir) => canon_dir,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -81,7 +93,7 @@ impl Files {
|
||||||
};
|
};
|
||||||
|
|
||||||
Files {
|
Files {
|
||||||
path: path.to_string(),
|
path: mount_path.to_owned(),
|
||||||
directory: dir,
|
directory: dir,
|
||||||
index: None,
|
index: None,
|
||||||
show_index: false,
|
show_index: false,
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 2.2.0 - 2020-11-25
|
||||||
### Added
|
### Added
|
||||||
* HttpResponse builders for 1xx status codes. [#1768]
|
* HttpResponse builders for 1xx status codes. [#1768]
|
||||||
|
* `Accept::mime_precedence` and `Accept::mime_preference`. [#1793]
|
||||||
|
* `TryFrom<u16>` and `TryFrom<f32>` for `http::header::Quality`. [#1797]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767]
|
* Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767]
|
||||||
|
|
||||||
### Changed
|
### 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
|
[#1767]: https://github.com/actix/actix-web/pull/1767
|
||||||
[#1768]: https://github.com/actix/actix-web/pull/1768
|
[#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
|
## 2.1.0 - 2020-10-30
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "2.1.0"
|
version = "2.2.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "HTTP primitives for the Actix ecosystem"
|
description = "HTTP primitives for the Actix ecosystem"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
> HTTP primitives for the Actix ecosystem.
|
> HTTP primitives for the Actix ecosystem.
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-http)
|
[](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)
|
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
## Documentation & Resources
|
## 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)
|
- [Chat on Gitter](https://gitter.im/actix/actix-web)
|
||||||
- Minimum Supported Rust Version (MSRV): 1.42.0
|
- Minimum Supported Rust Version (MSRV): 1.42.0
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
|
||||||
use crate::header::{qitem, QualityItem};
|
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)
|
/// `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
|
/// 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
|
/// 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
|
/// small set of desired types, as in the case of a request for an
|
||||||
/// in-line image
|
/// in-line image
|
||||||
|
@ -97,14 +99,14 @@ header! {
|
||||||
test_header!(
|
test_header!(
|
||||||
test1,
|
test1,
|
||||||
vec![b"audio/*; q=0.2, audio/basic"],
|
vec![b"audio/*; q=0.2, audio/basic"],
|
||||||
Some(HeaderField(vec![
|
Some(Accept(vec![
|
||||||
QualityItem::new("audio/*".parse().unwrap(), q(200)),
|
QualityItem::new("audio/*".parse().unwrap(), q(200)),
|
||||||
qitem("audio/basic".parse().unwrap()),
|
qitem("audio/basic".parse().unwrap()),
|
||||||
])));
|
])));
|
||||||
test_header!(
|
test_header!(
|
||||||
test2,
|
test2,
|
||||||
vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
|
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)),
|
QualityItem::new(mime::TEXT_PLAIN, q(500)),
|
||||||
qitem(mime::TEXT_HTML),
|
qitem(mime::TEXT_HTML),
|
||||||
QualityItem::new(
|
QualityItem::new(
|
||||||
|
@ -138,23 +140,148 @@ header! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Accept {
|
impl Accept {
|
||||||
/// A constructor to easily create `Accept: */*`.
|
/// Construct `Accept: */*`.
|
||||||
pub fn star() -> Accept {
|
pub fn star() -> Accept {
|
||||||
Accept(vec![qitem(mime::STAR_STAR)])
|
Accept(vec![qitem(mime::STAR_STAR)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A constructor to easily create `Accept: application/json`.
|
/// Construct `Accept: application/json`.
|
||||||
pub fn json() -> Accept {
|
pub fn json() -> Accept {
|
||||||
Accept(vec![qitem(mime::APPLICATION_JSON)])
|
Accept(vec![qitem(mime::APPLICATION_JSON)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A constructor to easily create `Accept: text/*`.
|
/// Construct `Accept: text/*`.
|
||||||
pub fn text() -> Accept {
|
pub fn text() -> Accept {
|
||||||
Accept(vec![qitem(mime::TEXT_STAR)])
|
Accept(vec![qitem(mime::TEXT_STAR)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A constructor to easily create `Accept: image/*`.
|
/// Construct `Accept: image/*`.
|
||||||
pub fn image() -> Accept {
|
pub fn image() -> Accept {
|
||||||
Accept(vec![qitem(mime::IMAGE_STAR)])
|
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<Mime> {
|
||||||
|
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<Mime> {
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,9 +370,7 @@ impl fmt::Display for ExtendedValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Percent encode a sequence of bytes with a character set defined in
|
/// Percent encode a sequence of bytes with a character set defined in
|
||||||
/// [https://tools.ietf.org/html/rfc5987#section-3.2][url]
|
/// <https://tools.ietf.org/html/rfc5987#section-3.2>
|
||||||
///
|
|
||||||
/// [url]: https://tools.ietf.org/html/rfc5987#section-3.2
|
|
||||||
pub fn http_percent_encode(f: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result {
|
pub fn http_percent_encode(f: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result {
|
||||||
let encoded = percent_encoding::percent_encode(bytes, HTTP_VALUE);
|
let encoded = percent_encoding::percent_encode(bytes, HTTP_VALUE);
|
||||||
fmt::Display::fmt(&encoded, f)
|
fmt::Display::fmt(&encoded, f)
|
||||||
|
|
|
@ -7,9 +7,7 @@ use self::Charset::*;
|
||||||
///
|
///
|
||||||
/// The string representation is normalized to upper case.
|
/// The string representation is normalized to upper case.
|
||||||
///
|
///
|
||||||
/// See [http://www.iana.org/assignments/character-sets/character-sets.xhtml][url].
|
/// See <http://www.iana.org/assignments/character-sets/character-sets.xhtml>.
|
||||||
///
|
|
||||||
/// [url]: http://www.iana.org/assignments/character-sets/character-sets.xhtml
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub enum Charset {
|
pub enum Charset {
|
||||||
|
|
|
@ -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.
|
/// Represents a quality used in quality values.
|
||||||
///
|
///
|
||||||
/// Can be created with the `q` function.
|
/// Can be created with the [`q`] function.
|
||||||
///
|
///
|
||||||
/// # Implementation notes
|
/// # 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)
|
/// [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.
|
/// 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);
|
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 {
|
impl Default for Quality {
|
||||||
fn default() -> Quality {
|
fn default() -> Quality {
|
||||||
Quality(1000)
|
Quality(MAX_QUALITY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Display, Error)]
|
||||||
|
pub struct QualityOutOfBounds;
|
||||||
|
|
||||||
|
impl TryFrom<u16> for Quality {
|
||||||
|
type Error = QualityOutOfBounds;
|
||||||
|
|
||||||
|
fn try_from(value: u16) -> Result<Self, Self::Error> {
|
||||||
|
if (0..=MAX_QUALITY).contains(&value) {
|
||||||
|
Ok(Quality(value))
|
||||||
|
} else {
|
||||||
|
Err(QualityOutOfBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<f32> for Quality {
|
||||||
|
type Error = QualityOutOfBounds;
|
||||||
|
|
||||||
|
fn try_from(value: f32) -> Result<Self, Self::Error> {
|
||||||
|
if (0.0..=MAX_FLOAT_QUALITY).contains(&value) {
|
||||||
|
Ok(Quality::from_f32(value))
|
||||||
|
} else {
|
||||||
|
Err(QualityOutOfBounds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +104,9 @@ impl<T: PartialEq> cmp::PartialOrd for QualityItem<T> {
|
||||||
impl<T: fmt::Display> fmt::Display for QualityItem<T> {
|
impl<T: fmt::Display> fmt::Display for QualityItem<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.item, f)?;
|
fmt::Display::fmt(&self.item, f)?;
|
||||||
|
|
||||||
match self.quality.0 {
|
match self.quality.0 {
|
||||||
1000 => Ok(()),
|
MAX_QUALITY => Ok(()),
|
||||||
0 => f.write_str("; q=0"),
|
0 => f.write_str("; q=0"),
|
||||||
x => write!(f, "; q=0.{}", format!("{:03}", x).trim_end_matches('0')),
|
x => write!(f, "; q=0.{}", format!("{:03}", x).trim_end_matches('0')),
|
||||||
}
|
}
|
||||||
|
@ -66,105 +116,79 @@ impl<T: fmt::Display> fmt::Display for QualityItem<T> {
|
||||||
impl<T: str::FromStr> str::FromStr for QualityItem<T> {
|
impl<T: str::FromStr> str::FromStr for QualityItem<T> {
|
||||||
type Err = crate::error::ParseError;
|
type Err = crate::error::ParseError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<QualityItem<T>, crate::error::ParseError> {
|
fn from_str(qitem_str: &str) -> Result<QualityItem<T>, crate::error::ParseError> {
|
||||||
if !s.is_ascii() {
|
if !qitem_str.is_ascii() {
|
||||||
return Err(crate::error::ParseError::Header);
|
return Err(crate::error::ParseError::Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set defaults used if parsing fails.
|
// Set defaults used if parsing fails.
|
||||||
let mut raw_item = s;
|
let mut raw_item = qitem_str;
|
||||||
let mut quality = 1f32;
|
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 {
|
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 {
|
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);
|
return Err(crate::error::ParseError::Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = &parts[0][0..2];
|
let start = &parts[0][0..2];
|
||||||
|
|
||||||
if start == "q=" || start == "Q=" {
|
if start == "q=" || start == "Q=" {
|
||||||
let q_part = &parts[0][2..parts[0].len()];
|
let q_val = &parts[0][2..];
|
||||||
if q_part.len() > 5 {
|
if q_val.len() > 5 {
|
||||||
|
// longer than 5 indicates an over-precise q-factor
|
||||||
return Err(crate::error::ParseError::Header);
|
return Err(crate::error::ParseError::Header);
|
||||||
}
|
}
|
||||||
match q_part.parse::<f32>() {
|
|
||||||
Ok(q_value) => {
|
let q_value = q_val
|
||||||
if 0f32 <= q_value && q_value <= 1f32 {
|
.parse::<f32>()
|
||||||
quality = q_value;
|
.map_err(|_| crate::error::ParseError::Header)?;
|
||||||
raw_item = parts[1];
|
|
||||||
} else {
|
if (0f32..=1f32).contains(&q_value) {
|
||||||
return Err(crate::error::ParseError::Header);
|
quality = q_value;
|
||||||
}
|
raw_item = parts[1];
|
||||||
}
|
} else {
|
||||||
Err(_) => return Err(crate::error::ParseError::Header),
|
return Err(crate::error::ParseError::Header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match raw_item.parse::<T>() {
|
|
||||||
// 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]
|
let item = raw_item
|
||||||
fn from_f32(f: f32) -> Quality {
|
.parse::<T>()
|
||||||
// this function is only used internally. A check that `f` is within range
|
.map_err(|_| crate::error::ParseError::Header)?;
|
||||||
// should be done before calling this method. Just in case, this
|
|
||||||
// debug_assert should catch if we were forgetful
|
// we already checked above that the quality is within range
|
||||||
debug_assert!(
|
Ok(QualityItem::new(item, Quality::from_f32(quality)))
|
||||||
f >= 0f32 && f <= 1f32,
|
}
|
||||||
"q value must be between 0.0 and 1.0"
|
|
||||||
);
|
|
||||||
Quality((f * 1000f32) as u16)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to wrap a value in a `QualityItem`
|
/// Convenience function to wrap a value in a `QualityItem`
|
||||||
/// Sets `q` to the default 1.0
|
/// Sets `q` to the default 1.0
|
||||||
pub fn qitem<T>(item: T) -> QualityItem<T> {
|
pub fn qitem<T>(item: T) -> QualityItem<T> {
|
||||||
QualityItem::new(item, Default::default())
|
QualityItem::new(item, Quality::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to create a `Quality` from a float or integer.
|
/// Convenience function to create a `Quality` from a float or integer.
|
||||||
///
|
///
|
||||||
/// Implemented for `u16` and `f32`. Panics if value is out of range.
|
/// Implemented for `u16` and `f32`. Panics if value is out of range.
|
||||||
pub fn q<T: IntoQuality>(val: T) -> Quality {
|
pub fn q<T>(val: T) -> Quality
|
||||||
val.into_quality()
|
where
|
||||||
}
|
T: TryInto<Quality>,
|
||||||
|
T::Error: fmt::Debug,
|
||||||
mod internal {
|
{
|
||||||
use super::Quality;
|
// TODO: on next breaking change, handle unwrap differently
|
||||||
|
val.try_into().unwrap()
|
||||||
// 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 {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -270,15 +294,13 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic] // FIXME - 32-bit msvc unwinding broken
|
#[should_panic]
|
||||||
#[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
|
|
||||||
fn test_quality_invalid() {
|
fn test_quality_invalid() {
|
||||||
q(-1.0);
|
q(-1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic] // FIXME - 32-bit msvc unwinding broken
|
#[should_panic]
|
||||||
#[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
|
|
||||||
fn test_quality_invalid2() {
|
fn test_quality_invalid2() {
|
||||||
q(2.0);
|
q(2.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 2.0.2 - 2020-11-25
|
||||||
### Changed
|
### 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
|
## 2.0.1 - 2020-10-30
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "awc"
|
name = "awc"
|
||||||
version = "2.0.1"
|
version = "2.0.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Async HTTP and WebSocket client library built on the Actix ecosystem"
|
description = "Async HTTP and WebSocket client library built on the Actix ecosystem"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
> Async HTTP and WebSocket client library.
|
> Async HTTP and WebSocket client library.
|
||||||
|
|
||||||
[](https://crates.io/crates/awc)
|
[](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)
|
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
## Documentation & Resources
|
## 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)
|
- [Example Project](https://github.com/actix/examples/tree/HEAD/awc_https)
|
||||||
- [Chat on Gitter](https://gitter.im/actix/actix-web)
|
- [Chat on Gitter](https://gitter.im/actix/actix-web)
|
||||||
- Minimum Supported Rust Version (MSRV): 1.42.0
|
- Minimum Supported Rust Version (MSRV): 1.42.0
|
||||||
|
|
|
@ -2,29 +2,31 @@ digraph {
|
||||||
subgraph cluster_web {
|
subgraph cluster_web {
|
||||||
label="actix/actix-web"
|
label="actix/actix-web"
|
||||||
"awc"
|
"awc"
|
||||||
"actix-web"
|
"web"
|
||||||
"actix-files"
|
"files"
|
||||||
"actix-http"
|
"http"
|
||||||
"actix-multipart"
|
"multipart"
|
||||||
"actix-web-actors"
|
"web-actors"
|
||||||
"actix-web-codegen"
|
"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" }
|
"web" -> { "codec" "service" "utils" "router" "rt" "server" "testing" "macros" "threadpool" "tls" "codegen" "http" "awc" }
|
||||||
"awc" -> { "actix-codec" "actix-service" "actix-http" "actix-rt" }
|
"awc" -> { "codec" "service" "http" "rt" }
|
||||||
"actix-web-actors" -> { "actix" "actix-web" "actix-http" "actix-codec" }
|
"web-actors" -> { "actix" "web" "http" "codec" }
|
||||||
"actix-multipart" -> { "actix-web" "actix-service" "actix-utils" }
|
"multipart" -> { "web" "service" "utils" }
|
||||||
"actix-http" -> { "actix-service" "actix-codec" "actix-connect" "actix-utils" "actix-rt" "actix-threadpool" }
|
"http" -> { "service" "codec" "connect" "utils" "rt" "threadpool" }
|
||||||
"actix-http" -> { "actix" "actix-tls" }[color=blue] // optional
|
"http" -> { "actix" "tls" }[color=blue] // optional
|
||||||
"actix-files" -> { "actix-web" "actix-http" }
|
"files" -> { "web" "http" }
|
||||||
|
"http-test" -> { "service" "codec" "connect" "utils" "rt" "server" "testing" "awc" }
|
||||||
|
|
||||||
// net
|
// net
|
||||||
|
|
||||||
"actix-utils" -> { "actix-service" "actix-rt" "actix-codec" }
|
"utils" -> { "service" "rt" "codec" }
|
||||||
"actix-tracing" -> { "actix-service" }
|
"tracing" -> { "service" }
|
||||||
"actix-tls" -> { "actix-service" "actix-codec" "actix-utils" }
|
"tls" -> { "service" "codec" "utils" }
|
||||||
"actix-testing" -> { "actix-rt" "actix-macros" "actix-server" "actix-service" }
|
"testing" -> { "rt" "macros" "server" "service" }
|
||||||
"actix-server" -> { "actix-service" "actix-rt" "actix-codec" "actix-utils" }
|
"server" -> { "service" "rt" "codec" "utils" }
|
||||||
"actix-rt" -> { "actix-macros" "actix-threadpool" }
|
"rt" -> { "macros" "threadpool" }
|
||||||
"actix-connect" -> { "actix-service" "actix-codec" "actix-utils" "actix-rt" }
|
"connect" -> { "service" "codec" "utils" "rt" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ digraph {
|
||||||
"actix-multipart"
|
"actix-multipart"
|
||||||
"actix-web-actors"
|
"actix-web-actors"
|
||||||
"actix-web-codegen"
|
"actix-web-codegen"
|
||||||
|
"actix-http-test"
|
||||||
}
|
}
|
||||||
|
|
||||||
"actix-web" -> { "actix-web-codegen" "actix-http" "awc" }
|
"actix-web" -> { "actix-web-codegen" "actix-http" "awc" }
|
||||||
|
@ -16,4 +17,5 @@ digraph {
|
||||||
"actix-multipart" -> { "actix-web" }
|
"actix-multipart" -> { "actix-web" }
|
||||||
"actix-http" -> { "actix" }[color=blue] // optional
|
"actix-http" -> { "actix" }[color=blue] // optional
|
||||||
"actix-files" -> { "actix-web" "actix-http" }
|
"actix-files" -> { "actix-web" "actix-http" }
|
||||||
|
"actix-http-test" -> { "awc" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,20 @@
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## 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
|
[#1645]: https://github.com/actix/actix-web/pull/1645
|
||||||
|
|
||||||
|
|
||||||
## 2.0.0 - 2020-09-11
|
## 2.0.0 - 2020-09-11
|
||||||
* Update actix-codec and actix-utils dependencies.
|
* Update actix-codec and actix-utils dependencies.
|
||||||
|
|
||||||
|
|
||||||
## 2.0.0-alpha.1 - 2020-05-23
|
## 2.0.0-alpha.1 - 2020-05-23
|
||||||
* Update the `time` dependency to 0.2.7
|
* Update the `time` dependency to 0.2.7
|
||||||
* Update `actix-connect` dependency to 2.0.0-alpha.2
|
* Update `actix-connect` dependency to 2.0.0-alpha.2
|
||||||
|
@ -20,74 +25,56 @@
|
||||||
* Update `base64` dependency to 0.12
|
* Update `base64` dependency to 0.12
|
||||||
* Update `env_logger` dependency to 0.7
|
* Update `env_logger` dependency to 0.7
|
||||||
|
|
||||||
## [1.0.0] - 2019-12-13
|
## 1.0.0 - 2019-12-13
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
* Replaced `TestServer::start()` with `test_server()`
|
* Replaced `TestServer::start()` with `test_server()`
|
||||||
|
|
||||||
|
|
||||||
## [1.0.0-alpha.3] - 2019-12-07
|
## 1.0.0-alpha.3 - 2019-12-07
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
* Migrate to `std::future`
|
* Migrate to `std::future`
|
||||||
|
|
||||||
|
|
||||||
## [0.2.5] - 2019-09-17
|
## 0.2.5 - 2019-09-17
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
* Update serde_urlencoded to "0.6.1"
|
* Update serde_urlencoded to "0.6.1"
|
||||||
* Increase TestServerRuntime timeouts from 500ms to 3000ms
|
* Increase TestServerRuntime timeouts from 500ms to 3000ms
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
* Do not override current `System`
|
* Do not override current `System`
|
||||||
|
|
||||||
|
|
||||||
## [0.2.4] - 2019-07-18
|
## 0.2.4 - 2019-07-18
|
||||||
|
|
||||||
* Update actix-server to 0.6
|
* 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`
|
* Add `delete`, `options`, `patch` methods to `TestServerRunner`
|
||||||
|
|
||||||
## [0.2.2] - 2019-06-16
|
|
||||||
|
|
||||||
|
## 0.2.2 - 2019-06-16
|
||||||
* Add .put() and .sput() methods
|
* Add .put() and .sput() methods
|
||||||
|
|
||||||
## [0.2.1] - 2019-06-05
|
|
||||||
|
|
||||||
|
## 0.2.1 - 2019-06-05
|
||||||
* Add license files
|
* Add license files
|
||||||
|
|
||||||
## [0.2.0] - 2019-05-12
|
|
||||||
|
|
||||||
|
## 0.2.0 - 2019-05-12
|
||||||
* Update awc and actix-http deps
|
* 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
|
* Always make new connection for http client
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0] - 2019-04-16
|
## 0.1.0 - 2019-04-16
|
||||||
|
|
||||||
* No changes
|
* No changes
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0-alpha.3] - 2019-04-02
|
## 0.1.0-alpha.3 - 2019-04-02
|
||||||
|
|
||||||
* Request functions accept path #743
|
* 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
|
* Added TestServerRuntime::load_body() method
|
||||||
|
|
||||||
* Update actix-http and awc libraries
|
* Update actix-http and awc libraries
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0-alpha.1] - 2019-03-28
|
## 0.1.0-alpha.1 - 2019-03-28
|
||||||
|
|
||||||
* Initial impl
|
* Initial impl
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-http-test"
|
name = "actix-http-test"
|
||||||
version = "2.0.0"
|
version = "2.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix HTTP test server"
|
description = "Various helpers for Actix applications to use during testing"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["http", "web", "framework", "async", "futures"]
|
keywords = ["http", "web", "framework", "async", "futures"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
|
|
|
@ -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/)
|
[](https://crates.io/crates/actix-http-test)
|
||||||
* [API Documentation](https://docs.rs/actix-http-test/)
|
[](https://docs.rs/actix-http-test/2.1.0)
|
||||||
* [Chat on gitter](https://gitter.im/actix/actix)
|

|
||||||
* Cargo package: [actix-http-test](https://crates.io/crates/actix-http-test)
|
[](https://deps.rs/crate/actix-http-test/2.1.0)
|
||||||
* Minimum supported Rust version: 1.40 or later
|
[](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
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
//! Various helpers for Actix applications to use during testing.
|
//! 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::sync::mpsc;
|
||||||
use std::{net, thread, time};
|
use std::{net, thread, time};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue