mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
cleanup and optimize some code
This commit is contained in:
parent
ab6efd2421
commit
2e83c5924d
@ -13,9 +13,11 @@ use futures::future::{FutureResult, result};
|
|||||||
/// simple handler
|
/// simple handler
|
||||||
fn index(mut req: HttpRequest) -> Result<HttpResponse> {
|
fn index(mut req: HttpRequest) -> Result<HttpResponse> {
|
||||||
println!("{:?}", req);
|
println!("{:?}", req);
|
||||||
if let Ok(ch) = req.payload_mut().readany() {
|
if let Some(payload) = req.payload_mut() {
|
||||||
if let futures::Async::Ready(Some(d)) = ch {
|
if let Ok(ch) = payload.readany() {
|
||||||
println!("{}", String::from_utf8_lossy(d.0.as_ref()));
|
if let futures::Async::Ready(Some(d)) = ch {
|
||||||
|
println!("{}", String::from_utf8_lossy(d.0.as_ref()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,14 +402,14 @@ impl PayloadEncoder {
|
|||||||
|
|
||||||
resp.headers_mut().insert(
|
resp.headers_mut().insert(
|
||||||
CONTENT_LENGTH,
|
CONTENT_LENGTH,
|
||||||
HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap());
|
HeaderValue::from_str(&b.len().to_string()).unwrap());
|
||||||
*bytes = Binary::from(b);
|
*bytes = Binary::from(b);
|
||||||
encoding = ContentEncoding::Identity;
|
encoding = ContentEncoding::Identity;
|
||||||
TransferEncoding::eof()
|
TransferEncoding::eof()
|
||||||
} else {
|
} else {
|
||||||
resp.headers_mut().insert(
|
resp.headers_mut().insert(
|
||||||
CONTENT_LENGTH,
|
CONTENT_LENGTH,
|
||||||
HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap());
|
HeaderValue::from_str(&bytes.len().to_string()).unwrap());
|
||||||
resp.headers_mut().remove(TRANSFER_ENCODING);
|
resp.headers_mut().remove(TRANSFER_ENCODING);
|
||||||
TransferEncoding::length(bytes.len() as u64)
|
TransferEncoding::length(bytes.len() as u64)
|
||||||
}
|
}
|
||||||
@ -478,22 +478,27 @@ impl PayloadEncoder {
|
|||||||
|
|
||||||
impl PayloadEncoder {
|
impl PayloadEncoder {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.get_ref().len()
|
self.0.get_ref().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get_mut(&mut self) -> &mut BytesMut {
|
pub fn get_mut(&mut self) -> &mut BytesMut {
|
||||||
self.0.get_mut()
|
self.0.get_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn is_eof(&self) -> bool {
|
pub fn is_eof(&self) -> bool {
|
||||||
self.0.is_eof()
|
self.0.is_eof()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn write(&mut self, payload: &[u8]) -> Result<(), io::Error> {
|
pub fn write(&mut self, payload: &[u8]) -> Result<(), io::Error> {
|
||||||
self.0.write(payload)
|
self.0.write(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn write_eof(&mut self) -> Result<(), io::Error> {
|
pub fn write_eof(&mut self) -> Result<(), io::Error> {
|
||||||
self.0.write_eof()
|
self.0.write_eof()
|
||||||
}
|
}
|
||||||
@ -508,6 +513,7 @@ enum ContentEncoder {
|
|||||||
|
|
||||||
impl ContentEncoder {
|
impl ContentEncoder {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn is_eof(&self) -> bool {
|
pub fn is_eof(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ContentEncoder::Br(ref encoder) =>
|
ContentEncoder::Br(ref encoder) =>
|
||||||
@ -521,6 +527,7 @@ impl ContentEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get_ref(&self) -> &BytesMut {
|
pub fn get_ref(&self) -> &BytesMut {
|
||||||
match *self {
|
match *self {
|
||||||
ContentEncoder::Br(ref encoder) =>
|
ContentEncoder::Br(ref encoder) =>
|
||||||
@ -534,6 +541,7 @@ impl ContentEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get_mut(&mut self) -> &mut BytesMut {
|
pub fn get_mut(&mut self) -> &mut BytesMut {
|
||||||
match *self {
|
match *self {
|
||||||
ContentEncoder::Br(ref mut encoder) =>
|
ContentEncoder::Br(ref mut encoder) =>
|
||||||
@ -547,6 +555,7 @@ impl ContentEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn write_eof(&mut self) -> Result<(), io::Error> {
|
pub fn write_eof(&mut self) -> Result<(), io::Error> {
|
||||||
let encoder = mem::replace(self, ContentEncoder::Identity(TransferEncoding::eof()));
|
let encoder = mem::replace(self, ContentEncoder::Identity(TransferEncoding::eof()));
|
||||||
|
|
||||||
@ -555,7 +564,6 @@ impl ContentEncoder {
|
|||||||
match encoder.finish() {
|
match encoder.finish() {
|
||||||
Ok(mut writer) => {
|
Ok(mut writer) => {
|
||||||
writer.encode_eof();
|
writer.encode_eof();
|
||||||
*self = ContentEncoder::Identity(writer);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
@ -565,7 +573,6 @@ impl ContentEncoder {
|
|||||||
match encoder.finish() {
|
match encoder.finish() {
|
||||||
Ok(mut writer) => {
|
Ok(mut writer) => {
|
||||||
writer.encode_eof();
|
writer.encode_eof();
|
||||||
*self = ContentEncoder::Identity(writer);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
@ -575,7 +582,6 @@ impl ContentEncoder {
|
|||||||
match encoder.finish() {
|
match encoder.finish() {
|
||||||
Ok(mut writer) => {
|
Ok(mut writer) => {
|
||||||
writer.encode_eof();
|
writer.encode_eof();
|
||||||
*self = ContentEncoder::Identity(writer);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
@ -583,19 +589,18 @@ impl ContentEncoder {
|
|||||||
},
|
},
|
||||||
ContentEncoder::Identity(mut writer) => {
|
ContentEncoder::Identity(mut writer) => {
|
||||||
writer.encode_eof();
|
writer.encode_eof();
|
||||||
*self = ContentEncoder::Identity(writer);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn write(&mut self, data: &[u8]) -> Result<(), io::Error> {
|
pub fn write(&mut self, data: &[u8]) -> Result<(), io::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
ContentEncoder::Br(ref mut encoder) => {
|
ContentEncoder::Br(ref mut encoder) => {
|
||||||
match encoder.write(data) {
|
match encoder.write(data) {
|
||||||
Ok(_) => {
|
Ok(_) =>
|
||||||
encoder.flush()
|
encoder.flush(),
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding br encoding: {}", err);
|
trace!("Error decoding br encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
@ -604,20 +609,18 @@ impl ContentEncoder {
|
|||||||
},
|
},
|
||||||
ContentEncoder::Gzip(ref mut encoder) => {
|
ContentEncoder::Gzip(ref mut encoder) => {
|
||||||
match encoder.write(data) {
|
match encoder.write(data) {
|
||||||
Ok(_) => {
|
Ok(_) =>
|
||||||
encoder.flush()
|
encoder.flush(),
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding br encoding: {}", err);
|
trace!("Error decoding gzip encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ContentEncoder::Deflate(ref mut encoder) => {
|
ContentEncoder::Deflate(ref mut encoder) => {
|
||||||
match encoder.write(data) {
|
match encoder.write(data) {
|
||||||
Ok(_) => {
|
Ok(_) =>
|
||||||
encoder.flush()
|
encoder.flush(),
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding deflate encoding: {}", err);
|
trace!("Error decoding deflate encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
@ -655,6 +658,7 @@ enum TransferEncodingKind {
|
|||||||
|
|
||||||
impl TransferEncoding {
|
impl TransferEncoding {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn eof() -> TransferEncoding {
|
pub fn eof() -> TransferEncoding {
|
||||||
TransferEncoding {
|
TransferEncoding {
|
||||||
kind: TransferEncodingKind::Eof,
|
kind: TransferEncodingKind::Eof,
|
||||||
@ -662,6 +666,7 @@ impl TransferEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn chunked() -> TransferEncoding {
|
pub fn chunked() -> TransferEncoding {
|
||||||
TransferEncoding {
|
TransferEncoding {
|
||||||
kind: TransferEncodingKind::Chunked(false),
|
kind: TransferEncodingKind::Chunked(false),
|
||||||
@ -669,6 +674,7 @@ impl TransferEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn length(len: u64) -> TransferEncoding {
|
pub fn length(len: u64) -> TransferEncoding {
|
||||||
TransferEncoding {
|
TransferEncoding {
|
||||||
kind: TransferEncodingKind::Length(len),
|
kind: TransferEncodingKind::Length(len),
|
||||||
@ -676,6 +682,7 @@ impl TransferEncoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn is_eof(&self) -> bool {
|
pub fn is_eof(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TransferEncodingKind::Eof => true,
|
TransferEncodingKind::Eof => true,
|
||||||
@ -687,6 +694,7 @@ impl TransferEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Encode message. Return `EOF` state of encoder
|
/// Encode message. Return `EOF` state of encoder
|
||||||
|
#[inline]
|
||||||
pub fn encode(&mut self, msg: &[u8]) -> bool {
|
pub fn encode(&mut self, msg: &[u8]) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TransferEncodingKind::Eof => {
|
TransferEncodingKind::Eof => {
|
||||||
@ -724,6 +732,7 @@ impl TransferEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Encode eof. Return `EOF` state of encoder
|
/// Encode eof. Return `EOF` state of encoder
|
||||||
|
#[inline]
|
||||||
pub fn encode_eof(&mut self) {
|
pub fn encode_eof(&mut self) {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TransferEncodingKind::Eof | TransferEncodingKind::Length(_) => (),
|
TransferEncodingKind::Eof | TransferEncodingKind::Length(_) => (),
|
||||||
@ -739,11 +748,13 @@ impl TransferEncoding {
|
|||||||
|
|
||||||
impl io::Write for TransferEncoding {
|
impl io::Write for TransferEncoding {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
self.encode(buf);
|
self.encode(buf);
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
13
src/error.rs
13
src/error.rs
@ -262,6 +262,9 @@ pub enum MultipartError {
|
|||||||
/// Multipart boundary is not found
|
/// Multipart boundary is not found
|
||||||
#[fail(display="Multipart boundary is not found")]
|
#[fail(display="Multipart boundary is not found")]
|
||||||
Boundary,
|
Boundary,
|
||||||
|
/// Request does not contain payload
|
||||||
|
#[fail(display="Request does not contain payload")]
|
||||||
|
NoPayload,
|
||||||
/// Error during field parsing
|
/// Error during field parsing
|
||||||
#[fail(display="{}", _0)]
|
#[fail(display="{}", _0)]
|
||||||
Parse(#[cause] ParseError),
|
Parse(#[cause] ParseError),
|
||||||
@ -329,6 +332,9 @@ pub enum WsHandshakeError {
|
|||||||
/// Websocket key is not set or wrong
|
/// Websocket key is not set or wrong
|
||||||
#[fail(display="Unknown websocket key")]
|
#[fail(display="Unknown websocket key")]
|
||||||
BadWebsocketKey,
|
BadWebsocketKey,
|
||||||
|
/// Request does not contain payload
|
||||||
|
#[fail(display="Request does not contain payload")]
|
||||||
|
NoPayload,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseError for WsHandshakeError {
|
impl ResponseError for WsHandshakeError {
|
||||||
@ -351,7 +357,9 @@ impl ResponseError for WsHandshakeError {
|
|||||||
WsHandshakeError::UnsupportedVersion =>
|
WsHandshakeError::UnsupportedVersion =>
|
||||||
HTTPBadRequest.with_reason("Unsupported version"),
|
HTTPBadRequest.with_reason("Unsupported version"),
|
||||||
WsHandshakeError::BadWebsocketKey =>
|
WsHandshakeError::BadWebsocketKey =>
|
||||||
HTTPBadRequest.with_reason("Handshake error")
|
HTTPBadRequest.with_reason("Handshake error"),
|
||||||
|
WsHandshakeError::NoPayload =>
|
||||||
|
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,6 +379,9 @@ pub enum UrlencodedError {
|
|||||||
/// Content type error
|
/// Content type error
|
||||||
#[fail(display="Content type error")]
|
#[fail(display="Content type error")]
|
||||||
ContentType,
|
ContentType,
|
||||||
|
/// Request does not contain payload
|
||||||
|
#[fail(display="Request does not contain payload")]
|
||||||
|
NoPayload,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `BadRequest` for `UrlencodedError`
|
/// Return `BadRequest` for `UrlencodedError`
|
||||||
|
47
src/h1.rs
47
src/h1.rs
@ -545,28 +545,25 @@ impl Reader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut psender, payload) = Payload::new(false);
|
let decoder = if upgrade(&method, &headers) {
|
||||||
let msg = HttpRequest::new(method, uri, version, headers, payload);
|
|
||||||
|
|
||||||
let decoder = if msg.upgrade() {
|
|
||||||
Decoder::eof()
|
Decoder::eof()
|
||||||
} else {
|
} else {
|
||||||
let has_len = msg.headers().contains_key(header::CONTENT_LENGTH);
|
let has_len = headers.contains_key(header::CONTENT_LENGTH);
|
||||||
|
|
||||||
// Chunked encoding
|
// Chunked encoding
|
||||||
if msg.chunked()? {
|
if chunked(&headers)? {
|
||||||
if has_len {
|
if has_len {
|
||||||
return Err(ParseError::Header)
|
return Err(ParseError::Header)
|
||||||
}
|
}
|
||||||
Decoder::chunked()
|
Decoder::chunked()
|
||||||
} else {
|
} else {
|
||||||
if !has_len {
|
if !has_len {
|
||||||
psender.feed_eof();
|
let msg = HttpRequest::new(method, uri, version, headers, None);
|
||||||
return Ok(Message::Http1(msg, None))
|
return Ok(Message::Http1(msg, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content-Length
|
// Content-Length
|
||||||
let len = msg.headers().get(header::CONTENT_LENGTH).unwrap();
|
let len = headers.get(header::CONTENT_LENGTH).unwrap();
|
||||||
if let Ok(s) = len.to_str() {
|
if let Ok(s) = len.to_str() {
|
||||||
if let Ok(len) = s.parse::<u64>() {
|
if let Ok(len) = s.parse::<u64>() {
|
||||||
Decoder::length(len)
|
Decoder::length(len)
|
||||||
@ -581,11 +578,13 @@ impl Reader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let payload = PayloadInfo {
|
let (psender, payload) = Payload::new(false);
|
||||||
tx: PayloadType::new(msg.headers(), psender),
|
let info = PayloadInfo {
|
||||||
|
tx: PayloadType::new(&headers, psender),
|
||||||
decoder: decoder,
|
decoder: decoder,
|
||||||
};
|
};
|
||||||
Ok(Message::Http1(msg, Some(payload)))
|
let msg = HttpRequest::new(method, uri, version, headers, Some(payload));
|
||||||
|
Ok(Message::Http1(msg, Some(info)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,6 +609,32 @@ fn record_header_indices(bytes: &[u8],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if request is UPGRADE
|
||||||
|
fn upgrade(method: &Method, headers: &HeaderMap) -> bool {
|
||||||
|
if let Some(conn) = headers.get(header::CONNECTION) {
|
||||||
|
if let Ok(s) = conn.to_str() {
|
||||||
|
s.to_lowercase().contains("upgrade")
|
||||||
|
} else {
|
||||||
|
*method == Method::CONNECT
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*method == Method::CONNECT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if request has chunked transfer encoding
|
||||||
|
fn chunked(headers: &HeaderMap) -> Result<bool, ParseError> {
|
||||||
|
if let Some(encodings) = headers.get(header::TRANSFER_ENCODING) {
|
||||||
|
if let Ok(s) = encodings.to_str() {
|
||||||
|
Ok(s.to_lowercase().contains("chunked"))
|
||||||
|
} else {
|
||||||
|
Err(ParseError::Header)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Decoders to handle different Transfer-Encodings.
|
/// Decoders to handle different Transfer-Encodings.
|
||||||
///
|
///
|
||||||
/// If a message body does not include a Transfer-Encoding, it *should*
|
/// If a message body does not include a Transfer-Encoding, it *should*
|
||||||
|
@ -237,7 +237,7 @@ impl Entry {
|
|||||||
let (psender, payload) = Payload::new(false);
|
let (psender, payload) = Payload::new(false);
|
||||||
|
|
||||||
let mut req = HttpRequest::new(
|
let mut req = HttpRequest::new(
|
||||||
parts.method, parts.uri, parts.version, parts.headers, payload);
|
parts.method, parts.uri, parts.version, parts.headers, Some(payload));
|
||||||
|
|
||||||
// set remote addr
|
// set remote addr
|
||||||
req.set_peer_addr(addr);
|
req.set_peer_addr(addr);
|
||||||
|
@ -58,6 +58,7 @@ pub(crate) enum ReplyItem {
|
|||||||
impl Reply {
|
impl Reply {
|
||||||
|
|
||||||
/// Create actor response
|
/// Create actor response
|
||||||
|
#[inline]
|
||||||
pub fn actor<A, S>(ctx: HttpContext<A, S>) -> Reply
|
pub fn actor<A, S>(ctx: HttpContext<A, S>) -> Reply
|
||||||
where A: Actor<Context=HttpContext<A, S>>, S: 'static
|
where A: Actor<Context=HttpContext<A, S>>, S: 'static
|
||||||
{
|
{
|
||||||
@ -65,6 +66,7 @@ impl Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create async response
|
/// Create async response
|
||||||
|
#[inline]
|
||||||
pub fn async<F>(fut: F) -> Reply
|
pub fn async<F>(fut: F) -> Reply
|
||||||
where F: Future<Item=HttpResponse, Error=Error> + 'static
|
where F: Future<Item=HttpResponse, Error=Error> + 'static
|
||||||
{
|
{
|
||||||
@ -72,10 +74,12 @@ impl Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send response
|
/// Send response
|
||||||
|
#[inline]
|
||||||
pub fn response<R: Into<HttpResponse>>(response: R) -> Reply {
|
pub fn response<R: Into<HttpResponse>>(response: R) -> Reply {
|
||||||
Reply(ReplyItem::Message(response.into()))
|
Reply(ReplyItem::Message(response.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) fn into(self) -> ReplyItem {
|
pub(crate) fn into(self) -> ReplyItem {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub struct HttpMessage {
|
|||||||
pub params: Params<'static>,
|
pub params: Params<'static>,
|
||||||
pub cookies: Option<Vec<Cookie<'static>>>,
|
pub cookies: Option<Vec<Cookie<'static>>>,
|
||||||
pub addr: Option<SocketAddr>,
|
pub addr: Option<SocketAddr>,
|
||||||
pub payload: Payload,
|
pub payload: Option<Payload>,
|
||||||
pub info: Option<ConnectionInfo<'static>>,
|
pub info: Option<ConnectionInfo<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ impl Default for HttpMessage {
|
|||||||
params: Params::default(),
|
params: Params::default(),
|
||||||
cookies: None,
|
cookies: None,
|
||||||
addr: None,
|
addr: None,
|
||||||
payload: Payload::empty(),
|
payload: None,
|
||||||
extensions: Extensions::new(),
|
extensions: Extensions::new(),
|
||||||
info: None,
|
info: None,
|
||||||
}
|
}
|
||||||
@ -72,13 +72,13 @@ impl HttpMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP Request
|
/// An HTTP Request
|
||||||
pub struct HttpRequest<S=()>(Rc<HttpMessage>, Rc<S>, Option<Router<S>>);
|
pub struct HttpRequest<S=()>(Rc<HttpMessage>, Option<Rc<S>>, Option<Router<S>>);
|
||||||
|
|
||||||
impl HttpRequest<()> {
|
impl HttpRequest<()> {
|
||||||
/// Construct a new Request.
|
/// Construct a new Request.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(method: Method, uri: Uri,
|
pub fn new(method: Method, uri: Uri,
|
||||||
version: Version, headers: HeaderMap, payload: Payload) -> HttpRequest
|
version: Version, headers: HeaderMap, payload: Option<Payload>) -> HttpRequest
|
||||||
{
|
{
|
||||||
HttpRequest(
|
HttpRequest(
|
||||||
Rc::new(HttpMessage {
|
Rc::new(HttpMessage {
|
||||||
@ -93,7 +93,7 @@ impl HttpRequest<()> {
|
|||||||
extensions: Extensions::new(),
|
extensions: Extensions::new(),
|
||||||
info: None,
|
info: None,
|
||||||
}),
|
}),
|
||||||
Rc::new(()),
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -118,14 +118,14 @@ impl HttpRequest<()> {
|
|||||||
extensions: Extensions::new(),
|
extensions: Extensions::new(),
|
||||||
info: None,
|
info: None,
|
||||||
}),
|
}),
|
||||||
Rc::new(()),
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct new http request with state.
|
/// Construct new http request with state.
|
||||||
pub fn with_state<S>(self, state: Rc<S>, router: Router<S>) -> HttpRequest<S> {
|
pub fn with_state<S>(self, state: Rc<S>, router: Router<S>) -> HttpRequest<S> {
|
||||||
HttpRequest(self.0, state, Some(router))
|
HttpRequest(self.0, Some(state), Some(router))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ impl<S> HttpRequest<S> {
|
|||||||
|
|
||||||
/// Construct new http request without state.
|
/// Construct new http request without state.
|
||||||
pub fn clone_without_state(&self) -> HttpRequest {
|
pub fn clone_without_state(&self) -> HttpRequest {
|
||||||
HttpRequest(Rc::clone(&self.0), Rc::new(()), None)
|
HttpRequest(Rc::clone(&self.0), None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get mutable reference for inner message
|
// get mutable reference for inner message
|
||||||
@ -153,7 +153,7 @@ impl<S> HttpRequest<S> {
|
|||||||
/// Shared application state
|
/// Shared application state
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn state(&self) -> &S {
|
pub fn state(&self) -> &S {
|
||||||
&self.1
|
self.1.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Protocol extensions.
|
/// Protocol extensions.
|
||||||
@ -377,20 +377,20 @@ impl<S> HttpRequest<S> {
|
|||||||
|
|
||||||
/// Returns reference to the associated http payload.
|
/// Returns reference to the associated http payload.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn payload(&self) -> &Payload {
|
pub fn payload(&self) -> Option<&Payload> {
|
||||||
&self.0.payload
|
self.0.payload.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns mutable reference to the associated http payload.
|
/// Returns mutable reference to the associated http payload.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn payload_mut(&mut self) -> &mut Payload {
|
pub fn payload_mut(&mut self) -> Option<&mut Payload> {
|
||||||
&mut self.as_mut().payload
|
self.as_mut().payload.as_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return payload
|
/// Return payload
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn take_payload(&mut self) -> Payload {
|
pub fn take_payload(&mut self) -> Option<Payload> {
|
||||||
mem::replace(&mut self.as_mut().payload, Payload::empty())
|
self.as_mut().payload.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return stream to process BODY as multipart.
|
/// Return stream to process BODY as multipart.
|
||||||
@ -398,7 +398,11 @@ impl<S> HttpRequest<S> {
|
|||||||
/// Content-type: multipart/form-data;
|
/// Content-type: multipart/form-data;
|
||||||
pub fn multipart(&mut self) -> Result<Multipart, MultipartError> {
|
pub fn multipart(&mut self) -> Result<Multipart, MultipartError> {
|
||||||
let boundary = Multipart::boundary(&self.0.headers)?;
|
let boundary = Multipart::boundary(&self.0.headers)?;
|
||||||
Ok(Multipart::new(boundary, self.take_payload()))
|
if let Some(payload) = self.take_payload() {
|
||||||
|
Ok(Multipart::new(boundary, payload))
|
||||||
|
} else {
|
||||||
|
Err(MultipartError::NoPayload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse `application/x-www-form-urlencoded` encoded body.
|
/// Parse `application/x-www-form-urlencoded` encoded body.
|
||||||
@ -441,7 +445,11 @@ impl<S> HttpRequest<S> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if t {
|
if t {
|
||||||
Ok(UrlEncoded{pl: self.take_payload(), body: BytesMut::new()})
|
if let Some(payload) = self.take_payload() {
|
||||||
|
Ok(UrlEncoded{pl: payload, body: BytesMut::new()})
|
||||||
|
} else {
|
||||||
|
Err(UrlencodedError::NoPayload)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(UrlencodedError::ContentType)
|
Err(UrlencodedError::ContentType)
|
||||||
}
|
}
|
||||||
@ -452,13 +460,13 @@ impl Default for HttpRequest<()> {
|
|||||||
|
|
||||||
/// Construct default request
|
/// Construct default request
|
||||||
fn default() -> HttpRequest {
|
fn default() -> HttpRequest {
|
||||||
HttpRequest(Rc::new(HttpMessage::default()), Rc::new(()), None)
|
HttpRequest(Rc::new(HttpMessage::default()), None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Clone for HttpRequest<S> {
|
impl<S> Clone for HttpRequest<S> {
|
||||||
fn clone(&self) -> HttpRequest<S> {
|
fn clone(&self) -> HttpRequest<S> {
|
||||||
HttpRequest(Rc::clone(&self.0), Rc::clone(&self.1), None)
|
HttpRequest(Rc::clone(&self.0), self.1.clone(), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,20 +222,20 @@ struct Parts {
|
|||||||
chunked: bool,
|
chunked: bool,
|
||||||
encoding: ContentEncoding,
|
encoding: ContentEncoding,
|
||||||
connection_type: Option<ConnectionType>,
|
connection_type: Option<ConnectionType>,
|
||||||
cookies: CookieJar,
|
cookies: Option<CookieJar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parts {
|
impl Parts {
|
||||||
fn new(status: StatusCode) -> Self {
|
fn new(status: StatusCode) -> Self {
|
||||||
Parts {
|
Parts {
|
||||||
version: None,
|
version: None,
|
||||||
headers: HeaderMap::new(),
|
headers: HeaderMap::with_capacity(8),
|
||||||
status: status,
|
status: status,
|
||||||
reason: None,
|
reason: None,
|
||||||
chunked: false,
|
chunked: false,
|
||||||
encoding: ContentEncoding::Auto,
|
encoding: ContentEncoding::Auto,
|
||||||
connection_type: None,
|
connection_type: None,
|
||||||
cookies: CookieJar::new(),
|
cookies: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +359,13 @@ impl HttpResponseBuilder {
|
|||||||
/// Set a cookie
|
/// Set a cookie
|
||||||
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
||||||
parts.cookies.add(cookie.into_owned());
|
if parts.cookies.is_none() {
|
||||||
|
let mut jar = CookieJar::new();
|
||||||
|
jar.add(cookie.into_owned());
|
||||||
|
parts.cookies = Some(jar)
|
||||||
|
} else {
|
||||||
|
parts.cookies.as_mut().unwrap().add(cookie.into_owned());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -367,9 +373,13 @@ impl HttpResponseBuilder {
|
|||||||
/// Remote cookie, cookie has to be cookie from `HttpRequest::cookies()` method.
|
/// Remote cookie, cookie has to be cookie from `HttpRequest::cookies()` method.
|
||||||
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
||||||
|
if parts.cookies.is_none() {
|
||||||
|
parts.cookies = Some(CookieJar::new())
|
||||||
|
}
|
||||||
|
let mut jar = parts.cookies.as_mut().unwrap();
|
||||||
let cookie = cookie.clone().into_owned();
|
let cookie = cookie.clone().into_owned();
|
||||||
parts.cookies.add_original(cookie.clone());
|
jar.add_original(cookie.clone());
|
||||||
parts.cookies.remove(cookie);
|
jar.remove(cookie);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -391,10 +401,12 @@ impl HttpResponseBuilder {
|
|||||||
if let Some(e) = self.err.take() {
|
if let Some(e) = self.err.take() {
|
||||||
return Err(e)
|
return Err(e)
|
||||||
}
|
}
|
||||||
for cookie in parts.cookies.delta() {
|
if let Some(jar) = parts.cookies {
|
||||||
parts.headers.append(
|
for cookie in jar.delta() {
|
||||||
header::SET_COOKIE,
|
parts.headers.append(
|
||||||
HeaderValue::from_str(&cookie.to_string())?);
|
header::SET_COOKIE,
|
||||||
|
HeaderValue::from_str(&cookie.to_string())?);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(HttpResponse {
|
Ok(HttpResponse {
|
||||||
version: parts.version,
|
version: parts.version,
|
||||||
|
21
src/ws.rs
21
src/ws.rs
@ -96,11 +96,15 @@ pub fn start<A, S>(mut req: HttpRequest<S>, actor: A) -> Result<Reply, Error>
|
|||||||
{
|
{
|
||||||
let resp = handshake(&req)?;
|
let resp = handshake(&req)?;
|
||||||
|
|
||||||
let stream = WsStream::new(&mut req);
|
if let Some(payload) = req.take_payload() {
|
||||||
let mut ctx = HttpContext::new(req, actor);
|
let stream = WsStream::new(payload);
|
||||||
ctx.start(resp);
|
let mut ctx = HttpContext::new(req, actor);
|
||||||
ctx.add_stream(stream);
|
ctx.start(resp);
|
||||||
Ok(ctx.into())
|
ctx.add_stream(stream);
|
||||||
|
Ok(ctx.into())
|
||||||
|
} else {
|
||||||
|
Err(WsHandshakeError::NoPayload.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare `WebSocket` handshake response.
|
/// Prepare `WebSocket` handshake response.
|
||||||
@ -178,8 +182,11 @@ pub struct WsStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WsStream {
|
impl WsStream {
|
||||||
pub fn new<S>(req: &mut HttpRequest<S>) -> WsStream {
|
pub fn new(payload: Payload) -> WsStream {
|
||||||
WsStream { rx: req.take_payload(), buf: BytesMut::new(), closed: false, error_sent: false }
|
WsStream { rx: payload,
|
||||||
|
buf: BytesMut::new(),
|
||||||
|
closed: false,
|
||||||
|
error_sent: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user