mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-30 10:42:55 +01:00
move typed headers and implement FromRequest (#2094)
Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
parent
c8ed8dd1a4
commit
50dc13f280
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
### Added
|
### Added
|
||||||
|
* `Header` extractor for extracting common HTTP headers in handlers. [#2094]
|
||||||
* Added `TestServer::client_headers` method. [#2097]
|
* Added `TestServer::client_headers` method. [#2097]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@ -17,6 +18,8 @@
|
|||||||
|
|
||||||
[#2067]: https://github.com/actix/actix-web/pull/2067
|
[#2067]: https://github.com/actix/actix-web/pull/2067
|
||||||
[#2093]: https://github.com/actix/actix-web/pull/2093
|
[#2093]: https://github.com/actix/actix-web/pull/2093
|
||||||
|
[#2094]: https://github.com/actix/actix-web/pull/2094
|
||||||
|
[#2097]: https://github.com/actix/actix-web/pull/2097
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.4 - 2021-03-09
|
## 4.0.0-beta.4 - 2021-03-09
|
||||||
|
@ -97,6 +97,8 @@ either = "1.5.3"
|
|||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
futures-core = { version = "0.3.7", default-features = false }
|
futures-core = { version = "0.3.7", default-features = false }
|
||||||
futures-util = { version = "0.3.7", default-features = false }
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
|
language-tags = "0.2"
|
||||||
|
once_cell = "1.5"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
pin-project = "1.0.0"
|
pin-project = "1.0.0"
|
||||||
|
@ -10,10 +10,12 @@
|
|||||||
* `client::Connector` type now only have one generic type for `actix_service::Service`. [#2063]
|
* `client::Connector` type now only have one generic type for `actix_service::Service`. [#2063]
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
* Common HTTP headers were moved into actix-web. [2094]
|
||||||
* `ResponseError` impl for `actix_utils::timeout::TimeoutError`. [#2127]
|
* `ResponseError` impl for `actix_utils::timeout::TimeoutError`. [#2127]
|
||||||
|
|
||||||
[#2063]: https://github.com/actix/actix-web/pull/2063
|
[#2063]: https://github.com/actix/actix-web/pull/2063
|
||||||
[#2081]: https://github.com/actix/actix-web/pull/2081
|
[#2081]: https://github.com/actix/actix-web/pull/2081
|
||||||
|
[#2094]: https://github.com/actix/actix-web/pull/2094
|
||||||
[#2127]: https://github.com/actix/actix-web/pull/2127
|
[#2127]: https://github.com/actix/actix-web/pull/2127
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
//! Typed HTTP headers, pre-defined `HeaderName`s, traits for parsing and conversion, and other
|
//! Typed HTTP headers, pre-defined `HeaderName`s, traits for parsing and conversion, and other
|
||||||
//! header utility methods.
|
//! header utility methods.
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
|
||||||
use percent_encoding::{AsciiSet, CONTROLS};
|
use percent_encoding::{AsciiSet, CONTROLS};
|
||||||
|
|
||||||
pub use http::header::*;
|
pub use http::header::*;
|
||||||
@ -16,11 +13,9 @@ mod into_pair;
|
|||||||
mod into_value;
|
mod into_value;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
mod common;
|
|
||||||
pub(crate) mod map;
|
pub(crate) mod map;
|
||||||
mod shared;
|
mod shared;
|
||||||
|
|
||||||
pub use self::common::*;
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use self::shared::*;
|
pub use self::shared::*;
|
||||||
|
|
||||||
@ -41,34 +36,6 @@ pub trait Header: IntoHeaderValue {
|
|||||||
fn parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError>;
|
fn parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub(crate) struct Writer {
|
|
||||||
buf: BytesMut,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Writer {
|
|
||||||
fn new() -> Writer {
|
|
||||||
Writer::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take(&mut self) -> Bytes {
|
|
||||||
self.buf.split().freeze()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Write for Writer {
|
|
||||||
#[inline]
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
self.buf.extend_from_slice(s.as_bytes());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
|
|
||||||
fmt::write(self, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert `http::HeaderMap` to our `HeaderMap`.
|
/// Convert `http::HeaderMap` to our `HeaderMap`.
|
||||||
impl From<http::HeaderMap> for HeaderMap {
|
impl From<http::HeaderMap> for HeaderMap {
|
||||||
fn from(mut map: http::HeaderMap) -> HeaderMap {
|
fn from(mut map: http::HeaderMap) -> HeaderMap {
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
//! Originally taken from `hyper::header::shared`.
|
//! Originally taken from `hyper::header::shared`.
|
||||||
|
|
||||||
mod charset;
|
mod charset;
|
||||||
mod encoding;
|
mod content_encoding;
|
||||||
mod entity;
|
|
||||||
mod extended;
|
mod extended;
|
||||||
mod httpdate;
|
mod httpdate;
|
||||||
mod quality_item;
|
mod quality_item;
|
||||||
|
|
||||||
pub use self::charset::Charset;
|
pub use self::charset::Charset;
|
||||||
pub use self::encoding::Encoding;
|
pub use self::content_encoding::ContentEncoding;
|
||||||
pub use self::entity::EntityTag;
|
|
||||||
pub use self::extended::{parse_extended_value, ExtendedValue};
|
pub use self::extended::{parse_extended_value, ExtendedValue};
|
||||||
pub use self::httpdate::HttpDate;
|
pub use self::httpdate::HttpDate;
|
||||||
pub use self::quality_item::{q, qitem, Quality, QualityItem};
|
pub use self::quality_item::{q, qitem, Quality, QualityItem};
|
||||||
|
@ -193,21 +193,69 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::super::encoding::*;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
// copy of encoding from actix-web headers
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub enum Encoding {
|
||||||
|
Chunked,
|
||||||
|
Brotli,
|
||||||
|
Gzip,
|
||||||
|
Deflate,
|
||||||
|
Compress,
|
||||||
|
Identity,
|
||||||
|
Trailers,
|
||||||
|
EncodingExt(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Encoding {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use Encoding::*;
|
||||||
|
f.write_str(match *self {
|
||||||
|
Chunked => "chunked",
|
||||||
|
Brotli => "br",
|
||||||
|
Gzip => "gzip",
|
||||||
|
Deflate => "deflate",
|
||||||
|
Compress => "compress",
|
||||||
|
Identity => "identity",
|
||||||
|
Trailers => "trailers",
|
||||||
|
EncodingExt(ref s) => s.as_ref(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl str::FromStr for Encoding {
|
||||||
|
type Err = crate::error::ParseError;
|
||||||
|
fn from_str(s: &str) -> Result<Encoding, crate::error::ParseError> {
|
||||||
|
use Encoding::*;
|
||||||
|
match s {
|
||||||
|
"chunked" => Ok(Chunked),
|
||||||
|
"br" => Ok(Brotli),
|
||||||
|
"deflate" => Ok(Deflate),
|
||||||
|
"gzip" => Ok(Gzip),
|
||||||
|
"compress" => Ok(Compress),
|
||||||
|
"identity" => Ok(Identity),
|
||||||
|
"trailers" => Ok(Trailers),
|
||||||
|
_ => Ok(EncodingExt(s.to_owned())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_fmt_q_1() {
|
fn test_quality_item_fmt_q_1() {
|
||||||
|
use Encoding::*;
|
||||||
let x = qitem(Chunked);
|
let x = qitem(Chunked);
|
||||||
assert_eq!(format!("{}", x), "chunked");
|
assert_eq!(format!("{}", x), "chunked");
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_fmt_q_0001() {
|
fn test_quality_item_fmt_q_0001() {
|
||||||
|
use Encoding::*;
|
||||||
let x = QualityItem::new(Chunked, Quality(1));
|
let x = QualityItem::new(Chunked, Quality(1));
|
||||||
assert_eq!(format!("{}", x), "chunked; q=0.001");
|
assert_eq!(format!("{}", x), "chunked; q=0.001");
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_fmt_q_05() {
|
fn test_quality_item_fmt_q_05() {
|
||||||
|
use Encoding::*;
|
||||||
// Custom value
|
// Custom value
|
||||||
let x = QualityItem {
|
let x = QualityItem {
|
||||||
item: EncodingExt("identity".to_owned()),
|
item: EncodingExt("identity".to_owned()),
|
||||||
@ -218,6 +266,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_fmt_q_0() {
|
fn test_quality_item_fmt_q_0() {
|
||||||
|
use Encoding::*;
|
||||||
// Custom value
|
// Custom value
|
||||||
let x = QualityItem {
|
let x = QualityItem {
|
||||||
item: EncodingExt("identity".to_owned()),
|
item: EncodingExt("identity".to_owned()),
|
||||||
@ -228,6 +277,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str1() {
|
fn test_quality_item_from_str1() {
|
||||||
|
use Encoding::*;
|
||||||
let x: Result<QualityItem<Encoding>, _> = "chunked".parse();
|
let x: Result<QualityItem<Encoding>, _> = "chunked".parse();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x.unwrap(),
|
x.unwrap(),
|
||||||
@ -237,8 +287,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str2() {
|
fn test_quality_item_from_str2() {
|
||||||
|
use Encoding::*;
|
||||||
let x: Result<QualityItem<Encoding>, _> = "chunked; q=1".parse();
|
let x: Result<QualityItem<Encoding>, _> = "chunked; q=1".parse();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x.unwrap(),
|
x.unwrap(),
|
||||||
@ -248,8 +300,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str3() {
|
fn test_quality_item_from_str3() {
|
||||||
|
use Encoding::*;
|
||||||
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.5".parse();
|
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.5".parse();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x.unwrap(),
|
x.unwrap(),
|
||||||
@ -259,8 +313,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str4() {
|
fn test_quality_item_from_str4() {
|
||||||
|
use Encoding::*;
|
||||||
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.273".parse();
|
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.273".parse();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x.unwrap(),
|
x.unwrap(),
|
||||||
@ -270,16 +326,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str5() {
|
fn test_quality_item_from_str5() {
|
||||||
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.2739999".parse();
|
let x: Result<QualityItem<Encoding>, _> = "gzip; q=0.2739999".parse();
|
||||||
assert!(x.is_err());
|
assert!(x.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_from_str6() {
|
fn test_quality_item_from_str6() {
|
||||||
let x: Result<QualityItem<Encoding>, _> = "gzip; q=2".parse();
|
let x: Result<QualityItem<Encoding>, _> = "gzip; q=2".parse();
|
||||||
assert!(x.is_err());
|
assert!(x.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quality_item_ordering() {
|
fn test_quality_item_ordering() {
|
||||||
let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap();
|
let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::{fmt, str::FromStr};
|
use std::{fmt, str::FromStr};
|
||||||
|
|
||||||
use http::HeaderValue;
|
use super::HeaderValue;
|
||||||
|
|
||||||
use crate::{error::ParseError, header::HTTP_VALUE};
|
use crate::{error::ParseError, header::HTTP_VALUE};
|
||||||
|
|
||||||
/// Reads a comma-delimited raw header into a Vec.
|
/// Reads a comma-delimited raw header into a Vec.
|
||||||
|
@ -359,10 +359,10 @@ impl ResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use actix_http::Response;
|
/// # use actix_http::Response;
|
||||||
/// use actix_http::http::header::ContentType;
|
/// use actix_http::http::header;
|
||||||
///
|
///
|
||||||
/// Response::Ok()
|
/// Response::Ok()
|
||||||
/// .insert_header(ContentType(mime::APPLICATION_JSON))
|
/// .insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
|
||||||
/// .insert_header(("X-TEST", "value"))
|
/// .insert_header(("X-TEST", "value"))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
@ -386,10 +386,10 @@ impl ResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use actix_http::Response;
|
/// # use actix_http::Response;
|
||||||
/// use actix_http::http::header::ContentType;
|
/// use actix_http::http::header;
|
||||||
///
|
///
|
||||||
/// Response::Ok()
|
/// Response::Ok()
|
||||||
/// .append_header(ContentType(mime::APPLICATION_JSON))
|
/// .append_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
|
||||||
/// .append_header(("X-TEST", "value1"))
|
/// .append_header(("X-TEST", "value1"))
|
||||||
/// .append_header(("X-TEST", "value2"))
|
/// .append_header(("X-TEST", "value2"))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
@ -682,7 +682,7 @@ impl ResponseBuilder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !contains {
|
if !contains {
|
||||||
self.insert_header(header::ContentType(mime::APPLICATION_JSON));
|
self.insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.body(Body::from(body))
|
self.body(Body::from(body))
|
||||||
@ -1133,7 +1133,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn response_builder_header_insert_typed() {
|
fn response_builder_header_insert_typed() {
|
||||||
let mut res = Response::Ok();
|
let mut res = Response::Ok();
|
||||||
res.insert_header(header::ContentType(mime::APPLICATION_OCTET_STREAM));
|
res.insert_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM));
|
||||||
let res = res.finish();
|
let res = res.finish();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1158,8 +1158,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn response_builder_header_append_typed() {
|
fn response_builder_header_append_typed() {
|
||||||
let mut res = Response::Ok();
|
let mut res = Response::Ok();
|
||||||
res.append_header(header::ContentType(mime::APPLICATION_OCTET_STREAM));
|
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM));
|
||||||
res.append_header(header::ContentType(mime::APPLICATION_JSON));
|
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_JSON));
|
||||||
let res = res.finish();
|
let res = res.finish();
|
||||||
|
|
||||||
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
||||||
|
@ -7,8 +7,10 @@
|
|||||||
### Changed
|
### Changed
|
||||||
* `ConnectorService` type is renamed to `BoxConnectorService`. [#2081]
|
* `ConnectorService` type is renamed to `BoxConnectorService`. [#2081]
|
||||||
* Fix http/https encoding when enabling `compress` feature. [#2116]
|
* Fix http/https encoding when enabling `compress` feature. [#2116]
|
||||||
|
* Rename `TestResponse::header` to `append_header`, `set` to `insert_header`. `TestResponse` header methods now take `IntoHeaderPair` tuples. [#2094]
|
||||||
|
|
||||||
[#2081]: https://github.com/actix/actix-web/pull/2081
|
[#2081]: https://github.com/actix/actix-web/pull/2081
|
||||||
|
[#2094]: https://github.com/actix/actix-web/pull/2094
|
||||||
[#2114]: https://github.com/actix/actix-web/pull/2114
|
[#2114]: https://github.com/actix/actix-web/pull/2114
|
||||||
[#2116]: https://github.com/actix/actix-web/pull/2116
|
[#2116]: https://github.com/actix/actix-web/pull/2116
|
||||||
|
|
||||||
|
@ -189,12 +189,12 @@ impl ClientRequest {
|
|||||||
/// # #[actix_rt::main]
|
/// # #[actix_rt::main]
|
||||||
/// # async fn main() {
|
/// # async fn main() {
|
||||||
/// # use awc::Client;
|
/// # use awc::Client;
|
||||||
/// use awc::http::header::ContentType;
|
/// use awc::http::header::CONTENT_TYPE;
|
||||||
///
|
///
|
||||||
/// Client::new()
|
/// Client::new()
|
||||||
/// .get("http://www.rust-lang.org")
|
/// .get("http://www.rust-lang.org")
|
||||||
/// .insert_header(("X-TEST", "value"))
|
/// .insert_header(("X-TEST", "value"))
|
||||||
/// .insert_header(ContentType(mime::APPLICATION_JSON));
|
/// .insert_header((CONTENT_TYPE, mime::APPLICATION_JSON));
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn append_header<H>(mut self, header: H) -> Self
|
pub fn append_header<H>(mut self, header: H) -> Self
|
||||||
@ -548,6 +548,8 @@ impl fmt::Debug for ClientRequest {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use actix_http::http::header::HttpDate;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Client;
|
use crate::Client;
|
||||||
|
|
||||||
@ -564,7 +566,7 @@ mod tests {
|
|||||||
let req = Client::new()
|
let req = Client::new()
|
||||||
.put("/")
|
.put("/")
|
||||||
.version(Version::HTTP_2)
|
.version(Version::HTTP_2)
|
||||||
.insert_header(header::Date(SystemTime::now().into()))
|
.insert_header((header::DATE, HttpDate::from(SystemTime::now())))
|
||||||
.content_type("plain/text")
|
.content_type("plain/text")
|
||||||
.append_header((header::SERVER, "awc"));
|
.append_header((header::SERVER, "awc"));
|
||||||
|
|
||||||
|
@ -449,13 +449,13 @@ mod tests {
|
|||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_body() {
|
async fn test_body() {
|
||||||
let mut req = TestResponse::with_header(header::CONTENT_LENGTH, "xxxx").finish();
|
let mut req = TestResponse::with_header((header::CONTENT_LENGTH, "xxxx")).finish();
|
||||||
match req.body().await.err().unwrap() {
|
match req.body().await.err().unwrap() {
|
||||||
PayloadError::UnknownLength => {}
|
PayloadError::UnknownLength => {}
|
||||||
_ => unreachable!("error"),
|
_ => unreachable!("error"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut req = TestResponse::with_header(header::CONTENT_LENGTH, "10000000").finish();
|
let mut req = TestResponse::with_header((header::CONTENT_LENGTH, "10000000")).finish();
|
||||||
match req.body().await.err().unwrap() {
|
match req.body().await.err().unwrap() {
|
||||||
PayloadError::Overflow => {}
|
PayloadError::Overflow => {}
|
||||||
_ => unreachable!("error"),
|
_ => unreachable!("error"),
|
||||||
@ -497,23 +497,23 @@ mod tests {
|
|||||||
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
|
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
|
||||||
|
|
||||||
let mut req = TestResponse::default()
|
let mut req = TestResponse::default()
|
||||||
.header(
|
.insert_header((
|
||||||
header::CONTENT_TYPE,
|
header::CONTENT_TYPE,
|
||||||
header::HeaderValue::from_static("application/text"),
|
header::HeaderValue::from_static("application/text"),
|
||||||
)
|
))
|
||||||
.finish();
|
.finish();
|
||||||
let json = JsonBody::<_, MyObject>::new(&mut req).await;
|
let json = JsonBody::<_, MyObject>::new(&mut req).await;
|
||||||
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
|
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
|
||||||
|
|
||||||
let mut req = TestResponse::default()
|
let mut req = TestResponse::default()
|
||||||
.header(
|
.insert_header((
|
||||||
header::CONTENT_TYPE,
|
header::CONTENT_TYPE,
|
||||||
header::HeaderValue::from_static("application/json"),
|
header::HeaderValue::from_static("application/json"),
|
||||||
)
|
))
|
||||||
.header(
|
.insert_header((
|
||||||
header::CONTENT_LENGTH,
|
header::CONTENT_LENGTH,
|
||||||
header::HeaderValue::from_static("10000"),
|
header::HeaderValue::from_static("10000"),
|
||||||
)
|
))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
let json = JsonBody::<_, MyObject>::new(&mut req).limit(100).await;
|
let json = JsonBody::<_, MyObject>::new(&mut req).limit(100).await;
|
||||||
@ -523,14 +523,14 @@ mod tests {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let mut req = TestResponse::default()
|
let mut req = TestResponse::default()
|
||||||
.header(
|
.insert_header((
|
||||||
header::CONTENT_TYPE,
|
header::CONTENT_TYPE,
|
||||||
header::HeaderValue::from_static("application/json"),
|
header::HeaderValue::from_static("application/json"),
|
||||||
)
|
))
|
||||||
.header(
|
.insert_header((
|
||||||
header::CONTENT_LENGTH,
|
header::CONTENT_LENGTH,
|
||||||
header::HeaderValue::from_static("16"),
|
header::HeaderValue::from_static("16"),
|
||||||
)
|
))
|
||||||
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
//! Test helpers for actix http client to use during testing.
|
//! Test helpers for actix http client to use during testing.
|
||||||
use std::convert::TryFrom;
|
use actix_http::http::header::IntoHeaderPair;
|
||||||
|
use actix_http::http::{StatusCode, Version};
|
||||||
use actix_http::http::header::{Header, IntoHeaderValue};
|
|
||||||
use actix_http::http::{Error as HttpError, HeaderName, StatusCode, Version};
|
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
use actix_http::{
|
use actix_http::{
|
||||||
cookie::{Cookie, CookieJar},
|
cookie::{Cookie, CookieJar},
|
||||||
@ -34,13 +32,11 @@ impl Default for TestResponse {
|
|||||||
|
|
||||||
impl TestResponse {
|
impl TestResponse {
|
||||||
/// Create TestResponse and set header
|
/// Create TestResponse and set header
|
||||||
pub fn with_header<K, V>(key: K, value: V) -> Self
|
pub fn with_header<H>(header: H) -> Self
|
||||||
where
|
where
|
||||||
HeaderName: TryFrom<K>,
|
H: IntoHeaderPair,
|
||||||
<HeaderName as TryFrom<K>>::Error: Into<HttpError>,
|
|
||||||
V: IntoHeaderValue,
|
|
||||||
{
|
{
|
||||||
Self::default().header(key, value)
|
Self::default().insert_header(header)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set HTTP version of this response
|
/// Set HTTP version of this response
|
||||||
@ -49,28 +45,27 @@ impl TestResponse {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a header
|
/// Insert a header
|
||||||
pub fn set<H: Header>(mut self, hdr: H) -> Self {
|
pub fn insert_header<H>(mut self, header: H) -> Self
|
||||||
if let Ok(value) = hdr.try_into_value() {
|
where
|
||||||
self.head.headers.append(H::name(), value);
|
H: IntoHeaderPair,
|
||||||
|
{
|
||||||
|
if let Ok((key, value)) = header.try_into_header_pair() {
|
||||||
|
self.head.headers.insert(key, value);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
panic!("Can not set header");
|
panic!("Can not set header");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a header
|
/// Append a header
|
||||||
pub fn header<K, V>(mut self, key: K, value: V) -> Self
|
pub fn append_header<H>(mut self, header: H) -> Self
|
||||||
where
|
where
|
||||||
HeaderName: TryFrom<K>,
|
H: IntoHeaderPair,
|
||||||
<HeaderName as TryFrom<K>>::Error: Into<HttpError>,
|
|
||||||
V: IntoHeaderValue,
|
|
||||||
{
|
{
|
||||||
if let Ok(key) = HeaderName::try_from(key) {
|
if let Ok((key, value)) = header.try_into_header_pair() {
|
||||||
if let Ok(value) = value.try_into_value() {
|
|
||||||
self.head.headers.append(key, value);
|
self.head.headers.append(key, value);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
panic!("Can not create header");
|
panic!("Can not create header");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +110,8 @@ impl TestResponse {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use actix_http::http::header::HttpDate;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{cookie, http::header};
|
use crate::{cookie, http::header};
|
||||||
|
|
||||||
@ -122,7 +119,7 @@ mod tests {
|
|||||||
fn test_basics() {
|
fn test_basics() {
|
||||||
let res = TestResponse::default()
|
let res = TestResponse::default()
|
||||||
.version(Version::HTTP_2)
|
.version(Version::HTTP_2)
|
||||||
.set(header::Date(SystemTime::now().into()))
|
.insert_header((header::DATE, HttpDate::from(SystemTime::now())))
|
||||||
.cookie(cookie::Cookie::build("name", "value").finish())
|
.cookie(cookie::Cookie::build("name", "value").finish())
|
||||||
.finish();
|
.finish();
|
||||||
assert!(res.headers().contains_key(header::SET_COOKIE));
|
assert!(res.headers().contains_key(header::SET_COOKIE));
|
||||||
|
@ -2,10 +2,10 @@ use std::cmp::Ordering;
|
|||||||
|
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
|
||||||
use crate::header::{qitem, QualityItem};
|
use super::{qitem, QualityItem};
|
||||||
use crate::http::header;
|
use crate::http::header;
|
||||||
|
|
||||||
header! {
|
crate::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
|
||||||
@ -33,10 +33,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{Accept, qitem};
|
/// use actix_web::http::header::{Accept, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Accept(vec![
|
/// Accept(vec![
|
||||||
/// qitem(mime::TEXT_HTML),
|
/// qitem(mime::TEXT_HTML),
|
||||||
@ -45,10 +45,10 @@ header! {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{Accept, qitem};
|
/// use actix_web::http::header::{Accept, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Accept(vec![
|
/// Accept(vec![
|
||||||
/// qitem(mime::APPLICATION_JSON),
|
/// qitem(mime::APPLICATION_JSON),
|
||||||
@ -57,10 +57,10 @@ header! {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{Accept, QualityItem, q, qitem};
|
/// use actix_web::http::header::{Accept, QualityItem, q, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Accept(vec![
|
/// Accept(vec![
|
||||||
/// qitem(mime::TEXT_HTML),
|
/// qitem(mime::TEXT_HTML),
|
||||||
@ -116,8 +116,8 @@ header! {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fuzzing1() {
|
fn test_fuzzing1() {
|
||||||
use crate::test::TestRequest;
|
use actix_http::test::TestRequest;
|
||||||
let req = TestRequest::default().insert_header((crate::header::ACCEPT, "chunk#;e")).finish();
|
let req = TestRequest::default().insert_header((crate::http::header::ACCEPT, "chunk#;e")).finish();
|
||||||
let header = Accept::parse(&req);
|
let header = Accept::parse(&req);
|
||||||
assert!(header.is_ok());
|
assert!(header.is_ok());
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ impl Accept {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::header::q;
|
use crate::http::header::q;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mime_precedence() {
|
fn test_mime_precedence() {
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{Charset, QualityItem, ACCEPT_CHARSET};
|
use super::{Charset, QualityItem, ACCEPT_CHARSET};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Accept-Charset` header, defined in
|
/// `Accept-Charset` header, defined in
|
||||||
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.3)
|
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.3)
|
||||||
///
|
///
|
||||||
@ -22,20 +22,20 @@ header! {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{AcceptCharset, Charset, qitem};
|
/// use actix_web::http::header::{AcceptCharset, Charset, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// AcceptCharset(vec![qitem(Charset::Us_Ascii)])
|
/// AcceptCharset(vec![qitem(Charset::Us_Ascii)])
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{AcceptCharset, Charset, q, QualityItem};
|
/// use actix_web::http::header::{AcceptCharset, Charset, q, QualityItem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// AcceptCharset(vec![
|
/// AcceptCharset(vec![
|
||||||
/// QualityItem::new(Charset::Us_Ascii, q(900)),
|
/// QualityItem::new(Charset::Us_Ascii, q(900)),
|
||||||
@ -45,10 +45,10 @@ header! {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{AcceptCharset, Charset, qitem};
|
/// use actix_web::http::header::{AcceptCharset, Charset, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// AcceptCharset(vec![qitem(Charset::Ext("utf-8".to_owned()))])
|
/// AcceptCharset(vec![qitem(Charset::Ext("utf-8".to_owned()))])
|
||||||
/// );
|
/// );
|
@ -26,18 +26,20 @@ header! {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use hyper::header::{Headers, AcceptEncoding, Encoding, qitem};
|
/// use actix_web::HttpResponse;
|
||||||
|
/// use actix_web::http::header::{AcceptEncoding, Encoding, qitem};
|
||||||
///
|
///
|
||||||
/// let mut headers = Headers::new();
|
/// let mut builder = HttpResponse::new();
|
||||||
/// headers.set(
|
/// builder.insert_header(
|
||||||
/// AcceptEncoding(vec![qitem(Encoding::Chunked)])
|
/// AcceptEncoding(vec![qitem(Encoding::Chunked)])
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
/// ```
|
/// ```
|
||||||
/// use hyper::header::{Headers, AcceptEncoding, Encoding, qitem};
|
/// use actix_web::HttpResponse;
|
||||||
|
/// use actix_web::http::header::{AcceptEncoding, Encoding, qitem};
|
||||||
///
|
///
|
||||||
/// let mut headers = Headers::new();
|
/// let mut builder = HttpResponse::new();
|
||||||
/// headers.set(
|
/// builder.insert_header(
|
||||||
/// AcceptEncoding(vec![
|
/// AcceptEncoding(vec![
|
||||||
/// qitem(Encoding::Chunked),
|
/// qitem(Encoding::Chunked),
|
||||||
/// qitem(Encoding::Gzip),
|
/// qitem(Encoding::Gzip),
|
||||||
@ -46,10 +48,11 @@ header! {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
/// ```
|
/// ```
|
||||||
/// use hyper::header::{Headers, AcceptEncoding, Encoding, QualityItem, q, qitem};
|
/// use actix_web::HttpResponse;
|
||||||
|
/// use actix_web::http::header::{AcceptEncoding, Encoding, QualityItem, q, qitem};
|
||||||
///
|
///
|
||||||
/// let mut headers = Headers::new();
|
/// let mut builder = HttpResponse::new();
|
||||||
/// headers.set(
|
/// builder.insert_header(
|
||||||
/// AcceptEncoding(vec![
|
/// AcceptEncoding(vec![
|
||||||
/// qitem(Encoding::Chunked),
|
/// qitem(Encoding::Chunked),
|
||||||
/// QualityItem::new(Encoding::Gzip, q(600)),
|
/// QualityItem::new(Encoding::Gzip, q(600)),
|
@ -1,7 +1,7 @@
|
|||||||
use crate::header::{QualityItem, ACCEPT_LANGUAGE};
|
use super::{QualityItem, ACCEPT_LANGUAGE};
|
||||||
use language_tags::LanguageTag;
|
use language_tags::LanguageTag;
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Accept-Language` header, defined in
|
/// `Accept-Language` header, defined in
|
||||||
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.5)
|
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.5)
|
||||||
///
|
///
|
||||||
@ -24,10 +24,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use language_tags::langtag;
|
/// use language_tags::langtag;
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{AcceptLanguage, LanguageTag, qitem};
|
/// use actix_web::http::header::{AcceptLanguage, LanguageTag, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let mut langtag: LanguageTag = Default::default();
|
/// let mut langtag: LanguageTag = Default::default();
|
||||||
/// langtag.language = Some("en".to_owned());
|
/// langtag.language = Some("en".to_owned());
|
||||||
/// langtag.region = Some("US".to_owned());
|
/// langtag.region = Some("US".to_owned());
|
||||||
@ -40,10 +40,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use language_tags::langtag;
|
/// use language_tags::langtag;
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{AcceptLanguage, QualityItem, q, qitem};
|
/// use actix_web::http::header::{AcceptLanguage, QualityItem, q, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// AcceptLanguage(vec![
|
/// AcceptLanguage(vec![
|
||||||
/// qitem(langtag!(da)),
|
/// qitem(langtag!(da)),
|
@ -1,7 +1,7 @@
|
|||||||
use http::header;
|
use actix_http::http::Method;
|
||||||
use http::Method;
|
use crate::http::header;
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Allow` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.4.1)
|
/// `Allow` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.4.1)
|
||||||
///
|
///
|
||||||
/// The `Allow` header field lists the set of methods advertised as
|
/// The `Allow` header field lists the set of methods advertised as
|
||||||
@ -23,20 +23,20 @@ header! {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::{header::Allow, Method};
|
/// use actix_web::http::{header::Allow, Method};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Allow(vec![Method::GET])
|
/// Allow(vec![Method::GET])
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::{header::Allow, Method};
|
/// use actix_web::http::{header::Allow, Method};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Allow(vec![
|
/// Allow(vec![
|
||||||
/// Method::GET,
|
/// Method::GET,
|
@ -1,12 +1,12 @@
|
|||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use http::header;
|
use super::{
|
||||||
|
|
||||||
use crate::header::{
|
|
||||||
fmt_comma_delimited, from_comma_delimited, Header, IntoHeaderValue, Writer,
|
fmt_comma_delimited, from_comma_delimited, Header, IntoHeaderValue, Writer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::http::header;
|
||||||
|
|
||||||
/// `Cache-Control` header, defined in [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.2)
|
/// `Cache-Control` header, defined in [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.2)
|
||||||
///
|
///
|
||||||
/// The `Cache-Control` header field is used to specify directives for
|
/// The `Cache-Control` header field is used to specify directives for
|
||||||
@ -29,18 +29,18 @@ use crate::header::{
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{CacheControl, CacheDirective};
|
/// use actix_web::http::header::{CacheControl, CacheDirective};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(CacheControl(vec![CacheDirective::MaxAge(86400u32)]));
|
/// builder.insert_header(CacheControl(vec![CacheDirective::MaxAge(86400u32)]));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{CacheControl, CacheDirective};
|
/// use actix_web::http::header::{CacheControl, CacheDirective};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(CacheControl(vec![
|
/// builder.insert_header(CacheControl(vec![
|
||||||
/// CacheDirective::NoCache,
|
/// CacheDirective::NoCache,
|
||||||
/// CacheDirective::Private,
|
/// CacheDirective::Private,
|
||||||
@ -191,8 +191,8 @@ impl FromStr for CacheDirective {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::header::Header;
|
use crate::http::header::Header;
|
||||||
use crate::test::TestRequest;
|
use actix_http::test::TestRequest;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_multiple_headers() {
|
fn test_parse_multiple_headers() {
|
@ -10,7 +10,8 @@ use once_cell::sync::Lazy;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
|
||||||
use crate::header::{self, ExtendedValue, Header, IntoHeaderValue, Writer};
|
use crate::http::header;
|
||||||
|
use super::{ExtendedValue, Header, IntoHeaderValue, Writer};
|
||||||
|
|
||||||
/// Split at the index of the first `needle` if it exists or at the end.
|
/// Split at the index of the first `needle` if it exists or at the end.
|
||||||
fn split_once(haystack: &str, needle: char) -> (&str, &str) {
|
fn split_once(haystack: &str, needle: char) -> (&str, &str) {
|
||||||
@ -63,7 +64,7 @@ impl<'a> From<&'a str> for DispositionType {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::http::header::DispositionParam;
|
/// use actix_web::http::header::DispositionParam;
|
||||||
///
|
///
|
||||||
/// let param = DispositionParam::Filename(String::from("sample.txt"));
|
/// let param = DispositionParam::Filename(String::from("sample.txt"));
|
||||||
/// assert!(param.is_filename());
|
/// assert!(param.is_filename());
|
||||||
@ -240,7 +241,7 @@ impl DispositionParam {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::http::header::{
|
/// use actix_web::http::header::{
|
||||||
/// Charset, ContentDisposition, DispositionParam, DispositionType,
|
/// Charset, ContentDisposition, DispositionParam, DispositionType,
|
||||||
/// ExtendedValue,
|
/// ExtendedValue,
|
||||||
/// };
|
/// };
|
||||||
@ -554,8 +555,8 @@ impl fmt::Display for ContentDisposition {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{ContentDisposition, DispositionParam, DispositionType};
|
use super::{ContentDisposition, DispositionParam, DispositionType};
|
||||||
use crate::header::shared::Charset;
|
use crate::http::header::Charset;
|
||||||
use crate::header::{ExtendedValue, HeaderValue};
|
use crate::http::header::{ExtendedValue, HeaderValue};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_raw_basic() {
|
fn test_from_raw_basic() {
|
@ -1,7 +1,7 @@
|
|||||||
use crate::header::{QualityItem, CONTENT_LANGUAGE};
|
use super::{QualityItem, CONTENT_LANGUAGE};
|
||||||
use language_tags::LanguageTag;
|
use language_tags::LanguageTag;
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Content-Language` header, defined in
|
/// `Content-Language` header, defined in
|
||||||
/// [RFC7231](https://tools.ietf.org/html/rfc7231#section-3.1.3.2)
|
/// [RFC7231](https://tools.ietf.org/html/rfc7231#section-3.1.3.2)
|
||||||
///
|
///
|
||||||
@ -25,10 +25,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use language_tags::langtag;
|
/// use language_tags::langtag;
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{ContentLanguage, qitem};
|
/// use actix_web::http::header::{ContentLanguage, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ContentLanguage(vec![
|
/// ContentLanguage(vec![
|
||||||
/// qitem(langtag!(en)),
|
/// qitem(langtag!(en)),
|
||||||
@ -38,10 +38,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use language_tags::langtag;
|
/// use language_tags::langtag;
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{ContentLanguage, qitem};
|
/// use actix_web::http::header::{ContentLanguage, qitem};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ContentLanguage(vec![
|
/// ContentLanguage(vec![
|
||||||
/// qitem(langtag!(da)),
|
/// qitem(langtag!(da)),
|
@ -2,11 +2,11 @@ use std::fmt::{self, Display, Write};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::header::{
|
use super::{
|
||||||
HeaderValue, IntoHeaderValue, InvalidHeaderValue, Writer, CONTENT_RANGE,
|
HeaderValue, IntoHeaderValue, InvalidHeaderValue, Writer, CONTENT_RANGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Content-Range` header, defined in
|
/// `Content-Range` header, defined in
|
||||||
/// [RFC7233](http://tools.ietf.org/html/rfc7233#section-4.2)
|
/// [RFC7233](http://tools.ietf.org/html/rfc7233#section-4.2)
|
||||||
(ContentRange, CONTENT_RANGE) => [ContentRangeSpec]
|
(ContentRange, CONTENT_RANGE) => [ContentRangeSpec]
|
@ -1,7 +1,7 @@
|
|||||||
use crate::header::CONTENT_TYPE;
|
use super::CONTENT_TYPE;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Content-Type` header, defined in
|
/// `Content-Type` header, defined in
|
||||||
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)
|
/// [RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)
|
||||||
///
|
///
|
||||||
@ -31,20 +31,20 @@ header! {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::ContentType;
|
/// use actix_web::http::header::ContentType;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ContentType::json()
|
/// ContentType::json()
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::ContentType;
|
/// use actix_web::http::header::ContentType;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ContentType(mime::TEXT_HTML)
|
/// ContentType(mime::TEXT_HTML)
|
||||||
/// );
|
/// );
|
@ -1,7 +1,7 @@
|
|||||||
use crate::header::{HttpDate, DATE};
|
use super::{HttpDate, DATE};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Date` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.1.2)
|
/// `Date` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.1.2)
|
||||||
///
|
///
|
||||||
/// The `Date` header field represents the date and time at which the
|
/// The `Date` header field represents the date and time at which the
|
||||||
@ -21,10 +21,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::SystemTime;
|
/// use std::time::SystemTime;
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::Date;
|
/// use actix_web::http::header::Date;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Date(SystemTime::now().into())
|
/// Date(SystemTime::now().into())
|
||||||
/// );
|
/// );
|
@ -1,7 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Write};
|
use std::fmt::{self, Display, Write};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::header::{HeaderValue, IntoHeaderValue, InvalidHeaderValue, Writer};
|
use super::{HeaderValue, IntoHeaderValue, InvalidHeaderValue, Writer};
|
||||||
|
|
||||||
/// check that each char in the slice is either:
|
/// check that each char in the slice is either:
|
||||||
/// 1. `%x21`, or
|
/// 1. `%x21`, or
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{EntityTag, ETAG};
|
use super::{EntityTag, ETAG};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `ETag` header, defined in [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.3)
|
/// `ETag` header, defined in [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.3)
|
||||||
///
|
///
|
||||||
/// The `ETag` header field in a response provides the current entity-tag
|
/// The `ETag` header field in a response provides the current entity-tag
|
||||||
@ -28,20 +28,20 @@ header! {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{ETag, EntityTag};
|
/// use actix_web::http::header::{ETag, EntityTag};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ETag(EntityTag::new(false, "xyzzy".to_owned()))
|
/// ETag(EntityTag::new(false, "xyzzy".to_owned()))
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{ETag, EntityTag};
|
/// use actix_web::http::header::{ETag, EntityTag};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// ETag(EntityTag::new(true, "xyzzy".to_owned()))
|
/// ETag(EntityTag::new(true, "xyzzy".to_owned()))
|
||||||
/// );
|
/// );
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{HttpDate, EXPIRES};
|
use super::{HttpDate, EXPIRES};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Expires` header, defined in [RFC7234](http://tools.ietf.org/html/rfc7234#section-5.3)
|
/// `Expires` header, defined in [RFC7234](http://tools.ietf.org/html/rfc7234#section-5.3)
|
||||||
///
|
///
|
||||||
/// The `Expires` header field gives the date/time after which the
|
/// The `Expires` header field gives the date/time after which the
|
||||||
@ -23,10 +23,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::{SystemTime, Duration};
|
/// use std::time::{SystemTime, Duration};
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::Expires;
|
/// use actix_web::http::header::Expires;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let expiration = SystemTime::now() + Duration::from_secs(60 * 60 * 24);
|
/// let expiration = SystemTime::now() + Duration::from_secs(60 * 60 * 24);
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// Expires(expiration.into())
|
/// Expires(expiration.into())
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{EntityTag, IF_MATCH};
|
use super::{EntityTag, IF_MATCH};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `If-Match` header, defined in
|
/// `If-Match` header, defined in
|
||||||
/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.1)
|
/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.1)
|
||||||
///
|
///
|
||||||
@ -30,18 +30,18 @@ header! {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::IfMatch;
|
/// use actix_web::http::header::IfMatch;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(IfMatch::Any);
|
/// builder.insert_header(IfMatch::Any);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{IfMatch, EntityTag};
|
/// use actix_web::http::header::{IfMatch, EntityTag};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfMatch::Items(vec![
|
/// IfMatch::Items(vec![
|
||||||
/// EntityTag::new(false, "xyzzy".to_owned()),
|
/// EntityTag::new(false, "xyzzy".to_owned()),
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{HttpDate, IF_MODIFIED_SINCE};
|
use super::{HttpDate, IF_MODIFIED_SINCE};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `If-Modified-Since` header, defined in
|
/// `If-Modified-Since` header, defined in
|
||||||
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.3)
|
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.3)
|
||||||
///
|
///
|
||||||
@ -23,10 +23,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::{SystemTime, Duration};
|
/// use std::time::{SystemTime, Duration};
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::IfModifiedSince;
|
/// use actix_web::http::header::IfModifiedSince;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfModifiedSince(modified.into())
|
/// IfModifiedSince(modified.into())
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{EntityTag, IF_NONE_MATCH};
|
use super::{EntityTag, IF_NONE_MATCH};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `If-None-Match` header, defined in
|
/// `If-None-Match` header, defined in
|
||||||
/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.2)
|
/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.2)
|
||||||
///
|
///
|
||||||
@ -32,18 +32,18 @@ header! {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::IfNoneMatch;
|
/// use actix_web::http::header::IfNoneMatch;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(IfNoneMatch::Any);
|
/// builder.insert_header(IfNoneMatch::Any);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{IfNoneMatch, EntityTag};
|
/// use actix_web::http::header::{IfNoneMatch, EntityTag};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfNoneMatch::Items(vec![
|
/// IfNoneMatch::Items(vec![
|
||||||
/// EntityTag::new(false, "xyzzy".to_owned()),
|
/// EntityTag::new(false, "xyzzy".to_owned()),
|
||||||
@ -66,8 +66,8 @@ header! {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::IfNoneMatch;
|
use super::IfNoneMatch;
|
||||||
use crate::header::{EntityTag, Header, IF_NONE_MATCH};
|
use crate::http::header::{EntityTag, Header, IF_NONE_MATCH};
|
||||||
use crate::test::TestRequest;
|
use actix_http::test::TestRequest;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_if_none_match() {
|
fn test_if_none_match() {
|
@ -1,8 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Write};
|
use std::fmt::{self, Display, Write};
|
||||||
|
|
||||||
|
use crate::http::header;
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::header::{
|
use super::{
|
||||||
self, from_one_raw_str, EntityTag, Header, HeaderName, HeaderValue, HttpDate,
|
from_one_raw_str, EntityTag, Header, HeaderName, HeaderValue, HttpDate,
|
||||||
IntoHeaderValue, InvalidHeaderValue, Writer,
|
IntoHeaderValue, InvalidHeaderValue, Writer,
|
||||||
};
|
};
|
||||||
use crate::HttpMessage;
|
use crate::HttpMessage;
|
||||||
@ -36,10 +37,10 @@ use crate::HttpMessage;
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::{EntityTag, IfRange};
|
/// use actix_web::http::header::{EntityTag, IfRange};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfRange::EntityTag(
|
/// IfRange::EntityTag(
|
||||||
/// EntityTag::new(false, "abc".to_owned())
|
/// EntityTag::new(false, "abc".to_owned())
|
||||||
@ -49,9 +50,9 @@ use crate::HttpMessage;
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::{Duration, SystemTime};
|
/// use std::time::{Duration, SystemTime};
|
||||||
/// use actix_http::{http::header::IfRange, Response};
|
/// use actix_web::{http::header::IfRange, HttpResponse};
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let fetched = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
/// let fetched = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfRange::Date(fetched.into())
|
/// IfRange::Date(fetched.into())
|
||||||
@ -111,7 +112,7 @@ impl IntoHeaderValue for IfRange {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_if_range {
|
mod test_if_range {
|
||||||
use super::IfRange as HeaderField;
|
use super::IfRange as HeaderField;
|
||||||
use crate::header::*;
|
use crate::http::header::*;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
test_header!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
test_header!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{HttpDate, IF_UNMODIFIED_SINCE};
|
use super::{HttpDate, IF_UNMODIFIED_SINCE};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `If-Unmodified-Since` header, defined in
|
/// `If-Unmodified-Since` header, defined in
|
||||||
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.4)
|
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.4)
|
||||||
///
|
///
|
||||||
@ -24,10 +24,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::{SystemTime, Duration};
|
/// use std::time::{SystemTime, Duration};
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::IfUnmodifiedSince;
|
/// use actix_web::http::header::IfUnmodifiedSince;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// IfUnmodifiedSince(modified.into())
|
/// IfUnmodifiedSince(modified.into())
|
@ -1,6 +1,6 @@
|
|||||||
use crate::header::{HttpDate, LAST_MODIFIED};
|
use super::{HttpDate, LAST_MODIFIED};
|
||||||
|
|
||||||
header! {
|
crate::header! {
|
||||||
/// `Last-Modified` header, defined in
|
/// `Last-Modified` header, defined in
|
||||||
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.2)
|
/// [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.2)
|
||||||
///
|
///
|
||||||
@ -23,10 +23,10 @@ header! {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::time::{SystemTime, Duration};
|
/// use std::time::{SystemTime, Duration};
|
||||||
/// use actix_http::Response;
|
/// use actix_web::HttpResponse;
|
||||||
/// use actix_http::http::header::LastModified;
|
/// use actix_web::http::header::LastModified;
|
||||||
///
|
///
|
||||||
/// let mut builder = Response::Ok();
|
/// let mut builder = HttpResponse::Ok();
|
||||||
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
/// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24);
|
||||||
/// builder.insert_header(
|
/// builder.insert_header(
|
||||||
/// LastModified(modified.into())
|
/// LastModified(modified.into())
|
@ -7,6 +7,10 @@
|
|||||||
//! is used, such as `ContentType(pub Mime)`.
|
//! is used, such as `ContentType(pub Mime)`.
|
||||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use bytes::{BytesMut, Bytes};
|
||||||
|
|
||||||
|
pub use actix_http::http::header::*;
|
||||||
pub use self::accept_charset::AcceptCharset;
|
pub use self::accept_charset::AcceptCharset;
|
||||||
//pub use self::accept_encoding::AcceptEncoding;
|
//pub use self::accept_encoding::AcceptEncoding;
|
||||||
pub use self::accept::Accept;
|
pub use self::accept::Accept;
|
||||||
@ -18,7 +22,6 @@ pub use self::content_disposition::{
|
|||||||
};
|
};
|
||||||
pub use self::content_language::ContentLanguage;
|
pub use self::content_language::ContentLanguage;
|
||||||
pub use self::content_range::{ContentRange, ContentRangeSpec};
|
pub use self::content_range::{ContentRange, ContentRangeSpec};
|
||||||
pub use self::content_encoding::{ContentEncoding};
|
|
||||||
pub use self::content_type::ContentType;
|
pub use self::content_type::ContentType;
|
||||||
pub use self::date::Date;
|
pub use self::date::Date;
|
||||||
pub use self::etag::ETag;
|
pub use self::etag::ETag;
|
||||||
@ -29,7 +32,39 @@ pub use self::if_none_match::IfNoneMatch;
|
|||||||
pub use self::if_range::IfRange;
|
pub use self::if_range::IfRange;
|
||||||
pub use self::if_unmodified_since::IfUnmodifiedSince;
|
pub use self::if_unmodified_since::IfUnmodifiedSince;
|
||||||
pub use self::last_modified::LastModified;
|
pub use self::last_modified::LastModified;
|
||||||
|
pub use self::encoding::Encoding;
|
||||||
|
pub use self::entity::EntityTag;
|
||||||
//pub use self::range::{Range, ByteRangeSpec};
|
//pub use self::range::{Range, ByteRangeSpec};
|
||||||
|
pub(crate) use actix_http::http::header::{fmt_comma_delimited, from_comma_delimited, from_one_raw_str};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct Writer {
|
||||||
|
buf: BytesMut,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writer {
|
||||||
|
pub fn new() -> Writer {
|
||||||
|
Writer::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Bytes {
|
||||||
|
self.buf.split().freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for Writer {
|
||||||
|
#[inline]
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
self.buf.extend_from_slice(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
|
||||||
|
fmt::write(self, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -61,9 +96,9 @@ macro_rules! __hyper__tm {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod $tm{
|
mod $tm{
|
||||||
use std::str;
|
use std::str;
|
||||||
use http::Method;
|
use actix_http::http::Method;
|
||||||
use mime::*;
|
use mime::*;
|
||||||
use $crate::header::*;
|
use $crate::http::header::*;
|
||||||
use super::$id as HeaderField;
|
use super::$id as HeaderField;
|
||||||
$($tf)*
|
$($tf)*
|
||||||
}
|
}
|
||||||
@ -77,8 +112,7 @@ macro_rules! test_header {
|
|||||||
($id:ident, $raw:expr) => {
|
($id:ident, $raw:expr) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $id() {
|
fn $id() {
|
||||||
use super::*;
|
use actix_http::test;
|
||||||
use $crate::test;
|
|
||||||
|
|
||||||
let raw = $raw;
|
let raw = $raw;
|
||||||
let a: Vec<Vec<u8>> = raw.iter().map(|x| x.to_vec()).collect();
|
let a: Vec<Vec<u8>> = raw.iter().map(|x| x.to_vec()).collect();
|
||||||
@ -106,7 +140,7 @@ macro_rules! test_header {
|
|||||||
($id:ident, $raw:expr, $typed:expr) => {
|
($id:ident, $raw:expr, $typed:expr) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $id() {
|
fn $id() {
|
||||||
use $crate::test;
|
use actix_http::test;
|
||||||
|
|
||||||
let a: Vec<Vec<u8>> = $raw.iter().map(|x| x.to_vec()).collect();
|
let a: Vec<Vec<u8>> = $raw.iter().map(|x| x.to_vec()).collect();
|
||||||
let mut req = test::TestRequest::default();
|
let mut req = test::TestRequest::default();
|
||||||
@ -134,6 +168,7 @@ macro_rules! test_header {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! header {
|
macro_rules! header {
|
||||||
// $a:meta: Attributes associated with the header item (usually docs)
|
// $a:meta: Attributes associated with the header item (usually docs)
|
||||||
@ -341,7 +376,6 @@ mod allow;
|
|||||||
mod cache_control;
|
mod cache_control;
|
||||||
mod content_disposition;
|
mod content_disposition;
|
||||||
mod content_language;
|
mod content_language;
|
||||||
mod content_encoding;
|
|
||||||
mod content_range;
|
mod content_range;
|
||||||
mod content_type;
|
mod content_type;
|
||||||
mod date;
|
mod date;
|
||||||
@ -353,3 +387,5 @@ mod if_none_match;
|
|||||||
mod if_range;
|
mod if_range;
|
||||||
mod if_unmodified_since;
|
mod if_unmodified_since;
|
||||||
mod last_modified;
|
mod last_modified;
|
||||||
|
mod encoding;
|
||||||
|
mod entity;
|
@ -1,8 +1,8 @@
|
|||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use header::parsing::from_one_raw_str;
|
use super::parsing::from_one_raw_str;
|
||||||
use header::{Header, Raw};
|
use super::{Header, Raw};
|
||||||
|
|
||||||
/// `Range` header, defined in [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1)
|
/// `Range` header, defined in [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1)
|
||||||
///
|
///
|
2
src/http/mod.rs
Normal file
2
src/http/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod header;
|
||||||
|
pub use actix_http::http::*;
|
@ -84,6 +84,7 @@ pub mod error;
|
|||||||
mod extract;
|
mod extract;
|
||||||
pub mod guard;
|
pub mod guard;
|
||||||
mod handler;
|
mod handler;
|
||||||
|
pub mod http;
|
||||||
mod info;
|
mod info;
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
mod request;
|
mod request;
|
||||||
@ -102,7 +103,7 @@ pub mod web;
|
|||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
pub use actix_http::cookie;
|
pub use actix_http::cookie;
|
||||||
pub use actix_http::Response as HttpResponse;
|
pub use actix_http::Response as HttpResponse;
|
||||||
pub use actix_http::{body, http, Error, HttpMessage, ResponseError, Result};
|
pub use actix_http::{body, Error, HttpMessage, ResponseError, Result};
|
||||||
pub use actix_rt as rt;
|
pub use actix_rt as rt;
|
||||||
pub use actix_web_codegen::*;
|
pub use actix_web_codegen::*;
|
||||||
|
|
||||||
|
22
src/test.rs
22
src/test.rs
@ -8,8 +8,7 @@ use std::{fmt, net, thread, time};
|
|||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
use actix_http::cookie::Cookie;
|
use actix_http::cookie::Cookie;
|
||||||
use actix_http::http::header::{ContentType, HeaderMap, IntoHeaderPair};
|
use actix_http::http::{HeaderMap, Method, StatusCode, Uri, Version};
|
||||||
use actix_http::http::{Method, StatusCode, Uri, Version};
|
|
||||||
use actix_http::test::TestRequest as HttpTestRequest;
|
use actix_http::test::TestRequest as HttpTestRequest;
|
||||||
use actix_http::{ws, Extensions, HttpService, Request};
|
use actix_http::{ws, Extensions, HttpService, Request};
|
||||||
use actix_router::{Path, ResourceDef, Url};
|
use actix_router::{Path, ResourceDef, Url};
|
||||||
@ -31,6 +30,7 @@ use crate::app_service::AppInitServiceState;
|
|||||||
use crate::config::AppConfig;
|
use crate::config::AppConfig;
|
||||||
use crate::data::Data;
|
use crate::data::Data;
|
||||||
use crate::dev::{Body, MessageBody, Payload, Server};
|
use crate::dev::{Body, MessageBody, Payload, Server};
|
||||||
|
use crate::http::header::{ContentType, IntoHeaderPair};
|
||||||
use crate::rmap::ResourceMap;
|
use crate::rmap::ResourceMap;
|
||||||
use crate::service::{ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceRequest, ServiceResponse};
|
||||||
use crate::{Error, HttpRequest, HttpResponse};
|
use crate::{Error, HttpRequest, HttpResponse};
|
||||||
@ -162,7 +162,7 @@ where
|
|||||||
let mut resp = app
|
let mut resp = app
|
||||||
.call(req)
|
.call(req)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|_| panic!("read_response failed at application call"));
|
.unwrap_or_else(|e| panic!("read_response failed at application call: {}", e));
|
||||||
|
|
||||||
let mut body = resp.take_body();
|
let mut body = resp.take_body();
|
||||||
let mut bytes = BytesMut::new();
|
let mut bytes = BytesMut::new();
|
||||||
@ -254,8 +254,12 @@ where
|
|||||||
{
|
{
|
||||||
let body = read_body(res).await;
|
let body = read_body(res).await;
|
||||||
|
|
||||||
serde_json::from_slice(&body)
|
serde_json::from_slice(&body).unwrap_or_else(|e| {
|
||||||
.unwrap_or_else(|e| panic!("read_response_json failed during deserialization: {}", e))
|
panic!(
|
||||||
|
"read_response_json failed during deserialization of body: {:?}, {}",
|
||||||
|
body, e
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_stream<S>(mut stream: S) -> Result<Bytes, Error>
|
pub async fn load_stream<S>(mut stream: S) -> Result<Bytes, Error>
|
||||||
@ -311,8 +315,12 @@ where
|
|||||||
{
|
{
|
||||||
let body = read_response(app, req).await;
|
let body = read_response(app, req).await;
|
||||||
|
|
||||||
serde_json::from_slice(&body)
|
serde_json::from_slice(&body).unwrap_or_else(|_| {
|
||||||
.unwrap_or_else(|_| panic!("read_response_json failed during deserialization"))
|
panic!(
|
||||||
|
"read_response_json failed during deserialization of body: {:?}",
|
||||||
|
body
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test `Request` builder.
|
/// Test `Request` builder.
|
||||||
|
112
src/types/header.rs
Normal file
112
src/types/header.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
//! For header extractor helper documentation, see [`Header`](crate::types::Header).
|
||||||
|
|
||||||
|
use std::{fmt, ops};
|
||||||
|
|
||||||
|
use actix_utils::future::{err, ok, Ready};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
dev::Payload, error::ParseError, extract::FromRequest, http::header::Header as ParseHeader,
|
||||||
|
HttpRequest,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Extract typed headers from the request.
|
||||||
|
///
|
||||||
|
/// To extract a header, the inner type `T` must implement the
|
||||||
|
/// [`Header`](crate::http::header::Header) trait.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use actix_web::{get, web, http::header};
|
||||||
|
///
|
||||||
|
/// #[get("/")]
|
||||||
|
/// async fn index(date: web::Header<header::Date>) -> String {
|
||||||
|
/// format!("Request was sent at {}", date.to_string())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Header<T>(pub T);
|
||||||
|
|
||||||
|
impl<T> Header<T> {
|
||||||
|
/// Unwrap into the inner `T` value.
|
||||||
|
pub fn into_inner(self) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ops::Deref for Header<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ops::DerefMut for Header<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Debug for Header<T>
|
||||||
|
where
|
||||||
|
T: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Header: {:?}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Display for Header<T>
|
||||||
|
where
|
||||||
|
T: fmt::Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FromRequest for Header<T>
|
||||||
|
where
|
||||||
|
T: ParseHeader,
|
||||||
|
{
|
||||||
|
type Error = ParseError;
|
||||||
|
type Future = Ready<Result<Self, Self::Error>>;
|
||||||
|
type Config = ();
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||||
|
match ParseHeader::parse(req) {
|
||||||
|
Ok(header) => ok(Header(header)),
|
||||||
|
Err(e) => err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::http::{header, Method};
|
||||||
|
use crate::test::TestRequest;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_header_extract() {
|
||||||
|
let (req, mut pl) = TestRequest::default()
|
||||||
|
.insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
|
||||||
|
.insert_header((header::ALLOW, header::Allow(vec![Method::GET])))
|
||||||
|
.to_http_parts();
|
||||||
|
|
||||||
|
let s = Header::<header::ContentType>::from_request(&req, &mut pl)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(s.into_inner().0, mime::APPLICATION_JSON);
|
||||||
|
|
||||||
|
let s = Header::<header::Allow>::from_request(&req, &mut pl)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(s.into_inner().0, vec![Method::GET]);
|
||||||
|
|
||||||
|
assert!(Header::<header::Date>::from_request(&req, &mut pl)
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
// TODO: review visibility
|
// TODO: review visibility
|
||||||
mod either;
|
mod either;
|
||||||
pub(crate) mod form;
|
pub(crate) mod form;
|
||||||
|
mod header;
|
||||||
pub(crate) mod json;
|
pub(crate) mod json;
|
||||||
mod path;
|
mod path;
|
||||||
pub(crate) mod payload;
|
pub(crate) mod payload;
|
||||||
@ -11,6 +12,7 @@ pub(crate) mod readlines;
|
|||||||
|
|
||||||
pub use self::either::{Either, EitherExtractError};
|
pub use self::either::{Either, EitherExtractError};
|
||||||
pub use self::form::{Form, FormConfig};
|
pub use self::form::{Form, FormConfig};
|
||||||
|
pub use self::header::Header;
|
||||||
pub use self::json::{Json, JsonConfig};
|
pub use self::json::{Json, JsonConfig};
|
||||||
pub use self::path::{Path, PathConfig};
|
pub use self::path::{Path, PathConfig};
|
||||||
pub use self::payload::{Payload, PayloadConfig};
|
pub use self::payload::{Payload, PayloadConfig};
|
||||||
|
Loading…
Reference in New Issue
Block a user