mirror of
https://github.com/ntex-rs/ntex-extras.git
synced 2025-04-01 20:07:40 +03:00
fmt
This commit is contained in:
parent
3dd7dc68bd
commit
8bb852aa36
9 changed files with 225 additions and 667 deletions
|
@ -1,11 +1,9 @@
|
|||
# Cors Middleware for actix web framework [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-cors) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
# Cors Middleware for ntex framework [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-cors) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
**This crate moved to https://github.com/actix/actix-extras.**
|
||||
**This crate moved to https://github.com/ntex/ntex-extras.**
|
||||
|
||||
## Documentation & community resources
|
||||
|
||||
* [User Guide](https://actix.rs/docs/)
|
||||
* [API Documentation](https://docs.rs/actix-cors/)
|
||||
* [Chat on gitter](https://gitter.im/actix/actix)
|
||||
* Cargo package: [actix-cors](https://crates.io/crates/actix-cors)
|
||||
* Minimum supported Rust version: 1.34 or later
|
||||
* [API Documentation](https://docs.rs/ntex-cors/)
|
||||
* Cargo package: [ntex-cors](https://crates.io/crates/ntex-cors)
|
||||
* Minimum supported Rust version: 1.42 or later
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#![allow(
|
||||
type_alias_bounds,
|
||||
clippy::borrow_interior_mutable_const,
|
||||
clippy::type_complexity
|
||||
)]
|
||||
#![allow(type_alias_bounds, clippy::borrow_interior_mutable_const, clippy::type_complexity)]
|
||||
|
||||
//! Static files support
|
||||
use std::fmt::Write;
|
||||
|
@ -40,8 +36,7 @@ use self::error::{FilesError, UriSegmentError};
|
|||
pub use crate::named::NamedFile;
|
||||
pub use crate::range::HttpRange;
|
||||
|
||||
type HttpService<Err: ErrorRenderer> =
|
||||
BoxService<WebRequest<Err>, WebResponse, Err::Container>;
|
||||
type HttpService<Err: ErrorRenderer> = BoxService<WebRequest<Err>, WebResponse, Err::Container>;
|
||||
type HttpServiceFactory<Err: ErrorRenderer> =
|
||||
BoxServiceFactory<(), WebRequest<Err>, WebResponse, Err::Container, ()>;
|
||||
|
||||
|
@ -60,18 +55,14 @@ pub struct ChunkedReadFile {
|
|||
size: u64,
|
||||
offset: u64,
|
||||
file: Option<File>,
|
||||
fut:
|
||||
Option<LocalBoxFuture<'static, Result<(File, Bytes), BlockingError<io::Error>>>>,
|
||||
fut: Option<LocalBoxFuture<'static, Result<(File, Bytes), BlockingError<io::Error>>>>,
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
impl Stream for ChunkedReadFile {
|
||||
type Item = Result<Bytes, std::io::Error>;
|
||||
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
if let Some(ref mut fut) = self.fut {
|
||||
return match Pin::new(fut).poll(cx) {
|
||||
Poll::Ready(Ok((file, bytes))) => {
|
||||
|
@ -108,8 +99,7 @@ impl Stream for ChunkedReadFile {
|
|||
max_bytes = cmp::min(size.saturating_sub(counter), 65_536) as usize;
|
||||
let mut buf = Vec::with_capacity(max_bytes);
|
||||
file.seek(io::SeekFrom::Start(offset))?;
|
||||
let nbytes =
|
||||
file.by_ref().take(max_bytes as u64).read_to_end(&mut buf)?;
|
||||
let nbytes = file.by_ref().take(max_bytes as u64).read_to_end(&mut buf)?;
|
||||
if nbytes == 0 {
|
||||
return Err(io::ErrorKind::UnexpectedEof.into());
|
||||
}
|
||||
|
@ -122,8 +112,7 @@ impl Stream for ChunkedReadFile {
|
|||
}
|
||||
}
|
||||
|
||||
type DirectoryRenderer =
|
||||
dyn Fn(&Directory, &HttpRequest) -> Result<WebResponse, io::Error>;
|
||||
type DirectoryRenderer = dyn Fn(&Directory, &HttpRequest) -> Result<WebResponse, io::Error>;
|
||||
|
||||
/// A directory; responds with the generated directory listing.
|
||||
#[derive(Debug)]
|
||||
|
@ -171,10 +160,7 @@ macro_rules! encode_file_name {
|
|||
};
|
||||
}
|
||||
|
||||
fn directory_listing(
|
||||
dir: &Directory,
|
||||
req: &HttpRequest,
|
||||
) -> Result<WebResponse, io::Error> {
|
||||
fn directory_listing(dir: &Directory, req: &HttpRequest) -> Result<WebResponse, io::Error> {
|
||||
let index_of = format!("Index of {}", req.path());
|
||||
let mut body = String::new();
|
||||
let base = Path::new(req.path());
|
||||
|
@ -183,9 +169,7 @@ fn directory_listing(
|
|||
if dir.is_visible(&entry) {
|
||||
let entry = entry.unwrap();
|
||||
let p = match entry.path().strip_prefix(&dir.path) {
|
||||
Ok(p) if cfg!(windows) => {
|
||||
base.join(p).to_string_lossy().replace("\\", "/")
|
||||
}
|
||||
Ok(p) if cfg!(windows) => base.join(p).to_string_lossy().replace("\\", "/"),
|
||||
Ok(p) => base.join(p).to_string_lossy().into_owned(),
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
@ -223,9 +207,7 @@ fn directory_listing(
|
|||
index_of, index_of, body
|
||||
);
|
||||
Ok(WebResponse::new(
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html),
|
||||
HttpResponse::Ok().content_type("text/html; charset=utf-8").body(html),
|
||||
req.clone(),
|
||||
))
|
||||
}
|
||||
|
@ -324,8 +306,8 @@ impl<Err: ErrorRenderer> Files<Err> {
|
|||
/// Set custom directory renderer
|
||||
pub fn files_listing_renderer<F>(mut self, f: F) -> Self
|
||||
where
|
||||
for<'r, 's> F: Fn(&'r Directory, &'s HttpRequest) -> Result<WebResponse, io::Error>
|
||||
+ 'static,
|
||||
for<'r, 's> F:
|
||||
Fn(&'r Directory, &'s HttpRequest) -> Result<WebResponse, io::Error> + 'static,
|
||||
{
|
||||
self.renderer = Rc::new(f);
|
||||
self
|
||||
|
@ -397,9 +379,7 @@ impl<Err: ErrorRenderer> Files<Err> {
|
|||
> + 'static,
|
||||
{
|
||||
// create and configure default resource
|
||||
self.default = Some(Rc::new(boxed::factory(
|
||||
f.into_factory().map_init_err(|_| ()),
|
||||
)));
|
||||
self.default = Some(Rc::new(boxed::factory(f.into_factory().map_init_err(|_| ()))));
|
||||
|
||||
self
|
||||
}
|
||||
|
@ -567,10 +547,7 @@ where
|
|||
|
||||
named_file.flags = self.file_flags;
|
||||
let (req, _) = req.into_parts();
|
||||
Either::Left(ok(WebResponse::new(
|
||||
named_file.into_response(&req),
|
||||
req,
|
||||
)))
|
||||
Either::Left(ok(WebResponse::new(named_file.into_response(&req), req)))
|
||||
}
|
||||
Err(e) => self.handle_io_error(e, req),
|
||||
}
|
||||
|
@ -595,17 +572,13 @@ where
|
|||
match NamedFile::open(path) {
|
||||
Ok(mut named_file) => {
|
||||
if let Some(ref mime_override) = self.mime_override {
|
||||
let new_disposition =
|
||||
mime_override(&named_file.content_type.type_());
|
||||
let new_disposition = mime_override(&named_file.content_type.type_());
|
||||
named_file.content_disposition.disposition = new_disposition;
|
||||
}
|
||||
|
||||
named_file.flags = self.file_flags;
|
||||
let (req, _) = req.into_parts();
|
||||
Either::Left(ok(WebResponse::new(
|
||||
named_file.into_response(&req),
|
||||
req,
|
||||
)))
|
||||
Either::Left(ok(WebResponse::new(named_file.into_response(&req), req)))
|
||||
}
|
||||
Err(e) => self.handle_io_error(e, req),
|
||||
}
|
||||
|
@ -682,9 +655,8 @@ mod tests {
|
|||
#[ntex::test]
|
||||
async fn test_if_modified_since_without_if_none_match() {
|
||||
let file = NamedFile::open("Cargo.toml").unwrap();
|
||||
let since = hyperx::header::HttpDate::from(
|
||||
SystemTime::now().add(Duration::from_secs(60)),
|
||||
);
|
||||
let since =
|
||||
hyperx::header::HttpDate::from(SystemTime::now().add(Duration::from_secs(60)));
|
||||
|
||||
let req = TestRequest::default()
|
||||
.header(http::header::IF_MODIFIED_SINCE, since.to_string())
|
||||
|
@ -696,9 +668,8 @@ mod tests {
|
|||
#[ntex::test]
|
||||
async fn test_if_modified_since_with_if_none_match() {
|
||||
let file = NamedFile::open("Cargo.toml").unwrap();
|
||||
let since = hyperx::header::HttpDate::from(
|
||||
SystemTime::now().add(Duration::from_secs(60)),
|
||||
);
|
||||
let since =
|
||||
hyperx::header::HttpDate::from(SystemTime::now().add(Duration::from_secs(60)));
|
||||
|
||||
let req = TestRequest::default()
|
||||
.header(http::header::IF_NONE_MATCH, "miss_etag")
|
||||
|
@ -722,14 +693,9 @@ mod tests {
|
|||
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(resp.headers().get(http::header::CONTENT_TYPE).unwrap(), "text/x-toml");
|
||||
assert_eq!(
|
||||
resp.headers().get(http::header::CONTENT_TYPE).unwrap(),
|
||||
"text/x-toml"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"inline; filename=\"Cargo.toml\""
|
||||
);
|
||||
}
|
||||
|
@ -749,21 +715,14 @@ mod tests {
|
|||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"inline; filename=\"Cargo.toml\""
|
||||
);
|
||||
|
||||
let file = NamedFile::open("Cargo.toml")
|
||||
.unwrap()
|
||||
.disable_content_disposition();
|
||||
let file = NamedFile::open("Cargo.toml").unwrap().disable_content_disposition();
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert!(resp
|
||||
.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.is_none());
|
||||
assert!(resp.headers().get(http::header::CONTENT_DISPOSITION).is_none());
|
||||
}
|
||||
|
||||
// #[ntex::test]
|
||||
|
@ -795,9 +754,7 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_named_file_set_content_type() {
|
||||
let mut file = NamedFile::open("Cargo.toml")
|
||||
.unwrap()
|
||||
.set_content_type(mime::TEXT_XML);
|
||||
let mut file = NamedFile::open("Cargo.toml").unwrap().set_content_type(mime::TEXT_XML);
|
||||
{
|
||||
file.file();
|
||||
let _f: &File = &file;
|
||||
|
@ -808,14 +765,9 @@ mod tests {
|
|||
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(resp.headers().get(http::header::CONTENT_TYPE).unwrap(), "text/xml");
|
||||
assert_eq!(
|
||||
resp.headers().get(http::header::CONTENT_TYPE).unwrap(),
|
||||
"text/xml"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"inline; filename=\"Cargo.toml\""
|
||||
);
|
||||
}
|
||||
|
@ -833,23 +785,16 @@ mod tests {
|
|||
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(resp.headers().get(http::header::CONTENT_TYPE).unwrap(), "image/png");
|
||||
assert_eq!(
|
||||
resp.headers().get(http::header::CONTENT_TYPE).unwrap(),
|
||||
"image/png"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"inline; filename=\"test.png\""
|
||||
);
|
||||
}
|
||||
|
||||
#[ntex::test]
|
||||
async fn test_named_file_image_attachment() {
|
||||
use hyperx::header::{
|
||||
Charset, ContentDisposition, DispositionParam, DispositionType,
|
||||
};
|
||||
use hyperx::header::{Charset, ContentDisposition, DispositionParam, DispositionType};
|
||||
|
||||
let cd = ContentDisposition {
|
||||
disposition: DispositionType::Attachment,
|
||||
|
@ -859,9 +804,7 @@ mod tests {
|
|||
"test.png".to_string().into_bytes(),
|
||||
)],
|
||||
};
|
||||
let mut file = NamedFile::open("tests/test.png")
|
||||
.unwrap()
|
||||
.set_content_disposition(cd);
|
||||
let mut file = NamedFile::open("tests/test.png").unwrap().set_content_disposition(cd);
|
||||
{
|
||||
file.file();
|
||||
let _f: &File = &file;
|
||||
|
@ -872,14 +815,9 @@ mod tests {
|
|||
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(resp.headers().get(http::header::CONTENT_TYPE).unwrap(), "image/png");
|
||||
assert_eq!(
|
||||
resp.headers().get(http::header::CONTENT_TYPE).unwrap(),
|
||||
"image/png"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"attachment; filename=\"test.png\""
|
||||
);
|
||||
}
|
||||
|
@ -902,18 +840,15 @@ mod tests {
|
|||
"application/octet-stream"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"attachment; filename=\"test.binary\""
|
||||
);
|
||||
}
|
||||
|
||||
#[ntex::test]
|
||||
async fn test_named_file_status_code_text() {
|
||||
let mut file = NamedFile::open("Cargo.toml")
|
||||
.unwrap()
|
||||
.set_status_code(StatusCode::NOT_FOUND);
|
||||
let mut file =
|
||||
NamedFile::open("Cargo.toml").unwrap().set_status_code(StatusCode::NOT_FOUND);
|
||||
{
|
||||
file.file();
|
||||
let _f: &File = &file;
|
||||
|
@ -924,14 +859,9 @@ mod tests {
|
|||
|
||||
let req = TestRequest::default().to_http_request();
|
||||
let resp = test::respond_to(file, &req).await;
|
||||
assert_eq!(resp.headers().get(http::header::CONTENT_TYPE).unwrap(), "text/x-toml");
|
||||
assert_eq!(
|
||||
resp.headers().get(http::header::CONTENT_TYPE).unwrap(),
|
||||
"text/x-toml"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.unwrap(),
|
||||
resp.headers().get(http::header::CONTENT_DISPOSITION).unwrap(),
|
||||
"inline; filename=\"Cargo.toml\""
|
||||
);
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
@ -943,13 +873,9 @@ mod tests {
|
|||
DispositionType::Attachment
|
||||
}
|
||||
|
||||
let mut srv = test::init_service(
|
||||
App::new().service(
|
||||
Files::new("/", ".")
|
||||
.mime_override(all_attachment)
|
||||
.index_file("Cargo.toml"),
|
||||
),
|
||||
)
|
||||
let mut srv = test::init_service(App::new().service(
|
||||
Files::new("/", ".").mime_override(all_attachment).index_file("Cargo.toml"),
|
||||
))
|
||||
.await;
|
||||
|
||||
let request = TestRequest::get().uri("/").to_request();
|
||||
|
@ -960,9 +886,8 @@ mod tests {
|
|||
.headers()
|
||||
.get(http::header::CONTENT_DISPOSITION)
|
||||
.expect("To have CONTENT_DISPOSITION");
|
||||
let content_disposition = content_disposition
|
||||
.to_str()
|
||||
.expect("Convert CONTENT_DISPOSITION to str");
|
||||
let content_disposition =
|
||||
content_disposition.to_str().expect("Convert CONTENT_DISPOSITION to str");
|
||||
assert_eq!(content_disposition, "attachment; filename=\"Cargo.toml\"");
|
||||
}
|
||||
|
||||
|
@ -1005,12 +930,8 @@ mod tests {
|
|||
.to_request();
|
||||
|
||||
let response = test::call_service(&mut srv, request).await;
|
||||
let contentrange = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_RANGE)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
let contentrange =
|
||||
response.headers().get(http::header::CONTENT_RANGE).unwrap().to_str().unwrap();
|
||||
|
||||
assert_eq!(contentrange, "bytes 10-20/100");
|
||||
|
||||
|
@ -1021,12 +942,8 @@ mod tests {
|
|||
.to_request();
|
||||
let response = test::call_service(&mut srv, request).await;
|
||||
|
||||
let contentrange = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_RANGE)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
let contentrange =
|
||||
response.headers().get(http::header::CONTENT_RANGE).unwrap().to_str().unwrap();
|
||||
|
||||
assert_eq!(contentrange, "bytes */100");
|
||||
}
|
||||
|
@ -1077,9 +994,7 @@ mod tests {
|
|||
// assert_eq!(contentlength, "100");
|
||||
|
||||
// chunked
|
||||
let request = TestRequest::get()
|
||||
.uri("/t%65st/tests/test.binary")
|
||||
.to_request();
|
||||
let request = TestRequest::get().uri("/t%65st/tests/test.binary").to_request();
|
||||
let response = test::call_service(&mut srv, request).await;
|
||||
|
||||
// with enabled compression
|
||||
|
@ -1128,9 +1043,7 @@ mod tests {
|
|||
App::new().service(Files::new("/", ".").index_file("Cargo.toml")),
|
||||
)
|
||||
.await;
|
||||
let request = TestRequest::get()
|
||||
.uri("/tests/test%20space.binary")
|
||||
.to_request();
|
||||
let request = TestRequest::get().uri("/tests/test%20space.binary").to_request();
|
||||
let response = test::call_service(&srv, request).await;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
|
@ -1143,19 +1056,13 @@ mod tests {
|
|||
async fn test_files_not_allowed() {
|
||||
let mut srv = test::init_service(App::new().service(Files::new("/", "."))).await;
|
||||
|
||||
let req = TestRequest::default()
|
||||
.uri("/Cargo.toml")
|
||||
.method(Method::POST)
|
||||
.to_request();
|
||||
let req = TestRequest::default().uri("/Cargo.toml").method(Method::POST).to_request();
|
||||
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||
|
||||
let mut srv = test::init_service(App::new().service(Files::new("/", "."))).await;
|
||||
let req = TestRequest::default()
|
||||
.method(Method::PUT)
|
||||
.uri("/Cargo.toml")
|
||||
.to_request();
|
||||
let req = TestRequest::default().method(Method::PUT).uri("/Cargo.toml").to_request();
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||
}
|
||||
|
@ -1167,10 +1074,7 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::default()
|
||||
.uri("/Cargo.toml")
|
||||
.method(Method::POST)
|
||||
.to_request();
|
||||
let req = TestRequest::default().uri("/Cargo.toml").method(Method::POST).to_request();
|
||||
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
@ -1214,11 +1118,7 @@ mod tests {
|
|||
let res = test::call_service(&mut srv, request).await;
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
res.headers()
|
||||
.get(http::header::CONTENT_ENCODING)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
res.headers().get(http::header::CONTENT_ENCODING).unwrap().to_str().unwrap(),
|
||||
"gzip"
|
||||
);
|
||||
}
|
||||
|
@ -1233,10 +1133,9 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_static_files() {
|
||||
let mut srv = test::init_service(
|
||||
App::new().service(Files::new("/", ".").show_files_listing()),
|
||||
)
|
||||
.await;
|
||||
let mut srv =
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing()))
|
||||
.await;
|
||||
let req = TestRequest::with_uri("/missing").to_request();
|
||||
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
|
@ -1248,10 +1147,9 @@ mod tests {
|
|||
let resp = test::call_service(&mut srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let mut srv = test::init_service(
|
||||
App::new().service(Files::new("/", ".").show_files_listing()),
|
||||
)
|
||||
.await;
|
||||
let mut srv =
|
||||
test::init_service(App::new().service(Files::new("/", ".").show_files_listing()))
|
||||
.await;
|
||||
let req = TestRequest::with_uri("/tests").to_request();
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
assert_eq!(
|
||||
|
@ -1275,13 +1173,9 @@ mod tests {
|
|||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
// should redirect if index present
|
||||
let mut srv = test::init_service(
|
||||
App::new().service(
|
||||
Files::new("/", ".")
|
||||
.index_file("test.png")
|
||||
.redirect_to_slash_directory(),
|
||||
),
|
||||
)
|
||||
let mut srv = test::init_service(App::new().service(
|
||||
Files::new("/", ".").index_file("test.png").redirect_to_slash_directory(),
|
||||
))
|
||||
.await;
|
||||
let req = TestRequest::with_uri("/tests").to_request();
|
||||
let resp = test::call_service(&mut srv, req).await;
|
||||
|
|
|
@ -100,10 +100,7 @@ impl NamedFile {
|
|||
None,
|
||||
filename.into_owned().into_bytes(),
|
||||
)];
|
||||
let cd = ContentDisposition {
|
||||
disposition,
|
||||
parameters,
|
||||
};
|
||||
let cd = ContentDisposition { disposition, parameters };
|
||||
(ct, cd)
|
||||
};
|
||||
|
||||
|
@ -256,13 +253,15 @@ impl NamedFile {
|
|||
pub fn into_response(self, req: &HttpRequest) -> HttpResponse {
|
||||
if self.status_code != StatusCode::OK {
|
||||
let mut resp = HttpResponse::build(self.status_code);
|
||||
resp.header(http::header::CONTENT_TYPE, self.content_type.to_string())
|
||||
.if_true(self.flags.contains(Flags::CONTENT_DISPOSITION), |res| {
|
||||
resp.header(http::header::CONTENT_TYPE, self.content_type.to_string()).if_true(
|
||||
self.flags.contains(Flags::CONTENT_DISPOSITION),
|
||||
|res| {
|
||||
res.header(
|
||||
http::header::CONTENT_DISPOSITION,
|
||||
self.content_disposition.to_string(),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
if let Some(current_encoding) = self.encoding {
|
||||
resp.encoding(current_encoding);
|
||||
}
|
||||
|
@ -276,16 +275,9 @@ impl NamedFile {
|
|||
return resp.streaming(reader);
|
||||
}
|
||||
|
||||
let etag = if self.flags.contains(Flags::ETAG) {
|
||||
self.etag()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let last_modified = if self.flags.contains(Flags::LAST_MD) {
|
||||
self.last_modified()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let etag = if self.flags.contains(Flags::ETAG) { self.etag() } else { None };
|
||||
let last_modified =
|
||||
if self.flags.contains(Flags::LAST_MD) { self.last_modified() } else { None };
|
||||
|
||||
// check preconditions
|
||||
let precondition_failed = if !any_match(etag.as_ref(), req) {
|
||||
|
@ -293,9 +285,9 @@ impl NamedFile {
|
|||
} else if let (Some(ref m), Some(header::IfUnmodifiedSince(ref since))) = {
|
||||
let mut header = None;
|
||||
for hdr in req.headers().get_all(http::header::IF_UNMODIFIED_SINCE) {
|
||||
if let Ok(v) = header::IfUnmodifiedSince::parse_header(
|
||||
&header::Raw::from(hdr.as_bytes()),
|
||||
) {
|
||||
if let Ok(v) =
|
||||
header::IfUnmodifiedSince::parse_header(&header::Raw::from(hdr.as_bytes()))
|
||||
{
|
||||
header = Some(v);
|
||||
break;
|
||||
}
|
||||
|
@ -321,9 +313,9 @@ impl NamedFile {
|
|||
} else if let (Some(ref m), Some(header::IfModifiedSince(ref since))) = {
|
||||
let mut header = None;
|
||||
for hdr in req.headers().get_all(http::header::IF_MODIFIED_SINCE) {
|
||||
if let Ok(v) = header::IfModifiedSince::parse_header(&header::Raw::from(
|
||||
hdr.as_bytes(),
|
||||
)) {
|
||||
if let Ok(v) =
|
||||
header::IfModifiedSince::parse_header(&header::Raw::from(hdr.as_bytes()))
|
||||
{
|
||||
header = Some(v);
|
||||
break;
|
||||
}
|
||||
|
@ -341,23 +333,22 @@ impl NamedFile {
|
|||
};
|
||||
|
||||
let mut resp = HttpResponse::build(self.status_code);
|
||||
resp.header(http::header::CONTENT_TYPE, self.content_type.to_string())
|
||||
.if_true(self.flags.contains(Flags::CONTENT_DISPOSITION), |res| {
|
||||
resp.header(http::header::CONTENT_TYPE, self.content_type.to_string()).if_true(
|
||||
self.flags.contains(Flags::CONTENT_DISPOSITION),
|
||||
|res| {
|
||||
res.header(
|
||||
http::header::CONTENT_DISPOSITION,
|
||||
self.content_disposition.to_string(),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
// default compressing
|
||||
if let Some(current_encoding) = self.encoding {
|
||||
resp.encoding(current_encoding);
|
||||
}
|
||||
|
||||
resp.if_some(last_modified, |lm, resp| {
|
||||
resp.header(
|
||||
http::header::LAST_MODIFIED,
|
||||
header::LastModified(lm).to_string(),
|
||||
);
|
||||
resp.header(http::header::LAST_MODIFIED, header::LastModified(lm).to_string());
|
||||
})
|
||||
.if_some(etag, |etag, resp| {
|
||||
resp.header(http::header::ETAG, header::ETag(etag).to_string());
|
||||
|
@ -377,18 +368,10 @@ impl NamedFile {
|
|||
resp.encoding(ContentEncoding::Identity);
|
||||
resp.header(
|
||||
http::header::CONTENT_RANGE,
|
||||
format!(
|
||||
"bytes {}-{}/{}",
|
||||
offset,
|
||||
offset + length - 1,
|
||||
self.md.len()
|
||||
),
|
||||
format!("bytes {}-{}/{}", offset, offset + length - 1, self.md.len()),
|
||||
);
|
||||
} else {
|
||||
resp.header(
|
||||
http::header::CONTENT_RANGE,
|
||||
format!("bytes */{}", length),
|
||||
);
|
||||
resp.header(http::header::CONTENT_RANGE, format!("bytes */{}", length));
|
||||
return resp.status(StatusCode::RANGE_NOT_SATISFIABLE).finish();
|
||||
};
|
||||
} else {
|
||||
|
|
|
@ -75,10 +75,7 @@ impl HttpRange {
|
|||
end - start + 1
|
||||
};
|
||||
|
||||
Ok(Some(HttpRange {
|
||||
start: start as u64,
|
||||
length: length as u64,
|
||||
}))
|
||||
Ok(Some(HttpRange { start: start as u64, length: length as u64 }))
|
||||
}
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
@ -122,180 +119,55 @@ mod tests {
|
|||
T("bytes=0x01-0x02", 10, vec![]),
|
||||
T("bytes= ", 10, vec![]),
|
||||
T("bytes= , , , ", 10, vec![]),
|
||||
T(
|
||||
"bytes=0-9",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 10,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=0-",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 10,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=5-",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 5,
|
||||
length: 5,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=0-20",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 10,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=15-,0-5",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 6,
|
||||
}],
|
||||
),
|
||||
T("bytes=0-9", 10, vec![HttpRange { start: 0, length: 10 }]),
|
||||
T("bytes=0-", 10, vec![HttpRange { start: 0, length: 10 }]),
|
||||
T("bytes=5-", 10, vec![HttpRange { start: 5, length: 5 }]),
|
||||
T("bytes=0-20", 10, vec![HttpRange { start: 0, length: 10 }]),
|
||||
T("bytes=15-,0-5", 10, vec![HttpRange { start: 0, length: 6 }]),
|
||||
T(
|
||||
"bytes=1-2,5-",
|
||||
10,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 1,
|
||||
length: 2,
|
||||
},
|
||||
HttpRange {
|
||||
start: 5,
|
||||
length: 5,
|
||||
},
|
||||
],
|
||||
vec![HttpRange { start: 1, length: 2 }, HttpRange { start: 5, length: 5 }],
|
||||
),
|
||||
T(
|
||||
"bytes=-2 , 7-",
|
||||
11,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 9,
|
||||
length: 2,
|
||||
},
|
||||
HttpRange {
|
||||
start: 7,
|
||||
length: 4,
|
||||
},
|
||||
],
|
||||
vec![HttpRange { start: 9, length: 2 }, HttpRange { start: 7, length: 4 }],
|
||||
),
|
||||
T(
|
||||
"bytes=0-0 ,2-2, 7-",
|
||||
11,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 0,
|
||||
length: 1,
|
||||
},
|
||||
HttpRange {
|
||||
start: 2,
|
||||
length: 1,
|
||||
},
|
||||
HttpRange {
|
||||
start: 7,
|
||||
length: 4,
|
||||
},
|
||||
HttpRange { start: 0, length: 1 },
|
||||
HttpRange { start: 2, length: 1 },
|
||||
HttpRange { start: 7, length: 4 },
|
||||
],
|
||||
),
|
||||
T(
|
||||
"bytes=-5",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 5,
|
||||
length: 5,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=-15",
|
||||
10,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 10,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=0-499",
|
||||
10000,
|
||||
vec![HttpRange {
|
||||
start: 0,
|
||||
length: 500,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=500-999",
|
||||
10000,
|
||||
vec![HttpRange {
|
||||
start: 500,
|
||||
length: 500,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=-500",
|
||||
10000,
|
||||
vec![HttpRange {
|
||||
start: 9500,
|
||||
length: 500,
|
||||
}],
|
||||
),
|
||||
T(
|
||||
"bytes=9500-",
|
||||
10000,
|
||||
vec![HttpRange {
|
||||
start: 9500,
|
||||
length: 500,
|
||||
}],
|
||||
),
|
||||
T("bytes=-5", 10, vec![HttpRange { start: 5, length: 5 }]),
|
||||
T("bytes=-15", 10, vec![HttpRange { start: 0, length: 10 }]),
|
||||
T("bytes=0-499", 10000, vec![HttpRange { start: 0, length: 500 }]),
|
||||
T("bytes=500-999", 10000, vec![HttpRange { start: 500, length: 500 }]),
|
||||
T("bytes=-500", 10000, vec![HttpRange { start: 9500, length: 500 }]),
|
||||
T("bytes=9500-", 10000, vec![HttpRange { start: 9500, length: 500 }]),
|
||||
T(
|
||||
"bytes=0-0,-1",
|
||||
10000,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 0,
|
||||
length: 1,
|
||||
},
|
||||
HttpRange {
|
||||
start: 9999,
|
||||
length: 1,
|
||||
},
|
||||
],
|
||||
vec![HttpRange { start: 0, length: 1 }, HttpRange { start: 9999, length: 1 }],
|
||||
),
|
||||
T(
|
||||
"bytes=500-600,601-999",
|
||||
10000,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 500,
|
||||
length: 101,
|
||||
},
|
||||
HttpRange {
|
||||
start: 601,
|
||||
length: 399,
|
||||
},
|
||||
HttpRange { start: 500, length: 101 },
|
||||
HttpRange { start: 601, length: 399 },
|
||||
],
|
||||
),
|
||||
T(
|
||||
"bytes=500-700,601-999",
|
||||
10000,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 500,
|
||||
length: 201,
|
||||
},
|
||||
HttpRange {
|
||||
start: 601,
|
||||
length: 399,
|
||||
},
|
||||
HttpRange { start: 500, length: 201 },
|
||||
HttpRange { start: 601, length: 399 },
|
||||
],
|
||||
),
|
||||
// Match Apache laxity:
|
||||
|
@ -303,18 +175,9 @@ mod tests {
|
|||
"bytes= 1 -2 , 4- 5, 7 - 8 , ,,",
|
||||
11,
|
||||
vec![
|
||||
HttpRange {
|
||||
start: 1,
|
||||
length: 2,
|
||||
},
|
||||
HttpRange {
|
||||
start: 4,
|
||||
length: 2,
|
||||
},
|
||||
HttpRange {
|
||||
start: 7,
|
||||
length: 2,
|
||||
},
|
||||
HttpRange { start: 1, length: 2 },
|
||||
HttpRange { start: 4, length: 2 },
|
||||
HttpRange { start: 7, length: 2 },
|
||||
],
|
||||
),
|
||||
];
|
||||
|
|
|
@ -62,9 +62,7 @@ use ntex::http::header::{self, HeaderValue};
|
|||
use ntex::http::{Extensions, HttpMessage, Payload};
|
||||
use ntex::service::{Service, Transform};
|
||||
use ntex::web::dev::{WebRequest, WebResponse};
|
||||
use ntex::web::{
|
||||
DefaultError, ErrorRenderer, FromRequest, HttpRequest, WebResponseError,
|
||||
};
|
||||
use ntex::web::{DefaultError, ErrorRenderer, FromRequest, HttpRequest, WebResponseError};
|
||||
|
||||
/// The extractor type to obtain your identity from a request.
|
||||
///
|
||||
|
@ -219,10 +217,7 @@ pub struct IdentityService<T, Err> {
|
|||
impl<T, Err> IdentityService<T, Err> {
|
||||
/// Create new identity service with specified backend.
|
||||
pub fn new(backend: T) -> Self {
|
||||
IdentityService {
|
||||
backend: Rc::new(backend),
|
||||
_t: PhantomData,
|
||||
}
|
||||
IdentityService { backend: Rc::new(backend), _t: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,11 +255,7 @@ pub struct IdentityServiceMiddleware<S, T, Err> {
|
|||
|
||||
impl<S, T, Err> Clone for IdentityServiceMiddleware<S, T, Err> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
backend: self.backend.clone(),
|
||||
service: self.service.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
Self { backend: self.backend.clone(), service: self.service.clone(), _t: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,8 +289,7 @@ where
|
|||
async move {
|
||||
match fut.await {
|
||||
Ok(id) => {
|
||||
req.extensions_mut()
|
||||
.insert(IdentityItem { id, changed: false });
|
||||
req.extensions_mut().insert(IdentityItem { id, changed: false });
|
||||
|
||||
// https://github.com/actix/actix-web/issues/1263
|
||||
let fut = { srv.call(req) };
|
||||
|
@ -400,11 +390,7 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
|
|||
}
|
||||
|
||||
let mut jar = CookieJar::new();
|
||||
let key = if self.legacy_supported() {
|
||||
&self.key
|
||||
} else {
|
||||
&self.key_v2
|
||||
};
|
||||
let key = if self.legacy_supported() { &self.key } else { &self.key_v2 };
|
||||
if add_cookie {
|
||||
jar.private(&key).add(cookie);
|
||||
} else {
|
||||
|
@ -412,8 +398,7 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
|
|||
jar.private(&key).remove(cookie);
|
||||
}
|
||||
for cookie in jar.delta() {
|
||||
let val =
|
||||
HeaderValue::from_str(&cookie.to_string()).map_err(HttpError::from)?;
|
||||
let val = HeaderValue::from_str(&cookie.to_string()).map_err(HttpError::from)?;
|
||||
resp.headers_mut().append(header::SET_COOKIE, val);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -432,11 +417,7 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
res.or_else(|| {
|
||||
jar.private(&self.key_v2)
|
||||
.get(&self.name)
|
||||
.and_then(|c| self.parse(c))
|
||||
})
|
||||
res.or_else(|| jar.private(&self.key_v2).get(&self.name).and_then(|c| self.parse(c)))
|
||||
}
|
||||
|
||||
fn parse(&self, cookie: Cookie) -> Option<CookieValue> {
|
||||
|
@ -575,19 +556,12 @@ impl<Err: ErrorRenderer> IdentityPolicy<Err> for CookieIdentityPolicy<Err> {
|
|||
type ResponseFuture = Ready<Result<(), CookieIdentityPolicyError>>;
|
||||
|
||||
fn from_request(&self, req: &mut WebRequest<Err>) -> Self::Future {
|
||||
ok(self.0.load(req).map(
|
||||
|CookieValue {
|
||||
identity,
|
||||
login_timestamp,
|
||||
..
|
||||
}| {
|
||||
if self.0.requires_oob_data() {
|
||||
req.extensions_mut()
|
||||
.insert(CookieIdentityExtention { login_timestamp });
|
||||
}
|
||||
identity
|
||||
},
|
||||
))
|
||||
ok(self.0.load(req).map(|CookieValue { identity, login_timestamp, .. }| {
|
||||
if self.0.requires_oob_data() {
|
||||
req.extensions_mut().insert(CookieIdentityExtention { login_timestamp });
|
||||
}
|
||||
identity
|
||||
}))
|
||||
}
|
||||
|
||||
fn to_response(
|
||||
|
@ -609,9 +583,8 @@ impl<Err: ErrorRenderer> IdentityPolicy<Err> for CookieIdentityPolicy<Err> {
|
|||
} else if self.0.always_update_cookie() && id.is_some() {
|
||||
let visit_timestamp = SystemTime::now();
|
||||
let login_timestamp = if self.0.requires_oob_data() {
|
||||
let CookieIdentityExtention {
|
||||
login_timestamp: lt,
|
||||
} = res.request().extensions_mut().remove().unwrap();
|
||||
let CookieIdentityExtention { login_timestamp: lt } =
|
||||
res.request().extensions_mut().remove().unwrap();
|
||||
lt
|
||||
} else {
|
||||
None
|
||||
|
@ -678,30 +651,24 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
let resp =
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/index").to_request())
|
||||
.await;
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/index").to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
let resp =
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
|
||||
.await;
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let c = resp.response().cookies().next().unwrap().to_owned();
|
||||
|
||||
let resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/index")
|
||||
.cookie(c.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/index").cookie(c.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::CREATED);
|
||||
|
||||
let resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/logout")
|
||||
.cookie(c.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/logout").cookie(c.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
@ -728,8 +695,7 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
let resp =
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
|
||||
.await;
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
assert!(resp.headers().contains_key(header::SET_COOKIE));
|
||||
let c = resp.response().cookies().next().unwrap().to_owned();
|
||||
|
@ -756,8 +722,7 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
let resp =
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
|
||||
.await;
|
||||
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
assert!(resp.headers().contains_key(header::SET_COOKIE));
|
||||
let c = resp.response().cookies().next().unwrap().to_owned();
|
||||
|
@ -779,11 +744,9 @@ mod tests {
|
|||
> {
|
||||
test::init_service(
|
||||
App::new()
|
||||
.wrap(IdentityService::new(f(CookieIdentityPolicy::new(
|
||||
&COOKIE_KEY_MASTER,
|
||||
)
|
||||
.secure(false)
|
||||
.name(COOKIE_NAME))))
|
||||
.wrap(IdentityService::new(f(CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
|
||||
.secure(false)
|
||||
.name(COOKIE_NAME))))
|
||||
.service(web::resource("/").to(|id: Identity| async move {
|
||||
let identity = id.identity();
|
||||
if identity.is_none() {
|
||||
|
@ -808,11 +771,8 @@ mod tests {
|
|||
visit_timestamp: Option<SystemTime>,
|
||||
) -> Cookie<'static> {
|
||||
let mut jar = CookieJar::new();
|
||||
let key: Vec<u8> = COOKIE_KEY_MASTER
|
||||
.iter()
|
||||
.chain([1, 0, 0, 0].iter())
|
||||
.map(|e| *e)
|
||||
.collect();
|
||||
let key: Vec<u8> =
|
||||
COOKIE_KEY_MASTER.iter().chain([1, 0, 0, 0].iter()).map(|e| *e).collect();
|
||||
jar.private(&Key::derive_from(&key)).add(Cookie::new(
|
||||
COOKIE_NAME,
|
||||
serde_json::to_string(&CookieValue {
|
||||
|
@ -836,10 +796,8 @@ mod tests {
|
|||
for cookie in response.headers().get_all(header::SET_COOKIE) {
|
||||
cookies.add(Cookie::parse(cookie.to_str().unwrap().to_string()).unwrap());
|
||||
}
|
||||
let cookie = cookies
|
||||
.private(&Key::derive_from(&COOKIE_KEY_MASTER))
|
||||
.get(COOKIE_NAME)
|
||||
.unwrap();
|
||||
let cookie =
|
||||
cookies.private(&Key::derive_from(&COOKIE_KEY_MASTER)).get(COOKIE_NAME).unwrap();
|
||||
assert_eq!(cookie.value(), identity);
|
||||
}
|
||||
|
||||
|
@ -864,15 +822,9 @@ mod tests {
|
|||
for cookie in response.headers().get_all(header::SET_COOKIE) {
|
||||
cookies.add(Cookie::parse(cookie.to_str().unwrap().to_string()).unwrap());
|
||||
}
|
||||
let key: Vec<u8> = COOKIE_KEY_MASTER
|
||||
.iter()
|
||||
.chain([1, 0, 0, 0].iter())
|
||||
.map(|e| *e)
|
||||
.collect();
|
||||
let cookie = cookies
|
||||
.private(&Key::derive_from(&key))
|
||||
.get(COOKIE_NAME)
|
||||
.unwrap();
|
||||
let key: Vec<u8> =
|
||||
COOKIE_KEY_MASTER.iter().chain([1, 0, 0, 0].iter()).map(|e| *e).collect();
|
||||
let cookie = cookies.private(&Key::derive_from(&key)).get(COOKIE_NAME).unwrap();
|
||||
let cv: CookieValue = serde_json::from_str(cookie.value()).unwrap();
|
||||
assert_eq!(cv.identity, identity);
|
||||
let now = SystemTime::now();
|
||||
|
@ -880,8 +832,7 @@ mod tests {
|
|||
match login_timestamp {
|
||||
LoginTimestampCheck::NoTimestamp => assert_eq!(cv.login_timestamp, None),
|
||||
LoginTimestampCheck::NewTimestamp => assert!(
|
||||
t30sec_ago <= cv.login_timestamp.unwrap()
|
||||
&& cv.login_timestamp.unwrap() <= now
|
||||
t30sec_ago <= cv.login_timestamp.unwrap() && cv.login_timestamp.unwrap() <= now
|
||||
),
|
||||
LoginTimestampCheck::OldTimestamp(old_timestamp) => {
|
||||
assert_eq!(cv.login_timestamp, Some(old_timestamp))
|
||||
|
@ -890,8 +841,7 @@ mod tests {
|
|||
match visit_timestamp {
|
||||
VisitTimeStampCheck::NoTimestamp => assert_eq!(cv.visit_timestamp, None),
|
||||
VisitTimeStampCheck::NewTimestamp => assert!(
|
||||
t30sec_ago <= cv.visit_timestamp.unwrap()
|
||||
&& cv.visit_timestamp.unwrap() <= now
|
||||
t30sec_ago <= cv.visit_timestamp.unwrap() && cv.visit_timestamp.unwrap() <= now
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -919,9 +869,7 @@ mod tests {
|
|||
let cookie = legacy_login_cookie(COOKIE_LOGIN);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_no_login_cookie(&mut resp);
|
||||
|
@ -930,14 +878,11 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_legacy_cookie_rejected_if_visit_timestamp_needed() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let cookie = legacy_login_cookie(COOKIE_LOGIN);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -951,14 +896,11 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_legacy_cookie_rejected_if_login_timestamp_needed() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let cookie = legacy_login_cookie(COOKIE_LOGIN);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -972,14 +914,11 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_cookie_rejected_if_login_timestamp_needed() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let cookie = login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now()));
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -993,14 +932,11 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_cookie_rejected_if_visit_timestamp_needed() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -1014,18 +950,12 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_cookie_rejected_if_login_timestamp_too_old() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let cookie = login_cookie(
|
||||
COOKIE_LOGIN,
|
||||
Some(SystemTime::now() - Duration::days(180)),
|
||||
None,
|
||||
);
|
||||
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let cookie =
|
||||
login_cookie(COOKIE_LOGIN, Some(SystemTime::now() - Duration::days(180)), None);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -1039,18 +969,12 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_cookie_rejected_if_visit_timestamp_too_old() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let cookie = login_cookie(
|
||||
COOKIE_LOGIN,
|
||||
None,
|
||||
Some(SystemTime::now() - Duration::days(180)),
|
||||
);
|
||||
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
|
||||
let cookie =
|
||||
login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now() - Duration::days(180)));
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
@ -1064,14 +988,11 @@ mod tests {
|
|||
|
||||
#[ntex::test]
|
||||
async fn test_identity_cookie_not_updated_on_login_deadline() {
|
||||
let mut srv =
|
||||
create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
|
||||
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_no_login_cookie(&mut resp);
|
||||
|
@ -1082,17 +1003,14 @@ mod tests {
|
|||
#[ntex::test]
|
||||
async fn test_identity_cookie_updated_on_visit_deadline() {
|
||||
let mut srv = create_identity_server(|c| {
|
||||
c.visit_deadline(Duration::days(90))
|
||||
.login_deadline(Duration::days(90))
|
||||
c.visit_deadline(Duration::days(90)).login_deadline(Duration::days(90))
|
||||
})
|
||||
.await;
|
||||
let timestamp = SystemTime::now() - Duration::days(1);
|
||||
let cookie = login_cookie(COOKIE_LOGIN, Some(timestamp), Some(timestamp));
|
||||
let mut resp = test::call_service(
|
||||
&mut srv,
|
||||
TestRequest::with_uri("/")
|
||||
.cookie(cookie.clone())
|
||||
.to_request(),
|
||||
TestRequest::with_uri("/").cookie(cookie.clone()).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_login_cookie(
|
||||
|
|
|
@ -71,11 +71,7 @@ impl Multipart {
|
|||
item: InnerMultipartItem::None,
|
||||
}))),
|
||||
},
|
||||
Err(err) => Multipart {
|
||||
error: Some(err),
|
||||
safety: Safety::new(),
|
||||
inner: None,
|
||||
},
|
||||
Err(err) => Multipart { error: Some(err), safety: Safety::new(), inner: None },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,10 +100,7 @@ impl Multipart {
|
|||
impl Stream for Multipart {
|
||||
type Item = Result<Field, MultipartError>;
|
||||
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
if let Some(err) = self.error.take() {
|
||||
Poll::Ready(Some(Err(err)))
|
||||
} else if self.safety.current() {
|
||||
|
@ -126,9 +119,7 @@ impl Stream for Multipart {
|
|||
}
|
||||
|
||||
impl InnerMultipart {
|
||||
fn read_headers(
|
||||
payload: &mut PayloadBuffer,
|
||||
) -> Result<Option<HeaderMap>, MultipartError> {
|
||||
fn read_headers(payload: &mut PayloadBuffer) -> Result<Option<HeaderMap>, MultipartError> {
|
||||
match payload.read_until(b"\r\n\r\n")? {
|
||||
None => {
|
||||
if payload.eof {
|
||||
|
@ -210,8 +201,7 @@ impl InnerMultipart {
|
|||
if chunk.len() < boundary.len() {
|
||||
continue;
|
||||
}
|
||||
if &chunk[..2] == b"--"
|
||||
&& &chunk[2..chunk.len() - 2] == boundary.as_bytes()
|
||||
if &chunk[..2] == b"--" && &chunk[2..chunk.len() - 2] == boundary.as_bytes()
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
|
@ -257,9 +247,7 @@ impl InnerMultipart {
|
|||
match field.borrow_mut().poll(safety) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Some(Ok(_))) => continue,
|
||||
Poll::Ready(Some(Err(e))) => {
|
||||
return Poll::Ready(Some(Err(e)))
|
||||
}
|
||||
Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))),
|
||||
Poll::Ready(None) => true,
|
||||
}
|
||||
}
|
||||
|
@ -295,10 +283,7 @@ impl InnerMultipart {
|
|||
}
|
||||
// read boundary
|
||||
InnerState::Boundary => {
|
||||
match InnerMultipart::read_boundary(
|
||||
&mut *payload,
|
||||
&self.boundary,
|
||||
)? {
|
||||
match InnerMultipart::read_boundary(&mut *payload, &self.boundary)? {
|
||||
None => return Poll::Pending,
|
||||
Some(eof) => {
|
||||
if eof {
|
||||
|
@ -380,12 +365,7 @@ impl Field {
|
|||
ct: mime::Mime,
|
||||
inner: Rc<RefCell<InnerField>>,
|
||||
) -> Self {
|
||||
Field {
|
||||
ct,
|
||||
headers,
|
||||
inner,
|
||||
safety,
|
||||
}
|
||||
Field { ct, headers, inner, safety }
|
||||
}
|
||||
|
||||
/// Get a map of headers
|
||||
|
@ -405,9 +385,7 @@ impl Stream for Field {
|
|||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
if self.safety.current() {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(mut payload) =
|
||||
inner.payload.as_ref().unwrap().get_mut(&self.safety)
|
||||
{
|
||||
if let Some(mut payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) {
|
||||
payload.poll_stream(cx)?;
|
||||
}
|
||||
inner.poll(&self.safety)
|
||||
|
@ -458,12 +436,7 @@ impl InnerField {
|
|||
None
|
||||
};
|
||||
|
||||
Ok(InnerField {
|
||||
boundary,
|
||||
payload: Some(payload),
|
||||
eof: false,
|
||||
length: len,
|
||||
})
|
||||
Ok(InnerField { boundary, payload: Some(payload), eof: false, length: len })
|
||||
}
|
||||
|
||||
/// Reads body part content chunk of the specified size.
|
||||
|
@ -576,8 +549,7 @@ impl InnerField {
|
|||
return Poll::Ready(None);
|
||||
}
|
||||
|
||||
let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s)
|
||||
{
|
||||
let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) {
|
||||
if !self.eof {
|
||||
let res = if let Some(ref mut len) = self.length {
|
||||
InnerField::read_len(&mut *payload, len)
|
||||
|
@ -597,7 +569,9 @@ impl InnerField {
|
|||
Ok(None) => Poll::Pending,
|
||||
Ok(Some(line)) => {
|
||||
if line.as_ref() != b"\r\n" {
|
||||
log::warn!("multipart field did not read all the data or it is malformed");
|
||||
log::warn!(
|
||||
"multipart field did not read all the data or it is malformed"
|
||||
);
|
||||
}
|
||||
Poll::Ready(None)
|
||||
}
|
||||
|
@ -620,9 +594,7 @@ struct PayloadRef {
|
|||
|
||||
impl PayloadRef {
|
||||
fn new(payload: PayloadBuffer) -> PayloadRef {
|
||||
PayloadRef {
|
||||
payload: Rc::new(payload.into()),
|
||||
}
|
||||
PayloadRef { payload: Rc::new(payload.into()) }
|
||||
}
|
||||
|
||||
fn get_mut<'a, 'b>(&'a self, s: &'b Safety) -> Option<RefMut<'a, PayloadBuffer>>
|
||||
|
@ -639,9 +611,7 @@ impl PayloadRef {
|
|||
|
||||
impl Clone for PayloadRef {
|
||||
fn clone(&self) -> PayloadRef {
|
||||
PayloadRef {
|
||||
payload: Rc::clone(&self.payload),
|
||||
}
|
||||
PayloadRef { payload: Rc::clone(&self.payload) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,11 +683,7 @@ impl PayloadBuffer {
|
|||
where
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
PayloadBuffer {
|
||||
eof: false,
|
||||
buf: BytesMut::new(),
|
||||
stream: stream.boxed_local(),
|
||||
}
|
||||
PayloadBuffer { eof: false, buf: BytesMut::new(), stream: stream.boxed_local() }
|
||||
}
|
||||
|
||||
fn poll_stream(&mut self, cx: &mut Context) -> Result<(), PayloadError> {
|
||||
|
@ -775,9 +741,7 @@ impl PayloadBuffer {
|
|||
/// Read bytes until new line delimiter or eof
|
||||
pub fn readline_or_eof(&mut self) -> Result<Option<Bytes>, MultipartError> {
|
||||
match self.readline() {
|
||||
Err(MultipartError::Incomplete) if self.eof => {
|
||||
Ok(Some(self.buf.split().freeze()))
|
||||
}
|
||||
Err(MultipartError::Incomplete) if self.eof => Ok(Some(self.buf.split().freeze())),
|
||||
line => line,
|
||||
}
|
||||
}
|
||||
|
@ -808,10 +772,7 @@ mod tests {
|
|||
}
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
header::CONTENT_TYPE,
|
||||
header::HeaderValue::from_static("test"),
|
||||
);
|
||||
headers.insert(header::CONTENT_TYPE, header::HeaderValue::from_static("test"));
|
||||
|
||||
match Multipart::boundary(&headers) {
|
||||
Err(MultipartError::ParseContentType) => (),
|
||||
|
@ -819,10 +780,8 @@ mod tests {
|
|||
}
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
header::CONTENT_TYPE,
|
||||
header::HeaderValue::from_static("multipart/mixed"),
|
||||
);
|
||||
headers
|
||||
.insert(header::CONTENT_TYPE, header::HeaderValue::from_static("multipart/mixed"));
|
||||
match Multipart::boundary(&headers) {
|
||||
Err(MultipartError::Boundary) => (),
|
||||
_ => unreachable!("should not happen"),
|
||||
|
@ -836,10 +795,7 @@ mod tests {
|
|||
),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Multipart::boundary(&headers).unwrap(),
|
||||
"5c02368e880e436dab70ed54e1c58209"
|
||||
);
|
||||
assert_eq!(Multipart::boundary(&headers).unwrap(), "5c02368e880e436dab70ed54e1c58209");
|
||||
}
|
||||
|
||||
fn create_stream() -> (
|
||||
|
@ -859,21 +815,14 @@ mod tests {
|
|||
|
||||
impl SlowStream {
|
||||
fn new(bytes: Bytes) -> SlowStream {
|
||||
return SlowStream {
|
||||
bytes,
|
||||
pos: 0,
|
||||
ready: false,
|
||||
};
|
||||
return SlowStream { bytes, pos: 0, ready: false };
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for SlowStream {
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
if !this.ready {
|
||||
this.ready = true;
|
||||
|
@ -1112,16 +1061,10 @@ mod tests {
|
|||
sender.feed_data(Bytes::from("line2"));
|
||||
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
Some(Bytes::from("line")),
|
||||
payload.read_until(b"ne").unwrap()
|
||||
);
|
||||
assert_eq!(Some(Bytes::from("line")), payload.read_until(b"ne").unwrap());
|
||||
assert_eq!(payload.buf.len(), 6);
|
||||
|
||||
assert_eq!(
|
||||
Some(Bytes::from("1line2")),
|
||||
payload.read_until(b"2").unwrap()
|
||||
);
|
||||
assert_eq!(Some(Bytes::from("1line2")), payload.read_until(b"2").unwrap());
|
||||
assert_eq!(payload.buf.len(), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,8 +89,7 @@ impl<Err> CookieSessionInner<Err> {
|
|||
state: impl Iterator<Item = (String, String)>,
|
||||
) -> Result<(), CookieSessionError> {
|
||||
let state: HashMap<String, String> = state.collect();
|
||||
let value =
|
||||
serde_json::to_string(&state).map_err(CookieSessionError::Serialize)?;
|
||||
let value = serde_json::to_string(&state).map_err(CookieSessionError::Serialize)?;
|
||||
if value.len() > 4064 {
|
||||
return Err(CookieSessionError::Overflow);
|
||||
}
|
||||
|
@ -153,9 +152,7 @@ impl<Err> CookieSessionInner<Err> {
|
|||
|
||||
let cookie_opt = match self.security {
|
||||
CookieSecurity::Signed => jar.signed(&self.key).get(&self.name),
|
||||
CookieSecurity::Private => {
|
||||
jar.private(&self.key).get(&self.name)
|
||||
}
|
||||
CookieSecurity::Private => jar.private(&self.key).get(&self.name),
|
||||
};
|
||||
if let Some(cookie) = cookie_opt {
|
||||
if let Ok(val) = serde_json::from_str(cookie.value()) {
|
||||
|
@ -216,20 +213,14 @@ impl<Err> CookieSession<Err> {
|
|||
///
|
||||
/// Panics if key length is less than 32 bytes.
|
||||
pub fn signed(key: &[u8]) -> Self {
|
||||
CookieSession(Rc::new(CookieSessionInner::new(
|
||||
key,
|
||||
CookieSecurity::Signed,
|
||||
)))
|
||||
CookieSession(Rc::new(CookieSessionInner::new(key, CookieSecurity::Signed)))
|
||||
}
|
||||
|
||||
/// Construct new *private* `CookieSessionBackend` instance.
|
||||
///
|
||||
/// Panics if key length is less than 32 bytes.
|
||||
pub fn private(key: &[u8]) -> Self {
|
||||
CookieSession(Rc::new(CookieSessionInner::new(
|
||||
key,
|
||||
CookieSecurity::Private,
|
||||
)))
|
||||
CookieSession(Rc::new(CookieSessionInner::new(key, CookieSecurity::Private)))
|
||||
}
|
||||
|
||||
/// Sets the `path` field in the session cookie being built.
|
||||
|
@ -310,10 +301,7 @@ where
|
|||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(CookieSessionMiddleware {
|
||||
service,
|
||||
inner: self.0.clone(),
|
||||
})
|
||||
ok(CookieSessionMiddleware { service, inner: self.0.clone() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,64 +388,52 @@ mod tests {
|
|||
#[ntex::test]
|
||||
async fn cookie_session() {
|
||||
let app = test::init_service(
|
||||
App::new()
|
||||
.wrap(CookieSession::signed(&[0; 32]).secure(false))
|
||||
.service(web::resource("/").to(|ses: Session| async move {
|
||||
App::new().wrap(CookieSession::signed(&[0; 32]).secure(false)).service(
|
||||
web::resource("/").to(|ses: Session| async move {
|
||||
let _ = ses.set("counter", 100);
|
||||
"test"
|
||||
})),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = test::TestRequest::get().to_request();
|
||||
let response = app.call(request).await.unwrap();
|
||||
assert!(response
|
||||
.response()
|
||||
.cookies()
|
||||
.find(|c| c.name() == "ntex-session")
|
||||
.is_some());
|
||||
assert!(response.response().cookies().find(|c| c.name() == "ntex-session").is_some());
|
||||
}
|
||||
|
||||
#[ntex::test]
|
||||
async fn private_cookie() {
|
||||
let app = test::init_service(
|
||||
App::new()
|
||||
.wrap(CookieSession::private(&[0; 32]).secure(false))
|
||||
.service(web::resource("/").to(|ses: Session| async move {
|
||||
App::new().wrap(CookieSession::private(&[0; 32]).secure(false)).service(
|
||||
web::resource("/").to(|ses: Session| async move {
|
||||
let _ = ses.set("counter", 100);
|
||||
"test"
|
||||
})),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = test::TestRequest::get().to_request();
|
||||
let response = app.call(request).await.unwrap();
|
||||
assert!(response
|
||||
.response()
|
||||
.cookies()
|
||||
.find(|c| c.name() == "ntex-session")
|
||||
.is_some());
|
||||
assert!(response.response().cookies().find(|c| c.name() == "ntex-session").is_some());
|
||||
}
|
||||
|
||||
#[ntex::test]
|
||||
async fn cookie_session_extractor() {
|
||||
let app = test::init_service(
|
||||
App::new()
|
||||
.wrap(CookieSession::signed(&[0; 32]).secure(false))
|
||||
.service(web::resource("/").to(|ses: Session| async move {
|
||||
App::new().wrap(CookieSession::signed(&[0; 32]).secure(false)).service(
|
||||
web::resource("/").to(|ses: Session| async move {
|
||||
let _ = ses.set("counter", 100);
|
||||
"test"
|
||||
})),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = test::TestRequest::get().to_request();
|
||||
let response = app.call(request).await.unwrap();
|
||||
assert!(response
|
||||
.response()
|
||||
.cookies()
|
||||
.find(|c| c.name() == "ntex-session")
|
||||
.is_some());
|
||||
assert!(response.response().cookies().find(|c| c.name() == "ntex-session").is_some());
|
||||
}
|
||||
|
||||
#[ntex::test]
|
||||
|
@ -486,17 +462,11 @@ mod tests {
|
|||
|
||||
let request = test::TestRequest::get().to_request();
|
||||
let response = app.call(request).await.unwrap();
|
||||
let cookie = response
|
||||
.response()
|
||||
.cookies()
|
||||
.find(|c| c.name() == "ntex-test")
|
||||
.unwrap()
|
||||
.clone();
|
||||
let cookie =
|
||||
response.response().cookies().find(|c| c.name() == "ntex-test").unwrap().clone();
|
||||
assert_eq!(cookie.path().unwrap(), "/test/");
|
||||
|
||||
let request = test::TestRequest::with_uri("/test/")
|
||||
.cookie(cookie)
|
||||
.to_request();
|
||||
let request = test::TestRequest::with_uri("/test/").cookie(cookie).to_request();
|
||||
let body = test::read_response(&app, request).await;
|
||||
assert_eq!(body, Bytes::from_static(b"counter: 100"));
|
||||
}
|
||||
|
@ -510,10 +480,7 @@ mod tests {
|
|||
let _ = ses.set("counter", 100);
|
||||
"test"
|
||||
}))
|
||||
.service(
|
||||
web::resource("/test/")
|
||||
.to(|| async move { "no-changes-in-session" }),
|
||||
),
|
||||
.service(web::resource("/test/").to(|| async move { "no-changes-in-session" })),
|
||||
)
|
||||
.await;
|
||||
|
||||
|
|
|
@ -139,9 +139,7 @@ impl Session {
|
|||
let mut inner = self.0.borrow_mut();
|
||||
if inner.status != SessionStatus::Purged {
|
||||
inner.status = SessionStatus::Changed;
|
||||
inner
|
||||
.state
|
||||
.insert(key.to_owned(), serde_json::to_string(&value)?);
|
||||
inner.state.insert(key.to_owned(), serde_json::to_string(&value)?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -190,17 +188,9 @@ impl Session {
|
|||
|
||||
pub fn get_changes(
|
||||
res: &mut WebResponse,
|
||||
) -> (
|
||||
SessionStatus,
|
||||
Option<impl Iterator<Item = (String, String)>>,
|
||||
) {
|
||||
if let Some(s_impl) = res
|
||||
.request()
|
||||
.extensions()
|
||||
.get::<Rc<RefCell<SessionInner>>>()
|
||||
{
|
||||
let state =
|
||||
std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
|
||||
) -> (SessionStatus, Option<impl Iterator<Item = (String, String)>>) {
|
||||
if let Some(s_impl) = res.request().extensions().get::<Rc<RefCell<SessionInner>>>() {
|
||||
let state = std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
|
||||
(s_impl.borrow().status.clone(), Some(state.into_iter()))
|
||||
} else {
|
||||
(SessionStatus::Unchanged, None)
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
max_width = 89
|
||||
max_width = 96
|
||||
reorder_imports = true
|
||||
use_small_heuristics = "max"
|
||||
use_field_init_shorthand = true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue