Reformat the source code
This commit is contained in:
@@ -14,8 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::PathBuf;
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
path::PathBuf,
|
||||
};
|
||||
use tempdir::TempDir;
|
||||
|
||||
use parity_runtime::{Runtime, TaskExecutor};
|
||||
@@ -24,64 +26,65 @@ use authcodes::AuthCodes;
|
||||
|
||||
/// Server with event loop
|
||||
pub struct Server<T> {
|
||||
/// Server
|
||||
pub server: T,
|
||||
/// RPC Event Loop
|
||||
pub event_loop: Runtime,
|
||||
/// Server
|
||||
pub server: T,
|
||||
/// RPC Event Loop
|
||||
pub event_loop: Runtime,
|
||||
}
|
||||
|
||||
impl<T> Server<T> {
|
||||
pub fn new<F>(f: F) -> Server<T> where
|
||||
F: FnOnce(TaskExecutor) -> T,
|
||||
{
|
||||
let event_loop = Runtime::with_thread_count(1);
|
||||
let remote = event_loop.raw_executor();
|
||||
pub fn new<F>(f: F) -> Server<T>
|
||||
where
|
||||
F: FnOnce(TaskExecutor) -> T,
|
||||
{
|
||||
let event_loop = Runtime::with_thread_count(1);
|
||||
let remote = event_loop.raw_executor();
|
||||
|
||||
Server {
|
||||
server: f(remote),
|
||||
event_loop,
|
||||
}
|
||||
}
|
||||
Server {
|
||||
server: f(remote),
|
||||
event_loop,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Server<T> {
|
||||
type Target = T;
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.server
|
||||
}
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.server
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct representing authcodes
|
||||
pub struct GuardedAuthCodes {
|
||||
authcodes: AuthCodes,
|
||||
_tempdir: TempDir,
|
||||
/// The path to the mock authcodes
|
||||
pub path: PathBuf,
|
||||
authcodes: AuthCodes,
|
||||
_tempdir: TempDir,
|
||||
/// The path to the mock authcodes
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for GuardedAuthCodes {
|
||||
fn default() -> Self {
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let path = tempdir.path().join("file");
|
||||
fn default() -> Self {
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let path = tempdir.path().join("file");
|
||||
|
||||
GuardedAuthCodes {
|
||||
authcodes: AuthCodes::from_file(&path).unwrap(),
|
||||
_tempdir: tempdir,
|
||||
path,
|
||||
}
|
||||
}
|
||||
GuardedAuthCodes {
|
||||
authcodes: AuthCodes::from_file(&path).unwrap(),
|
||||
_tempdir: tempdir,
|
||||
path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GuardedAuthCodes {
|
||||
type Target = AuthCodes;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.authcodes
|
||||
}
|
||||
type Target = AuthCodes;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.authcodes
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for GuardedAuthCodes {
|
||||
fn deref_mut(&mut self) -> &mut AuthCodes {
|
||||
&mut self.authcodes
|
||||
}
|
||||
fn deref_mut(&mut self) -> &mut AuthCodes {
|
||||
&mut self.authcodes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,119 +14,134 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::str::{self, Lines};
|
||||
use std::net::{TcpStream, SocketAddr};
|
||||
use std::{
|
||||
io::{self, Read, Write},
|
||||
net::{SocketAddr, TcpStream},
|
||||
str::{self, Lines},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub struct Response {
|
||||
pub status: String,
|
||||
pub headers: Vec<String>,
|
||||
pub headers_raw: String,
|
||||
pub body: String,
|
||||
pub status: String,
|
||||
pub headers: Vec<String>,
|
||||
pub headers_raw: String,
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
impl Response {
|
||||
pub fn assert_header(&self, header: &str, value: &str) {
|
||||
let header = format!("{}: {}", header, value);
|
||||
assert!(self.headers.iter().any(|h| h == &header), "Couldn't find header {} in {:?}", header, &self.headers)
|
||||
}
|
||||
pub fn assert_header(&self, header: &str, value: &str) {
|
||||
let header = format!("{}: {}", header, value);
|
||||
assert!(
|
||||
self.headers.iter().any(|h| h == &header),
|
||||
"Couldn't find header {} in {:?}",
|
||||
header,
|
||||
&self.headers
|
||||
)
|
||||
}
|
||||
|
||||
pub fn assert_status(&self, status: &str) {
|
||||
assert_eq!(self.status, status.to_owned(), "Got unexpected code. Body: {:?}", self.body);
|
||||
}
|
||||
pub fn assert_status(&self, status: &str) {
|
||||
assert_eq!(
|
||||
self.status,
|
||||
status.to_owned(),
|
||||
"Got unexpected code. Body: {:?}",
|
||||
self.body
|
||||
);
|
||||
}
|
||||
|
||||
pub fn assert_security_headers_present(&self, port: Option<u16>) {
|
||||
assert_security_headers_present(&self.headers, port)
|
||||
}
|
||||
pub fn assert_security_headers_present(&self, port: Option<u16>) {
|
||||
assert_security_headers_present(&self.headers, port)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_block(lines: &mut Lines, all: bool) -> String {
|
||||
let mut block = String::new();
|
||||
loop {
|
||||
let line = lines.next();
|
||||
match line {
|
||||
None => break,
|
||||
Some("") if !all => break,
|
||||
Some(v) => {
|
||||
block.push_str(v);
|
||||
block.push_str("\n");
|
||||
},
|
||||
}
|
||||
}
|
||||
block
|
||||
let mut block = String::new();
|
||||
loop {
|
||||
let line = lines.next();
|
||||
match line {
|
||||
None => break,
|
||||
Some("") if !all => break,
|
||||
Some(v) => {
|
||||
block.push_str(v);
|
||||
block.push_str("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
block
|
||||
}
|
||||
|
||||
fn connect(address: &SocketAddr) -> TcpStream {
|
||||
let mut retries = 0;
|
||||
let mut last_error = None;
|
||||
while retries < 10 {
|
||||
retries += 1;
|
||||
let mut retries = 0;
|
||||
let mut last_error = None;
|
||||
while retries < 10 {
|
||||
retries += 1;
|
||||
|
||||
let res = TcpStream::connect(address);
|
||||
match res {
|
||||
Ok(stream) => {
|
||||
return stream;
|
||||
},
|
||||
Err(e) => {
|
||||
last_error = Some(e);
|
||||
thread::sleep(Duration::from_millis(retries * 10));
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("Unable to connect to the server. Last error: {:?}", last_error);
|
||||
let res = TcpStream::connect(address);
|
||||
match res {
|
||||
Ok(stream) => {
|
||||
return stream;
|
||||
}
|
||||
Err(e) => {
|
||||
last_error = Some(e);
|
||||
thread::sleep(Duration::from_millis(retries * 10));
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
"Unable to connect to the server. Last error: {:?}",
|
||||
last_error
|
||||
);
|
||||
}
|
||||
|
||||
pub fn request(address: &SocketAddr, request: &str) -> Response {
|
||||
let mut req = connect(address);
|
||||
req.set_read_timeout(Some(Duration::from_secs(2))).unwrap();
|
||||
req.write_all(request.as_bytes()).unwrap();
|
||||
let mut req = connect(address);
|
||||
req.set_read_timeout(Some(Duration::from_secs(2))).unwrap();
|
||||
req.write_all(request.as_bytes()).unwrap();
|
||||
|
||||
let mut response = Vec::new();
|
||||
loop {
|
||||
let mut chunk = [0; 32 *1024];
|
||||
match req.read(&mut chunk) {
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
|
||||
Err(err) => panic!("Unable to read response: {:?}", err),
|
||||
Ok(0) => break,
|
||||
Ok(read) => response.extend_from_slice(&chunk[..read]),
|
||||
}
|
||||
}
|
||||
let mut response = Vec::new();
|
||||
loop {
|
||||
let mut chunk = [0; 32 * 1024];
|
||||
match req.read(&mut chunk) {
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
|
||||
Err(err) => panic!("Unable to read response: {:?}", err),
|
||||
Ok(0) => break,
|
||||
Ok(read) => response.extend_from_slice(&chunk[..read]),
|
||||
}
|
||||
}
|
||||
|
||||
let response = String::from_utf8_lossy(&response).into_owned();
|
||||
let mut lines = response.lines();
|
||||
let status = lines.next().expect("Expected a response").to_owned();
|
||||
let headers_raw = read_block(&mut lines, false);
|
||||
let headers = headers_raw.split('\n').map(ToOwned::to_owned).collect();
|
||||
let body = read_block(&mut lines, true);
|
||||
let response = String::from_utf8_lossy(&response).into_owned();
|
||||
let mut lines = response.lines();
|
||||
let status = lines.next().expect("Expected a response").to_owned();
|
||||
let headers_raw = read_block(&mut lines, false);
|
||||
let headers = headers_raw.split('\n').map(ToOwned::to_owned).collect();
|
||||
let body = read_block(&mut lines, true);
|
||||
|
||||
Response {
|
||||
status,
|
||||
headers,
|
||||
headers_raw,
|
||||
body,
|
||||
}
|
||||
Response {
|
||||
status,
|
||||
headers,
|
||||
headers_raw,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if all required security headers are present
|
||||
pub fn assert_security_headers_present(headers: &[String], port: Option<u16>) {
|
||||
if port.is_none() {
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN")
|
||||
"X-Frame-Options: SAMEORIGIN missing: {:?}", headers
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-XSS-Protection: 1; mode=block")
|
||||
"X-XSS-Protection missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Content-Type-Options: nosniff")
|
||||
"X-Content-Type-Options missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.starts_with("Content-Security-Policy: "))
|
||||
"Content-Security-Policy missing: {:?}", headers
|
||||
)
|
||||
if port.is_none() {
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN")
|
||||
"X-Frame-Options: SAMEORIGIN missing: {:?}", headers
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-XSS-Protection: 1; mode=block")
|
||||
"X-XSS-Protection missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Content-Type-Options: nosniff")
|
||||
"X-Content-Type-Options missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.starts_with("Content-Security-Policy: "))
|
||||
"Content-Security-Policy missing: {:?}", headers
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,5 +18,6 @@
|
||||
|
||||
mod helpers;
|
||||
mod http_client;
|
||||
#[cfg(test)] mod rpc;
|
||||
#[cfg(test)]
|
||||
mod rpc;
|
||||
pub mod ws;
|
||||
|
||||
@@ -14,68 +14,70 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use jsonrpc_core::MetaIoHandler;
|
||||
use http::{self, hyper};
|
||||
use jsonrpc_core::MetaIoHandler;
|
||||
|
||||
use {HttpServer};
|
||||
use tests::helpers::Server;
|
||||
use tests::http_client;
|
||||
use tests::{helpers::Server, http_client};
|
||||
use v1::{extractors, Metadata};
|
||||
use HttpServer;
|
||||
|
||||
fn serve(handler: Option<MetaIoHandler<Metadata>>) -> Server<HttpServer> {
|
||||
let address = "127.0.0.1:0".parse().unwrap();
|
||||
let handler = handler.unwrap_or_default();
|
||||
let address = "127.0.0.1:0".parse().unwrap();
|
||||
let handler = handler.unwrap_or_default();
|
||||
|
||||
Server::new(|_remote| ::start_http_with_middleware(
|
||||
&address,
|
||||
http::DomainsValidation::Disabled,
|
||||
http::DomainsValidation::Disabled,
|
||||
handler,
|
||||
extractors::RpcExtractor,
|
||||
|request: hyper::Request<hyper::Body>| {
|
||||
http::RequestMiddlewareAction::Proceed {
|
||||
should_continue_on_invalid_cors: false,
|
||||
request,
|
||||
}
|
||||
},
|
||||
1,
|
||||
5,
|
||||
false,
|
||||
).unwrap())
|
||||
Server::new(|_remote| {
|
||||
::start_http_with_middleware(
|
||||
&address,
|
||||
http::DomainsValidation::Disabled,
|
||||
http::DomainsValidation::Disabled,
|
||||
handler,
|
||||
extractors::RpcExtractor,
|
||||
|request: hyper::Request<hyper::Body>| http::RequestMiddlewareAction::Proceed {
|
||||
should_continue_on_invalid_cors: false,
|
||||
request,
|
||||
},
|
||||
1,
|
||||
5,
|
||||
false,
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
/// Test a single request to running server
|
||||
fn request(server: Server<HttpServer>, request: &str) -> http_client::Response {
|
||||
http_client::request(server.server.address(), request)
|
||||
http_client::request(server.server.address(), request)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use jsonrpc_core::{MetaIoHandler, Value};
|
||||
use v1::Metadata;
|
||||
use super::{request, Server};
|
||||
use super::{request, Server};
|
||||
use jsonrpc_core::{MetaIoHandler, Value};
|
||||
use v1::Metadata;
|
||||
|
||||
fn serve() -> (Server<::HttpServer>, ::std::net::SocketAddr) {
|
||||
let mut io = MetaIoHandler::default();
|
||||
io.add_method_with_meta("hello", |_, meta: Metadata| {
|
||||
Ok(Value::String(format!("{}", meta.origin)))
|
||||
});
|
||||
let server = super::serve(Some(io));
|
||||
let address = server.server.address().to_owned();
|
||||
fn serve() -> (Server<::HttpServer>, ::std::net::SocketAddr) {
|
||||
let mut io = MetaIoHandler::default();
|
||||
io.add_method_with_meta("hello", |_, meta: Metadata| {
|
||||
Ok(Value::String(format!("{}", meta.origin)))
|
||||
});
|
||||
let server = super::serve(Some(io));
|
||||
let address = server.server.address().to_owned();
|
||||
|
||||
(server, address)
|
||||
}
|
||||
(server, address)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_rpc_origin() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
#[test]
|
||||
fn should_extract_rpc_origin() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
|
||||
// when
|
||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||
let expected = "{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / unknown agent via RPC\",\"id\":1}\n";
|
||||
let res = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||
let expected = "{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / unknown agent via RPC\",\"id\":1}\n";
|
||||
let res = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
POST / HTTP/1.1\r\n\
|
||||
Host: {}\r\n\
|
||||
Content-Type: application/json\r\n\
|
||||
@@ -83,24 +85,31 @@ mod tests {
|
||||
Connection: close\r\n\
|
||||
\r\n\
|
||||
{}
|
||||
", address, req.len(), req)
|
||||
);
|
||||
",
|
||||
address,
|
||||
req.len(),
|
||||
req
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
res.assert_status("HTTP/1.1 200 OK");
|
||||
assert_eq!(res.body, expected);
|
||||
}
|
||||
// then
|
||||
res.assert_status("HTTP/1.1 200 OK");
|
||||
assert_eq!(res.body, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_rpc_origin_with_service() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
#[test]
|
||||
fn should_extract_rpc_origin_with_service() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
|
||||
// when
|
||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||
let expected = "{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / curl/7.16.3 via RPC\",\"id\":1}\n";
|
||||
let res = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||
let expected =
|
||||
"{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / curl/7.16.3 via RPC\",\"id\":1}\n";
|
||||
let res = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
POST / HTTP/1.1\r\n\
|
||||
Host: {}\r\n\
|
||||
Content-Type: application/json\r\n\
|
||||
@@ -109,23 +118,29 @@ mod tests {
|
||||
User-Agent: curl/7.16.3\r\n\
|
||||
\r\n\
|
||||
{}
|
||||
", address, req.len(), req)
|
||||
);
|
||||
",
|
||||
address,
|
||||
req.len(),
|
||||
req
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
res.assert_status("HTTP/1.1 200 OK");
|
||||
assert_eq!(res.body, expected);
|
||||
}
|
||||
// then
|
||||
res.assert_status("HTTP/1.1 200 OK");
|
||||
assert_eq!(res.body, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_respond_valid_to_any_requested_header() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
let headers = "Something, Anything, Xyz, 123, _?";
|
||||
#[test]
|
||||
fn should_respond_valid_to_any_requested_header() {
|
||||
// given
|
||||
let (server, address) = serve();
|
||||
let headers = "Something, Anything, Xyz, 123, _?";
|
||||
|
||||
// when
|
||||
let res = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let res = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
OPTIONS / HTTP/1.1\r\n\
|
||||
Host: {}\r\n\
|
||||
Origin: http://parity.io\r\n\
|
||||
@@ -134,13 +149,18 @@ mod tests {
|
||||
Connection: close\r\n\
|
||||
Access-Control-Request-Headers: {}\r\n\
|
||||
\r\n\
|
||||
", address, headers)
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(res.status, "HTTP/1.1 200 OK".to_owned());
|
||||
let expected = format!("access-control-allow-headers: {}", headers);
|
||||
assert!(res.headers.contains(&expected), "Headers missing in {:?}", res.headers);
|
||||
}
|
||||
",
|
||||
address, headers
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(res.status, "HTTP/1.1 200 OK".to_owned());
|
||||
let expected = format!("access-control-allow-headers: {}", headers);
|
||||
assert!(
|
||||
res.headers.contains(&expected),
|
||||
"Headers missing in {:?}",
|
||||
res.headers
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,71 +21,82 @@ use std::sync::Arc;
|
||||
use jsonrpc_core::MetaIoHandler;
|
||||
use ws;
|
||||
|
||||
use tests::{
|
||||
helpers::{GuardedAuthCodes, Server},
|
||||
http_client,
|
||||
};
|
||||
use v1::{extractors, informant};
|
||||
use tests::helpers::{GuardedAuthCodes, Server};
|
||||
use tests::http_client;
|
||||
|
||||
/// Setup a mock signer for tests
|
||||
pub fn serve() -> (Server<ws::Server>, usize, GuardedAuthCodes) {
|
||||
let address = "127.0.0.1:0".parse().unwrap();
|
||||
let io = MetaIoHandler::default();
|
||||
let authcodes = GuardedAuthCodes::default();
|
||||
let stats = Arc::new(informant::RpcStats::default());
|
||||
let address = "127.0.0.1:0".parse().unwrap();
|
||||
let io = MetaIoHandler::default();
|
||||
let authcodes = GuardedAuthCodes::default();
|
||||
let stats = Arc::new(informant::RpcStats::default());
|
||||
|
||||
let res = Server::new(|_| ::start_ws(
|
||||
&address,
|
||||
io,
|
||||
ws::DomainsValidation::Disabled,
|
||||
ws::DomainsValidation::Disabled,
|
||||
5,
|
||||
extractors::WsExtractor::new(Some(&authcodes.path)),
|
||||
extractors::WsExtractor::new(Some(&authcodes.path)),
|
||||
extractors::WsStats::new(stats),
|
||||
).unwrap());
|
||||
let port = res.addr().port() as usize;
|
||||
let res = Server::new(|_| {
|
||||
::start_ws(
|
||||
&address,
|
||||
io,
|
||||
ws::DomainsValidation::Disabled,
|
||||
ws::DomainsValidation::Disabled,
|
||||
5,
|
||||
extractors::WsExtractor::new(Some(&authcodes.path)),
|
||||
extractors::WsExtractor::new(Some(&authcodes.path)),
|
||||
extractors::WsStats::new(stats),
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
let port = res.addr().port() as usize;
|
||||
|
||||
(res, port, authcodes)
|
||||
(res, port, authcodes)
|
||||
}
|
||||
|
||||
/// Test a single request to running server
|
||||
pub fn request(server: Server<ws::Server>, request: &str) -> http_client::Response {
|
||||
http_client::request(server.server.addr(), request)
|
||||
http_client::request(server.server.addr(), request)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod testing {
|
||||
use std::time;
|
||||
use hash::keccak;
|
||||
use super::{serve, request, http_client};
|
||||
use super::{http_client, request, serve};
|
||||
use hash::keccak;
|
||||
use std::time;
|
||||
|
||||
#[test]
|
||||
fn should_not_redirect_to_parity_host() {
|
||||
// given
|
||||
let (server, port, _) = serve();
|
||||
#[test]
|
||||
fn should_not_redirect_to_parity_host() {
|
||||
// given
|
||||
let (server, port, _) = serve();
|
||||
|
||||
// when
|
||||
let response = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let response = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Host: 127.0.0.1:{}\r\n\
|
||||
Connection: close\r\n\
|
||||
\r\n\
|
||||
{{}}
|
||||
", port)
|
||||
);
|
||||
",
|
||||
port
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned());
|
||||
}
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_block_if_authorization_is_incorrect() {
|
||||
// given
|
||||
let (server, port, _) = serve();
|
||||
#[test]
|
||||
fn should_block_if_authorization_is_incorrect() {
|
||||
// given
|
||||
let (server, port, _) = serve();
|
||||
|
||||
// when
|
||||
let response = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let response = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Host: 127.0.0.1:{}\r\n\
|
||||
Connection: Upgrade\r\n\
|
||||
@@ -94,26 +105,30 @@ mod testing {
|
||||
Sec-WebSocket-Version: 13\r\n\
|
||||
\r\n\
|
||||
{{}}
|
||||
", port)
|
||||
);
|
||||
",
|
||||
port
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 403 Forbidden".to_owned());
|
||||
http_client::assert_security_headers_present(&response.headers, None);
|
||||
}
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 403 Forbidden".to_owned());
|
||||
http_client::assert_security_headers_present(&response.headers, None);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
fn should_allow_if_authorization_is_correct() {
|
||||
// given
|
||||
let (server, port, mut authcodes) = serve();
|
||||
let code = authcodes.generate_new().unwrap().replace("-", "");
|
||||
authcodes.to_file(&authcodes.path).unwrap();
|
||||
let timestamp = time::UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
fn should_allow_if_authorization_is_correct() {
|
||||
// given
|
||||
let (server, port, mut authcodes) = serve();
|
||||
let code = authcodes.generate_new().unwrap().replace("-", "");
|
||||
authcodes.to_file(&authcodes.path).unwrap();
|
||||
let timestamp = time::UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
|
||||
// when
|
||||
let response = request(server,
|
||||
&format!("\
|
||||
// when
|
||||
let response = request(
|
||||
server,
|
||||
&format!(
|
||||
"\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Host: 127.0.0.1:{}\r\n\
|
||||
Connection: Close\r\n\
|
||||
@@ -123,27 +138,32 @@ mod testing {
|
||||
\r\n\
|
||||
{{}}
|
||||
",
|
||||
port,
|
||||
keccak(format!("{}:{}", code, timestamp)),
|
||||
timestamp,
|
||||
)
|
||||
);
|
||||
port,
|
||||
keccak(format!("{}:{}", code, timestamp)),
|
||||
timestamp,
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 101 Switching Protocols".to_owned());
|
||||
}
|
||||
// then
|
||||
assert_eq!(
|
||||
response.status,
|
||||
"HTTP/1.1 101 Switching Protocols".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_allow_initial_connection_even_once() {
|
||||
// given
|
||||
let (server, port, authcodes) = serve();
|
||||
let code = "initial";
|
||||
let timestamp = time::UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
assert!(authcodes.is_empty());
|
||||
#[test]
|
||||
fn should_not_allow_initial_connection_even_once() {
|
||||
// given
|
||||
let (server, port, authcodes) = serve();
|
||||
let code = "initial";
|
||||
let timestamp = time::UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||
assert!(authcodes.is_empty());
|
||||
|
||||
// when
|
||||
let response1 = http_client::request(server.addr(),
|
||||
&format!("\
|
||||
// when
|
||||
let response1 = http_client::request(
|
||||
server.addr(),
|
||||
&format!(
|
||||
"\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Host: 127.0.0.1:{}\r\n\
|
||||
Connection: Close\r\n\
|
||||
@@ -153,14 +173,14 @@ mod testing {
|
||||
\r\n\
|
||||
{{}}
|
||||
",
|
||||
port,
|
||||
keccak(format!("{}:{}", code, timestamp)),
|
||||
timestamp,
|
||||
)
|
||||
);
|
||||
port,
|
||||
keccak(format!("{}:{}", code, timestamp)),
|
||||
timestamp,
|
||||
),
|
||||
);
|
||||
|
||||
// then
|
||||
assert_eq!(response1.status, "HTTP/1.1 403 Forbidden".to_owned());
|
||||
http_client::assert_security_headers_present(&response1.headers, None);
|
||||
}
|
||||
// then
|
||||
assert_eq!(response1.status, "HTTP/1.1 403 Forbidden".to_owned());
|
||||
http_client::assert_security_headers_present(&response1.headers, None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user