mirror of
https://github.com/fafhrd91/actix-web
synced 2025-08-19 20:35:36 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fbb52ad3b | ||
|
|
e5cdd22720 | ||
|
|
4f2e970732 | ||
|
|
4d45313f9d | ||
|
|
55a2a59906 | ||
|
|
61883042c2 |
14
CHANGES.md
14
CHANGES.md
@@ -1,5 +1,19 @@
|
||||
# Changes
|
||||
|
||||
## [0.7.18] - 2019-01-10
|
||||
|
||||
### Added
|
||||
|
||||
* Add `with_cookie` for `TestRequest` to allow users to customize request cookie. #647
|
||||
|
||||
* Add `cookie` method for `TestRequest` to allow users to add cookie dynamically.
|
||||
|
||||
### Fixed
|
||||
|
||||
* StaticFiles decode special characters in request's path
|
||||
|
||||
* Fix test server listener leak #654
|
||||
|
||||
## [0.7.17] - 2018-12-25
|
||||
|
||||
### Added
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-web"
|
||||
version = "0.7.17"
|
||||
version = "0.7.18"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
||||
readme = "README.md"
|
||||
@@ -64,7 +64,7 @@ cell = ["actix-net/cell"]
|
||||
actix = "0.7.9"
|
||||
actix-net = "0.2.6"
|
||||
|
||||
askama_escape = "0.1.0"
|
||||
v_htmlescape = "0.3.2"
|
||||
base64 = "0.10"
|
||||
bitflags = "1.0"
|
||||
failure = "^0.1.2"
|
||||
|
||||
30
src/fs.rs
30
src/fs.rs
@@ -11,7 +11,7 @@ use std::{cmp, io};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
use askama_escape::{escape as escape_html_entity};
|
||||
use v_htmlescape::HTMLEscape;
|
||||
use bytes::Bytes;
|
||||
use futures::{Async, Future, Poll, Stream};
|
||||
use futures_cpupool::{CpuFuture, CpuPool};
|
||||
@@ -569,6 +569,11 @@ macro_rules! encode_file_url {
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_html_entity(s: &str) -> HTMLEscape {
|
||||
HTMLEscape::from(s)
|
||||
}
|
||||
|
||||
// " -- " & -- & ' -- ' < -- < > -- > / -- /
|
||||
macro_rules! encode_file_name {
|
||||
($entry:ident) => {
|
||||
@@ -756,7 +761,7 @@ impl<S: 'static, C: StaticFileConfig> StaticFiles<S, C> {
|
||||
&self,
|
||||
req: &HttpRequest<S>,
|
||||
) -> Result<AsyncResult<HttpResponse>, Error> {
|
||||
let tail: String = req.match_info().query("tail")?;
|
||||
let tail: String = req.match_info().get_decoded("tail").unwrap_or_else(|| "".to_string());
|
||||
let relpath = PathBuf::from_param(tail.trim_left_matches('/'))?;
|
||||
|
||||
// full filepath
|
||||
@@ -1298,6 +1303,27 @@ mod tests {
|
||||
assert_eq!(bytes, data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_static_files_with_spaces() {
|
||||
let mut srv = test::TestServer::with_factory(|| {
|
||||
App::new().handler(
|
||||
"/",
|
||||
StaticFiles::new(".").unwrap().index_file("Cargo.toml"),
|
||||
)
|
||||
});
|
||||
let request = srv
|
||||
.get()
|
||||
.uri(srv.url("/tests/test%20space.binary"))
|
||||
.finish()
|
||||
.unwrap();
|
||||
let response = srv.execute(request.send()).unwrap();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let bytes = srv.execute(response.body()).unwrap();
|
||||
let data = Bytes::from(fs::read("tests/test space.binary").unwrap());
|
||||
assert_eq!(bytes, data);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OnlyMethodHeadConfig;
|
||||
impl StaticFileConfig for OnlyMethodHeadConfig {
|
||||
|
||||
@@ -100,7 +100,6 @@ extern crate failure;
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate futures;
|
||||
extern crate askama_escape;
|
||||
extern crate cookie;
|
||||
extern crate futures_cpupool;
|
||||
extern crate http as modhttp;
|
||||
@@ -137,6 +136,7 @@ extern crate serde_urlencoded;
|
||||
extern crate percent_encoding;
|
||||
extern crate serde_json;
|
||||
extern crate smallvec;
|
||||
extern crate v_htmlescape;
|
||||
|
||||
extern crate actix_net;
|
||||
#[macro_use]
|
||||
|
||||
46
src/test.rs
46
src/test.rs
@@ -5,7 +5,9 @@ use std::sync::mpsc;
|
||||
use std::{net, thread};
|
||||
|
||||
use actix::{Actor, Addr, System};
|
||||
use actix::actors::signal;
|
||||
|
||||
use actix_net::server::Server;
|
||||
use cookie::Cookie;
|
||||
use futures::Future;
|
||||
use http::header::HeaderName;
|
||||
@@ -66,6 +68,7 @@ pub struct TestServer {
|
||||
ssl: bool,
|
||||
conn: Addr<ClientConnector>,
|
||||
rt: Runtime,
|
||||
backend: Addr<Server>,
|
||||
}
|
||||
|
||||
impl TestServer {
|
||||
@@ -112,24 +115,25 @@ impl TestServer {
|
||||
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let local_addr = tcp.local_addr().unwrap();
|
||||
|
||||
let _ = HttpServer::new(factory)
|
||||
let srv = HttpServer::new(factory)
|
||||
.disable_signals()
|
||||
.listen(tcp)
|
||||
.keep_alive(5)
|
||||
.start();
|
||||
|
||||
tx.send((System::current(), local_addr, TestServer::get_conn()))
|
||||
tx.send((System::current(), local_addr, TestServer::get_conn(), srv))
|
||||
.unwrap();
|
||||
sys.run();
|
||||
});
|
||||
|
||||
let (system, addr, conn) = rx.recv().unwrap();
|
||||
let (system, addr, conn, backend) = rx.recv().unwrap();
|
||||
System::set_current(system);
|
||||
TestServer {
|
||||
addr,
|
||||
conn,
|
||||
ssl: false,
|
||||
rt: Runtime::new().unwrap(),
|
||||
backend,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +201,7 @@ impl TestServer {
|
||||
|
||||
/// Stop http server
|
||||
fn stop(&mut self) {
|
||||
let _ = self.backend.send(signal::Signal(signal::SignalType::Term)).wait();
|
||||
System::current().stop();
|
||||
}
|
||||
|
||||
@@ -333,8 +338,7 @@ where
|
||||
.keep_alive(5)
|
||||
.disable_signals();
|
||||
|
||||
tx.send((System::current(), addr, TestServer::get_conn()))
|
||||
.unwrap();
|
||||
|
||||
|
||||
#[cfg(any(feature = "alpn", feature = "ssl"))]
|
||||
{
|
||||
@@ -356,18 +360,22 @@ where
|
||||
let tcp = net::TcpListener::bind(addr).unwrap();
|
||||
srv = srv.listen(tcp);
|
||||
}
|
||||
srv.start();
|
||||
let backend = srv.start();
|
||||
|
||||
tx.send((System::current(), addr, TestServer::get_conn(), backend))
|
||||
.unwrap();
|
||||
|
||||
sys.run();
|
||||
});
|
||||
|
||||
let (system, addr, conn) = rx.recv().unwrap();
|
||||
let (system, addr, conn, backend) = rx.recv().unwrap();
|
||||
System::set_current(system);
|
||||
TestServer {
|
||||
addr,
|
||||
conn,
|
||||
ssl: has_ssl,
|
||||
rt: Runtime::new().unwrap(),
|
||||
backend,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,6 +515,11 @@ impl TestRequest<()> {
|
||||
{
|
||||
TestRequest::default().header(key, value)
|
||||
}
|
||||
|
||||
/// Create TestRequest and set request cookie
|
||||
pub fn with_cookie(cookie: Cookie<'static>) -> TestRequest<()> {
|
||||
TestRequest::default().cookie(cookie)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> TestRequest<S> {
|
||||
@@ -543,6 +556,25 @@ impl<S: 'static> TestRequest<S> {
|
||||
self
|
||||
}
|
||||
|
||||
/// set cookie of this request
|
||||
pub fn cookie(mut self, cookie: Cookie<'static>) -> Self {
|
||||
if self.cookies.is_none() {
|
||||
let mut should_insert = true;
|
||||
let old_cookies = self.cookies.as_mut().unwrap();
|
||||
for old_cookie in old_cookies.iter() {
|
||||
if old_cookie == &cookie {
|
||||
should_insert = false
|
||||
};
|
||||
};
|
||||
if should_insert {
|
||||
old_cookies.push(cookie);
|
||||
};
|
||||
} else {
|
||||
self.cookies = Some(vec![cookie]);
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a header
|
||||
pub fn set<H: Header>(mut self, hdr: H) -> Self {
|
||||
if let Ok(value) = hdr.try_into() {
|
||||
|
||||
1
tests/test space.binary
Normal file
1
tests/test space.binary
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD>TǑɂV<EFBFBD>2<EFBFBD>vI<EFBFBD><EFBFBD><EFBFBD>\<5C>R˙<52><CB99><EFBFBD>e<EFBFBD><04>vD<76>:藽<>RV<03>Yp<59><70>;<3B><>G<><47>p!2<7F>C<EFBFBD>.<2E><0C><><EFBFBD><EFBFBD>pA!<21>ߦ<EFBFBD>x j+Uc<55><63><EFBFBD>X<13>c%<17>;<3B>"y<10><>AI
|
||||
Reference in New Issue
Block a user