1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

Do not set default headers for websocket request

This commit is contained in:
Nikolay Kim 2019-04-14 07:43:53 -07:00
parent 5bd5651faa
commit 6bc1a0c76b
5 changed files with 198 additions and 167 deletions

View File

@ -182,6 +182,8 @@
} }
``` ```
* `actix_web::server` module has been removed. To start http server use `actix_web::HttpServer` type
* StaticFiles and NamedFile has been move to separate create. * StaticFiles and NamedFile has been move to separate create.
instead of `use actix_web::fs::StaticFile` instead of `use actix_web::fs::StaticFile`
@ -198,10 +200,10 @@
use `use actix_multipart::Multipart` use `use actix_multipart::Multipart`
* Request/response compression/decompression is not enabled by default. * Response compression is not enabled by default.
To enable use `App::enable_encoding()` method. To enable, use `Compress` middleware, `App::new().wrap(Compress::default())`.
* `actix_web::server` module has been removed. To start http server use `actix_web::HttpServer` type * Session middleware moved to actix-session crate
* Actors support have been moved to `actix-web-actors` crate * Actors support have been moved to `actix-web-actors` crate

View File

@ -1,5 +1,12 @@
# Changes # Changes
## [0.1.0-alpha.6] - 2019-04-xx
### Changed
* Do not set default headers for websocket request
## [0.1.0-alpha.5] - 2019-04-12 ## [0.1.0-alpha.5] - 2019-04-12
### Changed ### Changed

View File

@ -545,101 +545,91 @@ impl fmt::Debug for ClientRequest {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{test, Client}; use crate::Client;
#[test] #[test]
fn test_debug() { fn test_debug() {
test::run_on(|| { let request = Client::new().get("/").header("x-test", "111");
let request = Client::new().get("/").header("x-test", "111"); let repr = format!("{:?}", request);
let repr = format!("{:?}", request); assert!(repr.contains("ClientRequest"));
assert!(repr.contains("ClientRequest")); assert!(repr.contains("x-test"));
assert!(repr.contains("x-test"));
})
} }
#[test] #[test]
fn test_client_header() { fn test_client_header() {
test::run_on(|| { let req = Client::build()
let req = Client::build() .header(header::CONTENT_TYPE, "111")
.header(header::CONTENT_TYPE, "111") .finish()
.finish() .get("/");
.get("/");
assert_eq!( assert_eq!(
req.head req.head
.headers .headers
.get(header::CONTENT_TYPE) .get(header::CONTENT_TYPE)
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap(), .unwrap(),
"111" "111"
); );
})
} }
#[test] #[test]
fn test_client_header_override() { fn test_client_header_override() {
test::run_on(|| { let req = Client::build()
let req = Client::build() .header(header::CONTENT_TYPE, "111")
.header(header::CONTENT_TYPE, "111") .finish()
.finish() .get("/")
.get("/") .set_header(header::CONTENT_TYPE, "222");
.set_header(header::CONTENT_TYPE, "222");
assert_eq!( assert_eq!(
req.head req.head
.headers .headers
.get(header::CONTENT_TYPE) .get(header::CONTENT_TYPE)
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap(), .unwrap(),
"222" "222"
); );
})
} }
#[test] #[test]
fn client_basic_auth() { fn client_basic_auth() {
test::run_on(|| { let req = Client::new()
let req = Client::new() .get("/")
.get("/") .basic_auth("username", Some("password"));
.basic_auth("username", Some("password")); assert_eq!(
assert_eq!( req.head
req.head .headers
.headers .get(header::AUTHORIZATION)
.get(header::AUTHORIZATION) .unwrap()
.unwrap() .to_str()
.to_str() .unwrap(),
.unwrap(), "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
"Basic dXNlcm5hbWU6cGFzc3dvcmQ=" );
);
let req = Client::new().get("/").basic_auth("username", None); let req = Client::new().get("/").basic_auth("username", None);
assert_eq!( assert_eq!(
req.head req.head
.headers .headers
.get(header::AUTHORIZATION) .get(header::AUTHORIZATION)
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap(), .unwrap(),
"Basic dXNlcm5hbWU=" "Basic dXNlcm5hbWU="
); );
});
} }
#[test] #[test]
fn client_bearer_auth() { fn client_bearer_auth() {
test::run_on(|| { let req = Client::new().get("/").bearer_auth("someS3cr3tAutht0k3n");
let req = Client::new().get("/").bearer_auth("someS3cr3tAutht0k3n"); assert_eq!(
assert_eq!( req.head
req.head .headers
.headers .get(header::AUTHORIZATION)
.get(header::AUTHORIZATION) .unwrap()
.unwrap() .to_str()
.to_str() .unwrap(),
.unwrap(), "Bearer someS3cr3tAutht0k3n"
"Bearer someS3cr3tAutht0k3n" );
);
})
} }
} }

View File

@ -1,13 +1,11 @@
//! Websockets client //! Websockets client
use std::fmt::Write as FmtWrite; use std::fmt::Write as FmtWrite;
use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
use std::{fmt, str}; use std::{fmt, str};
use actix_codec::Framed; use actix_codec::Framed;
use actix_http::cookie::{Cookie, CookieJar}; use actix_http::cookie::{Cookie, CookieJar};
use actix_http::{ws, Payload, RequestHead}; use actix_http::{ws, Payload, RequestHead};
use bytes::{BufMut, BytesMut};
use futures::future::{err, Either, Future}; use futures::future::{err, Either, Future};
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET}; use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
use tokio_timer::Timeout; use tokio_timer::Timeout;
@ -33,7 +31,6 @@ pub struct WebsocketsRequest {
protocols: Option<String>, protocols: Option<String>,
max_size: usize, max_size: usize,
server_mode: bool, server_mode: bool,
default_headers: bool,
cookies: Option<CookieJar>, cookies: Option<CookieJar>,
config: Rc<ClientConfig>, config: Rc<ClientConfig>,
} }
@ -63,7 +60,6 @@ impl WebsocketsRequest {
max_size: 65_536, max_size: 65_536,
server_mode: false, server_mode: false,
cookies: None, cookies: None,
default_headers: true,
} }
} }
@ -119,13 +115,6 @@ impl WebsocketsRequest {
self self
} }
/// Do not add default request headers.
/// By default `Date` and `User-Agent` headers are set.
pub fn no_default_headers(mut self) -> Self {
self.default_headers = false;
self
}
/// Append a header. /// Append a header.
/// ///
/// Header gets appended to existing header. /// Header gets appended to existing header.
@ -188,10 +177,9 @@ impl WebsocketsRequest {
} }
/// Set HTTP basic authorization header /// Set HTTP basic authorization header
pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> Self pub fn basic_auth<U>(self, username: U, password: Option<&str>) -> Self
where where
U: fmt::Display, U: fmt::Display,
P: fmt::Display,
{ {
let auth = match password { let auth = match password {
Some(password) => format!("{}:{}", username, password), Some(password) => format!("{}:{}", username, password),
@ -232,67 +220,36 @@ impl WebsocketsRequest {
return Either::A(err(InvalidUrl::UnknownScheme.into())); return Either::A(err(InvalidUrl::UnknownScheme.into()));
} }
// set default headers
let mut slf = if self.default_headers {
// set request host header
if let Some(host) = self.head.uri.host() {
if !self.head.headers.contains_key(&header::HOST) {
let mut wrt = BytesMut::with_capacity(host.len() + 5).writer();
let _ = match self.head.uri.port_u16() {
None | Some(80) | Some(443) => write!(wrt, "{}", host),
Some(port) => write!(wrt, "{}:{}", host, port),
};
match wrt.get_mut().take().freeze().try_into() {
Ok(value) => {
self.head.headers.insert(header::HOST, value);
}
Err(e) => return Either::A(err(HttpError::from(e).into())),
}
}
}
// user agent
self.set_header_if_none(
header::USER_AGENT,
concat!("awc/", env!("CARGO_PKG_VERSION")),
)
} else {
self
};
let mut head = slf.head;
// set cookies // set cookies
if let Some(ref mut jar) = slf.cookies { if let Some(ref mut jar) = self.cookies {
let mut cookie = String::new(); let mut cookie = String::new();
for c in jar.delta() { for c in jar.delta() {
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET); let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET); let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
let _ = write!(&mut cookie, "; {}={}", name, value); let _ = write!(&mut cookie, "; {}={}", name, value);
} }
head.headers.insert( self.head.headers.insert(
header::COOKIE, header::COOKIE,
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(), HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
); );
} }
// origin // origin
if let Some(origin) = slf.origin.take() { if let Some(origin) = self.origin.take() {
head.headers.insert(header::ORIGIN, origin); self.head.headers.insert(header::ORIGIN, origin);
} }
head.set_connection_type(ConnectionType::Upgrade); self.head.set_connection_type(ConnectionType::Upgrade);
head.headers self.head
.headers
.insert(header::UPGRADE, HeaderValue::from_static("websocket")); .insert(header::UPGRADE, HeaderValue::from_static("websocket"));
head.headers.insert( self.head.headers.insert(
header::SEC_WEBSOCKET_VERSION, header::SEC_WEBSOCKET_VERSION,
HeaderValue::from_static("13"), HeaderValue::from_static("13"),
); );
if let Some(protocols) = slf.protocols.take() { if let Some(protocols) = self.protocols.take() {
head.headers.insert( self.head.headers.insert(
header::SEC_WEBSOCKET_PROTOCOL, header::SEC_WEBSOCKET_PROTOCOL,
HeaderValue::try_from(protocols.as_str()).unwrap(), HeaderValue::try_from(protocols.as_str()).unwrap(),
); );
@ -304,15 +261,16 @@ impl WebsocketsRequest {
let sec_key: [u8; 16] = rand::random(); let sec_key: [u8; 16] = rand::random();
let key = base64::encode(&sec_key); let key = base64::encode(&sec_key);
head.headers.insert( self.head.headers.insert(
header::SEC_WEBSOCKET_KEY, header::SEC_WEBSOCKET_KEY,
HeaderValue::try_from(key.as_str()).unwrap(), HeaderValue::try_from(key.as_str()).unwrap(),
); );
let max_size = slf.max_size; let head = self.head;
let server_mode = slf.server_mode; let max_size = self.max_size;
let server_mode = self.server_mode;
let fut = slf let fut = self
.config .config
.connector .connector
.borrow_mut() .borrow_mut()
@ -387,7 +345,7 @@ impl WebsocketsRequest {
}); });
// set request timeout // set request timeout
if let Some(timeout) = slf.config.timeout { if let Some(timeout) = self.config.timeout {
Either::B(Either::A(Timeout::new(fut, timeout).map_err(|e| { Either::B(Either::A(Timeout::new(fut, timeout).map_err(|e| {
if let Some(e) = e.into_inner() { if let Some(e) = e.into_inner() {
e e
@ -400,3 +358,107 @@ impl WebsocketsRequest {
} }
} }
} }
impl fmt::Debug for WebsocketsRequest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
"\nWebsocketsRequest {}:{}",
self.head.method, self.head.uri
)?;
writeln!(f, " headers:")?;
for (key, val) in self.head.headers.iter() {
writeln!(f, " {:?}: {:?}", key, val)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Client;
#[test]
fn test_debug() {
let request = Client::new().ws("/").header("x-test", "111");
let repr = format!("{:?}", request);
assert!(repr.contains("WebsocketsRequest"));
assert!(repr.contains("x-test"));
}
#[test]
fn test_header_override() {
let req = Client::build()
.header(header::CONTENT_TYPE, "111")
.finish()
.ws("/")
.set_header(header::CONTENT_TYPE, "222");
assert_eq!(
req.head
.headers
.get(header::CONTENT_TYPE)
.unwrap()
.to_str()
.unwrap(),
"222"
);
}
#[test]
fn basic_auth() {
let req = Client::new()
.ws("/")
.basic_auth("username", Some("password"));
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Basic dXNlcm5hbWU6cGFzc3dvcmQ="
);
let req = Client::new().ws("/").basic_auth("username", None);
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Basic dXNlcm5hbWU="
);
}
#[test]
fn bearer_auth() {
let req = Client::new().ws("/").bearer_auth("someS3cr3tAutht0k3n");
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Bearer someS3cr3tAutht0k3n"
);
}
#[test]
fn basics() {
let req = Client::new()
.ws("/")
.origin("test-origin")
.max_frame_size(100)
.server_mode()
.protocols(&["v1", "v2"])
.cookie(Cookie::build("cookie1", "value1").finish());
assert_eq!(req.origin.unwrap().to_str().unwrap(), "test-origin");
assert_eq!(req.max_size, 100);
assert_eq!(req.server_mode, true);
assert_eq!(req.protocols, Some("v1,v2".to_string()));
}
}

View File

@ -10,6 +10,7 @@ use rand::Rng;
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::TestServer; use actix_http_test::TestServer;
use actix_web::http::Cookie;
use actix_web::{http::header, web, App, Error, HttpMessage, HttpRequest, HttpResponse}; use actix_web::{http::header, web, App, Error, HttpMessage, HttpRequest, HttpResponse};
use awc::error::SendRequestError; use awc::error::SendRequestError;
@ -406,7 +407,6 @@ fn test_client_brotli_encoding() {
#[test] #[test]
fn test_client_cookie_handling() { fn test_client_cookie_handling() {
use actix_web::http::Cookie;
fn err() -> Error { fn err() -> Error {
use std::io::{Error as IoError, ErrorKind}; use std::io::{Error as IoError, ErrorKind};
// stub some generic error // stub some generic error
@ -468,36 +468,6 @@ fn test_client_cookie_handling() {
assert_eq!(c2, cookie2); assert_eq!(c2, cookie2);
} }
// #[test]
// fn test_default_headers() {
// let srv = test::TestServer::new(|app| app.handler(|_| HttpResponse::Ok().body(STR)));
// let request = srv.get("/").finish().unwrap();
// let repr = format!("{:?}", request);
// assert!(repr.contains("\"accept-encoding\": \"gzip, deflate\""));
// assert!(repr.contains(concat!(
// "\"user-agent\": \"actix-web/",
// env!("CARGO_PKG_VERSION"),
// "\""
// )));
// let request_override = srv
// .get("/")
// .header("User-Agent", "test")
// .header("Accept-Encoding", "over_test")
// .finish()
// .unwrap();
// let repr_override = format!("{:?}", request_override);
// assert!(repr_override.contains("\"user-agent\": \"test\""));
// assert!(repr_override.contains("\"accept-encoding\": \"over_test\""));
// assert!(!repr_override.contains("\"accept-encoding\": \"gzip, deflate\""));
// assert!(!repr_override.contains(concat!(
// "\"user-agent\": \"Actix-web/",
// env!("CARGO_PKG_VERSION"),
// "\""
// )));
// }
// #[test] // #[test]
// fn client_read_until_eof() { // fn client_read_until_eof() {
// let addr = test::TestServer::unused_addr(); // let addr = test::TestServer::unused_addr();