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

response version is optional

This commit is contained in:
Nikolay Kim 2017-10-10 17:14:30 -07:00
parent 0e6a67fc26
commit 8b1fdeb8c9
3 changed files with 47 additions and 74 deletions

View File

@ -16,41 +16,6 @@ pub enum ConnectionType {
Upgrade, Upgrade,
} }
pub trait Message {
fn version(&self) -> Version;
fn headers(&self) -> &HeaderMap;
/// Checks if a connection is expecting a `100 Continue` before sending its body.
#[inline]
fn expecting_continue(&self) -> bool {
if self.version() == Version::HTTP_11 {
if let Some(hdr) = self.headers().get(header::EXPECT) {
if let Ok(hdr) = hdr.to_str() {
return hdr.to_lowercase().contains("continue")
}
}
}
false
}
fn is_chunked(&self) -> Result<bool, io::Error> {
if let Some(encodings) = self.headers().get(header::TRANSFER_ENCODING) {
if let Ok(s) = encodings.to_str() {
return Ok(s.to_lowercase().contains("chunked"))
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"Request with transfer-encoding header, but not chunked"))
}
} else {
Ok(false)
}
}
}
#[derive(Debug)] #[derive(Debug)]
/// An HTTP Request /// An HTTP Request
pub struct HttpRequest { pub struct HttpRequest {
@ -61,15 +26,6 @@ pub struct HttpRequest {
params: Params, params: Params,
} }
impl Message for HttpRequest {
fn version(&self) -> Version {
self.version
}
fn headers(&self) -> &HeaderMap {
&self.headers
}
}
impl HttpRequest { impl HttpRequest {
/// Construct a new Request. /// Construct a new Request.
#[inline] #[inline]
@ -87,18 +43,20 @@ impl HttpRequest {
#[inline] #[inline]
pub fn uri(&self) -> &Uri { &self.uri } pub fn uri(&self) -> &Uri { &self.uri }
/// Read the Request Version.
#[inline]
pub fn version(&self) -> Version { self.version }
/// Read the Request headers.
#[inline]
pub fn headers(&self) -> &HeaderMap { &self.headers }
/// Read the Request method. /// Read the Request method.
#[inline] #[inline]
pub fn method(&self) -> &Method { &self.method } pub fn method(&self) -> &Method { &self.method }
/// Read the Request Version.
pub fn version(&self) -> Version {
self.version
}
/// Read the Request Headers.
pub fn headers(&self) -> &HeaderMap {
&self.headers
}
// /// The remote socket address of this request // /// The remote socket address of this request
// /// // ///
// /// This is an `Option`, because some underlying transports may not have // /// This is an `Option`, because some underlying transports may not have
@ -169,6 +127,20 @@ impl HttpRequest {
} }
false false
} }
pub fn is_chunked(&self) -> Result<bool, io::Error> {
if let Some(encodings) = self.headers().get(header::TRANSFER_ENCODING) {
if let Ok(s) = encodings.to_str() {
return Ok(s.to_lowercase().contains("chunked"))
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"Request with transfer-encoding header, but not chunked"))
}
} else {
Ok(false)
}
}
} }
/// Represents various types of http message body. /// Represents various types of http message body.
@ -200,7 +172,7 @@ impl Body {
#[derive(Debug)] #[derive(Debug)]
/// An HTTP Response /// An HTTP Response
pub struct HttpResponse { pub struct HttpResponse {
pub version: Version, pub version: Option<Version>,
pub headers: HeaderMap, pub headers: HeaderMap,
pub status: StatusCode, pub status: StatusCode,
reason: Option<&'static str>, reason: Option<&'static str>,
@ -209,15 +181,6 @@ pub struct HttpResponse {
connection_type: Option<ConnectionType>, connection_type: Option<ConnectionType>,
} }
impl Message for HttpResponse {
fn version(&self) -> Version {
self.version
}
fn headers(&self) -> &HeaderMap {
&self.headers
}
}
impl HttpResponse { impl HttpResponse {
#[inline] #[inline]
@ -232,7 +195,7 @@ impl HttpResponse {
#[inline] #[inline]
pub fn new(status: StatusCode, body: Body) -> HttpResponse { pub fn new(status: StatusCode, body: Body) -> HttpResponse {
HttpResponse { HttpResponse {
version: Version::HTTP_11, version: None,
headers: Default::default(), headers: Default::default(),
status: status, status: status,
reason: None, reason: None,
@ -245,7 +208,7 @@ impl HttpResponse {
/// Get the HTTP version of this response. /// Get the HTTP version of this response.
#[inline] #[inline]
pub fn version(&self) -> Version { pub fn version(&self) -> Option<Version> {
self.version self.version
} }
@ -344,9 +307,18 @@ impl From<Error> for HttpResponse {
} }
} }
impl<I: Into<HttpResponse>, E: Into<HttpResponse>> From<Result<I, E>> for HttpResponse {
fn from(res: Result<I, E>) -> Self {
match res {
Ok(val) => val.into(),
Err(err) => err.into(),
}
}
}
#[derive(Debug)] #[derive(Debug)]
struct Parts { struct Parts {
version: Version, version: Option<Version>,
headers: HeaderMap, headers: HeaderMap,
status: StatusCode, status: StatusCode,
reason: Option<&'static str>, reason: Option<&'static str>,
@ -357,7 +329,7 @@ struct Parts {
impl Parts { impl Parts {
fn new(status: StatusCode) -> Self { fn new(status: StatusCode) -> Self {
Parts { Parts {
version: Version::default(), version: None,
headers: HeaderMap::new(), headers: HeaderMap::new(),
status: status, status: status,
reason: None, reason: None,
@ -383,7 +355,7 @@ impl Builder {
#[inline] #[inline]
pub fn version(&mut self, version: Version) -> &mut Self { pub fn version(&mut self, version: Version) -> &mut Self {
if let Some(parts) = parts(&mut self.parts, &self.err) { if let Some(parts) = parts(&mut self.parts, &self.err) {
parts.version = version; parts.version = Some(version);
} }
self self
} }

View File

@ -9,8 +9,8 @@ use tokio_io::AsyncRead;
use error::{Error, Result}; use error::{Error, Result};
use decode::Decoder; use decode::Decoder;
use httpmessage::HttpRequest;
use payload::{Payload, PayloadSender}; use payload::{Payload, PayloadSender};
use httpmessage::{Message, HttpRequest};
const MAX_HEADERS: usize = 100; const MAX_HEADERS: usize = 100;
const INIT_BUFFER_SIZE: usize = 8192; const INIT_BUFFER_SIZE: usize = 8192;

View File

@ -56,9 +56,9 @@ pub struct Task {
impl Task { impl Task {
pub fn reply(req: HttpRequest, msg: HttpResponse) -> Self { pub fn reply<R: Into<HttpResponse>>(req: HttpRequest, response: R) -> Self {
let mut frames = VecDeque::new(); let mut frames = VecDeque::new();
frames.push_back(Frame::Message(req, msg)); frames.push_back(Frame::Message(req, response.into()));
frames.push_back(Frame::Payload(None)); frames.push_back(Frame::Payload(None));
Task { Task {
@ -92,6 +92,7 @@ impl Task {
let mut extra = 0; let mut extra = 0;
let body = msg.replace_body(Body::Empty); let body = msg.replace_body(Body::Empty);
let version = msg.version().unwrap_or_else(|| req.version());
match body { match body {
Body::Empty => { Body::Empty => {
@ -122,7 +123,7 @@ impl Task {
} }
Body::Streaming => { Body::Streaming => {
if msg.chunked() { if msg.chunked() {
if msg.version < Version::HTTP_11 { if version < Version::HTTP_11 {
error!("Chunked transfer encoding is forbidden for {:?}", msg.version); error!("Chunked transfer encoding is forbidden for {:?}", msg.version);
} }
msg.headers.remove(CONTENT_LENGTH); msg.headers.remove(CONTENT_LENGTH);
@ -144,10 +145,10 @@ impl Task {
} }
// keep-alive // keep-alive
else if msg.keep_alive().unwrap_or_else(|| req.keep_alive()) { else if msg.keep_alive().unwrap_or_else(|| req.keep_alive()) {
if msg.version < Version::HTTP_11 { if version < Version::HTTP_11 {
msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive")); msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive"));
} }
} else if msg.version >= Version::HTTP_11 { } else if version >= Version::HTTP_11 {
msg.headers.insert(CONNECTION, HeaderValue::from_static("close")); msg.headers.insert(CONNECTION, HeaderValue::from_static("close"));
} }
@ -155,7 +156,7 @@ impl Task {
let init_cap = 100 + msg.headers.len() * AVERAGE_HEADER_SIZE + extra; let init_cap = 100 + msg.headers.len() * AVERAGE_HEADER_SIZE + extra;
self.buffer.reserve(init_cap); self.buffer.reserve(init_cap);
if msg.version == Version::HTTP_11 && msg.status == StatusCode::OK { if version == Version::HTTP_11 && msg.status == StatusCode::OK {
self.buffer.extend(b"HTTP/1.1 200 OK\r\n"); self.buffer.extend(b"HTTP/1.1 200 OK\r\n");
} else { } else {
let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status); let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status);