mirror of
https://github.com/fafhrd91/actix-web
synced 2025-08-26 23:24:47 +02:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1fcf1d4a49 | ||
|
4012606910 | ||
|
e975124630 | ||
|
6862aa6ee7 | ||
|
8a22558f25 | ||
|
b5b9f9656e | ||
|
2fffc55d34 | ||
|
7d39f1582e | ||
|
75ed053a35 | ||
|
cfedf5fff4 | ||
|
be73a36339 | ||
|
1ad8ba2604 |
22
CHANGES.md
22
CHANGES.md
@@ -1,5 +1,27 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.6.14] - 2018-06-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Allow to disable masking for websockets client
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* SendRequest execution fails with the "internal error: entered unreachable code" #329
|
||||||
|
|
||||||
|
|
||||||
|
## [0.6.13] - 2018-06-13
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* http/2 end-of-frame is not set if body is empty bytes #307
|
||||||
|
|
||||||
|
* InternalError can trigger memory unsafety #301
|
||||||
|
|
||||||
|
* Fix docs.rs build
|
||||||
|
|
||||||
|
|
||||||
## [0.6.12] - 2018-06-08
|
## [0.6.12] - 2018-06-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-web"
|
name = "actix-web"
|
||||||
version = "0.6.12"
|
version = "0.6.14"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@@ -865,7 +865,7 @@ impl fut::ActorFuture for Maintenance {
|
|||||||
let conn = AcquiredConn(key.clone(), Some(Rc::clone(&act.pool)));
|
let conn = AcquiredConn(key.clone(), Some(Rc::clone(&act.pool)));
|
||||||
|
|
||||||
fut::WrapFuture::<ClientConnector>::actfuture(
|
fut::WrapFuture::<ClientConnector>::actfuture(
|
||||||
Connector::from_registry().send(
|
act.resolver.send(
|
||||||
ResolveConnect::host_and_port(&conn.0.host, conn.0.port)
|
ResolveConnect::host_and_port(&conn.0.host, conn.0.port)
|
||||||
.timeout(waiter.conn_timeout),
|
.timeout(waiter.conn_timeout),
|
||||||
),
|
),
|
||||||
|
@@ -380,7 +380,7 @@ impl Pipeline {
|
|||||||
match self.timeout.as_mut().unwrap().poll() {
|
match self.timeout.as_mut().unwrap().poll() {
|
||||||
Ok(Async::Ready(())) => return Err(SendRequestError::Timeout),
|
Ok(Async::Ready(())) => return Err(SendRequestError::Timeout),
|
||||||
Ok(Async::NotReady) => (),
|
Ok(Async::NotReady) => (),
|
||||||
Err(_) => unreachable!(),
|
Err(e) => return Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
70
src/error.rs
70
src/error.rs
@@ -1,9 +1,9 @@
|
|||||||
//! Error and Result module
|
//! Error and Result module
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use std::{fmt, io, result};
|
use std::sync::Mutex;
|
||||||
|
use std::{fmt, io, mem, result};
|
||||||
|
|
||||||
use actix::MailboxError;
|
use actix::MailboxError;
|
||||||
use cookie;
|
use cookie;
|
||||||
@@ -21,9 +21,10 @@ pub use url::ParseError as UrlParseError;
|
|||||||
// re-exports
|
// re-exports
|
||||||
pub use cookie::ParseError as CookieParseError;
|
pub use cookie::ParseError as CookieParseError;
|
||||||
|
|
||||||
|
use body::Body;
|
||||||
use handler::Responder;
|
use handler::Responder;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::{HttpResponse, InnerHttpResponse};
|
||||||
|
|
||||||
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
|
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
|
||||||
/// for actix web operations
|
/// for actix web operations
|
||||||
@@ -35,7 +36,7 @@ pub type Result<T, E = Error> = result::Result<T, E>;
|
|||||||
|
|
||||||
/// General purpose actix web error.
|
/// General purpose actix web error.
|
||||||
///
|
///
|
||||||
/// An actix web error is used to carry errors from `failure` or `std::error`
|
/// An actix web error is used to carry errors from `failure` or `std::error`
|
||||||
/// through actix in a convenient way. It can be created through through
|
/// through actix in a convenient way. It can be created through through
|
||||||
/// converting errors with `into()`.
|
/// converting errors with `into()`.
|
||||||
///
|
///
|
||||||
@@ -50,7 +51,9 @@ pub struct Error {
|
|||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
/// Deprecated way to reference the underlying response error.
|
/// Deprecated way to reference the underlying response error.
|
||||||
#[deprecated(since = "0.6.0", note = "please use `Error::as_response_error()` instead")]
|
#[deprecated(
|
||||||
|
since = "0.6.0", note = "please use `Error::as_response_error()` instead"
|
||||||
|
)]
|
||||||
pub fn cause(&self) -> &ResponseError {
|
pub fn cause(&self) -> &ResponseError {
|
||||||
self.cause.as_ref()
|
self.cause.as_ref()
|
||||||
}
|
}
|
||||||
@@ -77,7 +80,8 @@ impl Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to downcast this `Error` to a particular `Fail` type by reference.
|
/// Attempts to downcast this `Error` to a particular `Fail` type by
|
||||||
|
/// reference.
|
||||||
///
|
///
|
||||||
/// If the underlying error is not of type `T`, this will return `None`.
|
/// If the underlying error is not of type `T`, this will return `None`.
|
||||||
pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
|
pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
|
||||||
@@ -96,14 +100,13 @@ impl Error {
|
|||||||
//
|
//
|
||||||
// This currently requires a transmute. This could be avoided if failure
|
// This currently requires a transmute. This could be avoided if failure
|
||||||
// provides a deref: https://github.com/rust-lang-nursery/failure/pull/213
|
// provides a deref: https://github.com/rust-lang-nursery/failure/pull/213
|
||||||
let compat: Option<&failure::Compat<failure::Error>> = Fail::downcast_ref(self.cause.as_fail());
|
let compat: Option<&failure::Compat<failure::Error>> =
|
||||||
|
Fail::downcast_ref(self.cause.as_fail());
|
||||||
if let Some(compat) = compat {
|
if let Some(compat) = compat {
|
||||||
pub struct CompatWrappedError {
|
pub struct CompatWrappedError {
|
||||||
error: failure::Error,
|
error: failure::Error,
|
||||||
}
|
}
|
||||||
let compat: &CompatWrappedError = unsafe {
|
let compat: &CompatWrappedError = unsafe { ::std::mem::transmute(compat) };
|
||||||
::std::mem::transmute(compat)
|
|
||||||
};
|
|
||||||
compat.error.downcast_ref()
|
compat.error.downcast_ref()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -113,8 +116,8 @@ impl Error {
|
|||||||
|
|
||||||
/// Helper trait to downcast a response error into a fail.
|
/// Helper trait to downcast a response error into a fail.
|
||||||
///
|
///
|
||||||
/// This is currently not exposed because it's unclear if this is the best way to
|
/// This is currently not exposed because it's unclear if this is the best way
|
||||||
/// achieve the downcasting on `Error` for which this is needed.
|
/// to achieve the downcasting on `Error` for which this is needed.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait InternalResponseErrorAsFail {
|
pub trait InternalResponseErrorAsFail {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -125,8 +128,12 @@ pub trait InternalResponseErrorAsFail {
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl<T: ResponseError> InternalResponseErrorAsFail for T {
|
impl<T: ResponseError> InternalResponseErrorAsFail for T {
|
||||||
fn as_fail(&self) -> &Fail { self }
|
fn as_fail(&self) -> &Fail {
|
||||||
fn as_mut_fail(&mut self) -> &mut Fail { self }
|
self
|
||||||
|
}
|
||||||
|
fn as_mut_fail(&mut self) -> &mut Fail {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error that can be converted to `HttpResponse`
|
/// Error that can be converted to `HttpResponse`
|
||||||
@@ -183,11 +190,9 @@ impl<T: ResponseError> From<T> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compatibility for `failure::Error`
|
/// Compatibility for `failure::Error`
|
||||||
impl<T> ResponseError for failure::Compat<T>
|
impl<T> ResponseError for failure::Compat<T> where
|
||||||
where
|
T: fmt::Display + fmt::Debug + Sync + Send + 'static
|
||||||
T: fmt::Display + fmt::Debug + Sync + Send + 'static,
|
{}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<failure::Error> for Error {
|
impl From<failure::Error> for Error {
|
||||||
fn from(err: failure::Error) -> Error {
|
fn from(err: failure::Error) -> Error {
|
||||||
@@ -620,8 +625,8 @@ impl From<UrlParseError> for UrlGenerationError {
|
|||||||
/// use actix_web::fs::NamedFile;
|
/// use actix_web::fs::NamedFile;
|
||||||
///
|
///
|
||||||
/// fn index(req: HttpRequest) -> Result<fs::NamedFile> {
|
/// fn index(req: HttpRequest) -> Result<fs::NamedFile> {
|
||||||
/// let f = NamedFile::open("test.txt").map_err(error::ErrorBadRequest)?;
|
/// let f = NamedFile::open("test.txt").map_err(error::ErrorBadRequest)?;
|
||||||
/// Ok(f)
|
/// Ok(f)
|
||||||
/// }
|
/// }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
@@ -631,12 +636,9 @@ pub struct InternalError<T> {
|
|||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T> Sync for InternalError<T> {}
|
|
||||||
unsafe impl<T> Send for InternalError<T> {}
|
|
||||||
|
|
||||||
enum InternalErrorType {
|
enum InternalErrorType {
|
||||||
Status(StatusCode),
|
Status(StatusCode),
|
||||||
Response(RefCell<Option<HttpResponse>>),
|
Response(Mutex<Option<Box<InnerHttpResponse>>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InternalError<T> {
|
impl<T> InternalError<T> {
|
||||||
@@ -651,9 +653,21 @@ impl<T> InternalError<T> {
|
|||||||
|
|
||||||
/// Create `InternalError` with predefined `HttpResponse`.
|
/// Create `InternalError` with predefined `HttpResponse`.
|
||||||
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
||||||
|
let mut resp = response.into_inner();
|
||||||
|
let body = mem::replace(&mut resp.body, Body::Empty);
|
||||||
|
match body {
|
||||||
|
Body::Empty => (),
|
||||||
|
Body::Binary(mut bin) => {
|
||||||
|
resp.body = Body::Binary(bin.take().into());
|
||||||
|
}
|
||||||
|
Body::Streaming(_) | Body::Actor(_) => {
|
||||||
|
error!("Streaming or Actor body is not support by error response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InternalError {
|
InternalError {
|
||||||
cause,
|
cause,
|
||||||
status: InternalErrorType::Response(RefCell::new(Some(response))),
|
status: InternalErrorType::Response(Mutex::new(Some(resp))),
|
||||||
backtrace: Backtrace::new(),
|
backtrace: Backtrace::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,8 +708,8 @@ where
|
|||||||
match self.status {
|
match self.status {
|
||||||
InternalErrorType::Status(st) => HttpResponse::new(st),
|
InternalErrorType::Status(st) => HttpResponse::new(st),
|
||||||
InternalErrorType::Response(ref resp) => {
|
InternalErrorType::Response(ref resp) => {
|
||||||
if let Some(resp) = resp.borrow_mut().take() {
|
if let Some(resp) = resp.lock().unwrap().take() {
|
||||||
resp
|
HttpResponse::from_inner(resp)
|
||||||
} else {
|
} else {
|
||||||
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
|
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
}
|
}
|
||||||
|
@@ -241,6 +241,14 @@ impl HttpResponse {
|
|||||||
pub fn set_write_buffer_capacity(&mut self, cap: usize) {
|
pub fn set_write_buffer_capacity(&mut self, cap: usize) {
|
||||||
self.get_mut().write_capacity = cap;
|
self.get_mut().write_capacity = cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn into_inner(mut self) -> Box<InnerHttpResponse> {
|
||||||
|
self.0.take().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_inner(inner: Box<InnerHttpResponse>) -> HttpResponse {
|
||||||
|
HttpResponse(Some(inner), HttpResponsePool::pool())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for HttpResponse {
|
impl fmt::Debug for HttpResponse {
|
||||||
@@ -297,11 +305,13 @@ impl HttpResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # extern crate actix_web;
|
||||||
/// use actix_web::{HttpRequest, HttpResponse, Result, http};
|
/// use actix_web::{http, HttpRequest, HttpResponse, Result};
|
||||||
///
|
///
|
||||||
/// fn index(req: HttpRequest) -> Result<HttpResponse> {
|
/// fn index(req: HttpRequest) -> Result<HttpResponse> {
|
||||||
/// Ok(HttpResponse::Ok()
|
/// Ok(HttpResponse::Ok()
|
||||||
/// .set(http::header::IfModifiedSince("Sun, 07 Nov 1994 08:48:37 GMT".parse()?))
|
/// .set(http::header::IfModifiedSince(
|
||||||
|
/// "Sun, 07 Nov 1994 08:48:37 GMT".parse()?,
|
||||||
|
/// ))
|
||||||
/// .finish())
|
/// .finish())
|
||||||
/// }
|
/// }
|
||||||
/// fn main() {}
|
/// fn main() {}
|
||||||
@@ -455,7 +465,8 @@ impl HttpResponseBuilder {
|
|||||||
/// .path("/")
|
/// .path("/")
|
||||||
/// .secure(true)
|
/// .secure(true)
|
||||||
/// .http_only(true)
|
/// .http_only(true)
|
||||||
/// .finish())
|
/// .finish(),
|
||||||
|
/// )
|
||||||
/// .finish()
|
/// .finish()
|
||||||
/// }
|
/// }
|
||||||
/// fn main() {}
|
/// fn main() {}
|
||||||
@@ -781,12 +792,12 @@ impl<'a, S> From<&'a HttpRequest<S>> for HttpResponseBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct InnerHttpResponse {
|
pub(crate) struct InnerHttpResponse {
|
||||||
version: Option<Version>,
|
version: Option<Version>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
reason: Option<&'static str>,
|
reason: Option<&'static str>,
|
||||||
body: Body,
|
pub(crate) body: Body,
|
||||||
chunked: Option<bool>,
|
chunked: Option<bool>,
|
||||||
encoding: Option<ContentEncoding>,
|
encoding: Option<ContentEncoding>,
|
||||||
connection_type: Option<ConnectionType>,
|
connection_type: Option<ConnectionType>,
|
||||||
@@ -795,6 +806,9 @@ struct InnerHttpResponse {
|
|||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for InnerHttpResponse {}
|
||||||
|
unsafe impl Send for InnerHttpResponse {}
|
||||||
|
|
||||||
impl InnerHttpResponse {
|
impl InnerHttpResponse {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(status: StatusCode, body: Body) -> InnerHttpResponse {
|
fn new(status: StatusCode, body: Body) -> InnerHttpResponse {
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@@ -6,15 +6,15 @@
|
|||||||
//! # use std::thread;
|
//! # use std::thread;
|
||||||
//!
|
//!
|
||||||
//! fn index(info: Path<(String, u32)>) -> String {
|
//! fn index(info: Path<(String, u32)>) -> String {
|
||||||
//! format!("Hello {}! id:{}", info.0, info.1)
|
//! format!("Hello {}! id:{}", info.0, info.1)
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! # thread::spawn(|| {
|
//! # thread::spawn(|| {
|
||||||
//! server::new(
|
//! server::new(|| {
|
||||||
//! || App::new()
|
//! App::new().resource("/{name}/{id}/index.html", |r| r.with(index))
|
||||||
//! .resource("/{name}/{id}/index.html", |r| r.with(index)))
|
//! }).bind("127.0.0.1:8080")
|
||||||
//! .bind("127.0.0.1:8080").unwrap()
|
//! .unwrap()
|
||||||
//! .run();
|
//! .run();
|
||||||
//! # });
|
//! # });
|
||||||
//! }
|
//! }
|
||||||
@@ -77,6 +77,7 @@
|
|||||||
//!
|
//!
|
||||||
#![cfg_attr(actix_nightly, feature(
|
#![cfg_attr(actix_nightly, feature(
|
||||||
specialization, // for impl ErrorResponse for std::error::Error
|
specialization, // for impl ErrorResponse for std::error::Error
|
||||||
|
extern_prelude,
|
||||||
))]
|
))]
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
|
@@ -89,9 +89,6 @@ impl<H: 'static> Writer for H2Writer<H> {
|
|||||||
self.flags.insert(Flags::STARTED);
|
self.flags.insert(Flags::STARTED);
|
||||||
self.encoder =
|
self.encoder =
|
||||||
ContentEncoder::for_server(self.buffer.clone(), req, msg, encoding);
|
ContentEncoder::for_server(self.buffer.clone(), req, msg, encoding);
|
||||||
if let Body::Empty = *msg.body() {
|
|
||||||
self.flags.insert(Flags::EOF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// http2 specific
|
// http2 specific
|
||||||
msg.headers_mut().remove(CONNECTION);
|
msg.headers_mut().remove(CONNECTION);
|
||||||
@@ -108,15 +105,22 @@ impl<H: 'static> Writer for H2Writer<H> {
|
|||||||
let body = msg.replace_body(Body::Empty);
|
let body = msg.replace_body(Body::Empty);
|
||||||
match body {
|
match body {
|
||||||
Body::Binary(ref bytes) => {
|
Body::Binary(ref bytes) => {
|
||||||
let mut val = BytesMut::new();
|
if bytes.is_empty() {
|
||||||
helpers::convert_usize(bytes.len(), &mut val);
|
msg.headers_mut()
|
||||||
let l = val.len();
|
.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
|
||||||
msg.headers_mut().insert(
|
self.flags.insert(Flags::EOF);
|
||||||
CONTENT_LENGTH,
|
} else {
|
||||||
HeaderValue::try_from(val.split_to(l - 2).freeze()).unwrap(),
|
let mut val = BytesMut::new();
|
||||||
);
|
helpers::convert_usize(bytes.len(), &mut val);
|
||||||
|
let l = val.len();
|
||||||
|
msg.headers_mut().insert(
|
||||||
|
CONTENT_LENGTH,
|
||||||
|
HeaderValue::try_from(val.split_to(l - 2).freeze()).unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Body::Empty => {
|
Body::Empty => {
|
||||||
|
self.flags.insert(Flags::EOF);
|
||||||
msg.headers_mut()
|
msg.headers_mut()
|
||||||
.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
|
.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
|
||||||
}
|
}
|
||||||
@@ -141,14 +145,18 @@ impl<H: 'static> Writer for H2Writer<H> {
|
|||||||
trace!("Response: {:?}", msg);
|
trace!("Response: {:?}", msg);
|
||||||
|
|
||||||
if let Body::Binary(bytes) = body {
|
if let Body::Binary(bytes) = body {
|
||||||
self.flags.insert(Flags::EOF);
|
if bytes.is_empty() {
|
||||||
self.written = bytes.len() as u64;
|
Ok(WriterState::Done)
|
||||||
self.encoder.write(bytes)?;
|
} else {
|
||||||
if let Some(ref mut stream) = self.stream {
|
self.flags.insert(Flags::EOF);
|
||||||
self.flags.insert(Flags::RESERVED);
|
self.written = bytes.len() as u64;
|
||||||
stream.reserve_capacity(cmp::min(self.buffer.len(), CHUNK_SIZE));
|
self.encoder.write(bytes)?;
|
||||||
|
if let Some(ref mut stream) = self.stream {
|
||||||
|
self.flags.insert(Flags::RESERVED);
|
||||||
|
stream.reserve_capacity(cmp::min(self.buffer.len(), CHUNK_SIZE));
|
||||||
|
}
|
||||||
|
Ok(WriterState::Pause)
|
||||||
}
|
}
|
||||||
Ok(WriterState::Pause)
|
|
||||||
} else {
|
} else {
|
||||||
msg.replace_body(body);
|
msg.replace_body(body);
|
||||||
self.buffer_capacity = msg.write_buffer_capacity();
|
self.buffer_capacity = msg.write_buffer_capacity();
|
||||||
@@ -177,10 +185,8 @@ impl<H: 'static> Writer for H2Writer<H> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_eof(&mut self) -> io::Result<WriterState> {
|
fn write_eof(&mut self) -> io::Result<WriterState> {
|
||||||
self.encoder.write_eof()?;
|
|
||||||
|
|
||||||
self.flags.insert(Flags::EOF);
|
self.flags.insert(Flags::EOF);
|
||||||
if !self.encoder.is_eof() {
|
if !self.encoder.write_eof()? {
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Last payload item, but eof is not reached",
|
"Last payload item, but eof is not reached",
|
||||||
|
@@ -113,6 +113,7 @@ pub struct Client {
|
|||||||
protocols: Option<String>,
|
protocols: Option<String>,
|
||||||
conn: Addr<Unsync, ClientConnector>,
|
conn: Addr<Unsync, ClientConnector>,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
|
no_masking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@@ -132,6 +133,7 @@ impl Client {
|
|||||||
origin: None,
|
origin: None,
|
||||||
protocols: None,
|
protocols: None,
|
||||||
max_size: 65_536,
|
max_size: 65_536,
|
||||||
|
no_masking: false,
|
||||||
conn,
|
conn,
|
||||||
};
|
};
|
||||||
cl.request.uri(uri.as_ref());
|
cl.request.uri(uri.as_ref());
|
||||||
@@ -186,6 +188,12 @@ impl Client {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disable payload masking. By default ws client masks frame payload.
|
||||||
|
pub fn no_masking(mut self) -> Self {
|
||||||
|
self.no_masking = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set request header
|
/// Set request header
|
||||||
pub fn header<K, V>(mut self, key: K, value: V) -> Self
|
pub fn header<K, V>(mut self, key: K, value: V) -> Self
|
||||||
where
|
where
|
||||||
@@ -248,7 +256,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start handshake
|
// start handshake
|
||||||
ClientHandshake::new(request, self.max_size)
|
ClientHandshake::new(request, self.max_size, self.no_masking)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,10 +277,13 @@ pub struct ClientHandshake {
|
|||||||
key: String,
|
key: String,
|
||||||
error: Option<ClientError>,
|
error: Option<ClientError>,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
|
no_masking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientHandshake {
|
impl ClientHandshake {
|
||||||
fn new(mut request: ClientRequest, max_size: usize) -> ClientHandshake {
|
fn new(
|
||||||
|
mut request: ClientRequest, max_size: usize, no_masking: bool,
|
||||||
|
) -> ClientHandshake {
|
||||||
// Generate a random key for the `Sec-WebSocket-Key` header.
|
// Generate a random key for the `Sec-WebSocket-Key` header.
|
||||||
// a base64-encoded (see Section 4 of [RFC4648]) value that,
|
// a base64-encoded (see Section 4 of [RFC4648]) value that,
|
||||||
// when decoded, is 16 bytes in length (RFC 6455)
|
// when decoded, is 16 bytes in length (RFC 6455)
|
||||||
@@ -292,6 +303,7 @@ impl ClientHandshake {
|
|||||||
ClientHandshake {
|
ClientHandshake {
|
||||||
key,
|
key,
|
||||||
max_size,
|
max_size,
|
||||||
|
no_masking,
|
||||||
request: Some(request.send()),
|
request: Some(request.send()),
|
||||||
tx: Some(tx),
|
tx: Some(tx),
|
||||||
error: None,
|
error: None,
|
||||||
@@ -305,6 +317,7 @@ impl ClientHandshake {
|
|||||||
tx: None,
|
tx: None,
|
||||||
error: Some(err),
|
error: Some(err),
|
||||||
max_size: 0,
|
max_size: 0,
|
||||||
|
no_masking: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,6 +428,7 @@ impl Future for ClientHandshake {
|
|||||||
ClientReader {
|
ClientReader {
|
||||||
inner: Rc::clone(&inner),
|
inner: Rc::clone(&inner),
|
||||||
max_size: self.max_size,
|
max_size: self.max_size,
|
||||||
|
no_masking: self.no_masking,
|
||||||
},
|
},
|
||||||
ClientWriter { inner },
|
ClientWriter { inner },
|
||||||
)))
|
)))
|
||||||
@@ -424,6 +438,7 @@ impl Future for ClientHandshake {
|
|||||||
pub struct ClientReader {
|
pub struct ClientReader {
|
||||||
inner: Rc<UnsafeCell<Inner>>,
|
inner: Rc<UnsafeCell<Inner>>,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
|
no_masking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ClientReader {
|
impl fmt::Debug for ClientReader {
|
||||||
@@ -445,13 +460,14 @@ impl Stream for ClientReader {
|
|||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
let max_size = self.max_size;
|
let max_size = self.max_size;
|
||||||
|
let no_masking = self.no_masking;
|
||||||
let inner = self.as_mut();
|
let inner = self.as_mut();
|
||||||
if inner.closed {
|
if inner.closed {
|
||||||
return Ok(Async::Ready(None));
|
return Ok(Async::Ready(None));
|
||||||
}
|
}
|
||||||
|
|
||||||
// read
|
// read
|
||||||
match Frame::parse(&mut inner.rx, false, max_size) {
|
match Frame::parse(&mut inner.rx, no_masking, max_size) {
|
||||||
Ok(Async::Ready(Some(frame))) => {
|
Ok(Async::Ready(Some(frame))) => {
|
||||||
let (_finished, opcode, payload) = frame.unpack();
|
let (_finished, opcode, payload) = frame.unpack();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user