1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +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,
}
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)]
/// An HTTP Request
pub struct HttpRequest {
@ -61,15 +26,6 @@ pub struct HttpRequest {
params: Params,
}
impl Message for HttpRequest {
fn version(&self) -> Version {
self.version
}
fn headers(&self) -> &HeaderMap {
&self.headers
}
}
impl HttpRequest {
/// Construct a new Request.
#[inline]
@ -87,18 +43,20 @@ impl HttpRequest {
#[inline]
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.
#[inline]
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
// ///
// /// This is an `Option`, because some underlying transports may not have
@ -169,6 +127,20 @@ impl HttpRequest {
}
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.
@ -200,7 +172,7 @@ impl Body {
#[derive(Debug)]
/// An HTTP Response
pub struct HttpResponse {
pub version: Version,
pub version: Option<Version>,
pub headers: HeaderMap,
pub status: StatusCode,
reason: Option<&'static str>,
@ -209,15 +181,6 @@ pub struct HttpResponse {
connection_type: Option<ConnectionType>,
}
impl Message for HttpResponse {
fn version(&self) -> Version {
self.version
}
fn headers(&self) -> &HeaderMap {
&self.headers
}
}
impl HttpResponse {
#[inline]
@ -232,7 +195,7 @@ impl HttpResponse {
#[inline]
pub fn new(status: StatusCode, body: Body) -> HttpResponse {
HttpResponse {
version: Version::HTTP_11,
version: None,
headers: Default::default(),
status: status,
reason: None,
@ -245,7 +208,7 @@ impl HttpResponse {
/// Get the HTTP version of this response.
#[inline]
pub fn version(&self) -> Version {
pub fn version(&self) -> Option<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)]
struct Parts {
version: Version,
version: Option<Version>,
headers: HeaderMap,
status: StatusCode,
reason: Option<&'static str>,
@ -357,7 +329,7 @@ struct Parts {
impl Parts {
fn new(status: StatusCode) -> Self {
Parts {
version: Version::default(),
version: None,
headers: HeaderMap::new(),
status: status,
reason: None,
@ -383,7 +355,7 @@ impl Builder {
#[inline]
pub fn version(&mut self, version: Version) -> &mut Self {
if let Some(parts) = parts(&mut self.parts, &self.err) {
parts.version = version;
parts.version = Some(version);
}
self
}

View File

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

View File

@ -56,9 +56,9 @@ pub struct 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();
frames.push_back(Frame::Message(req, msg));
frames.push_back(Frame::Message(req, response.into()));
frames.push_back(Frame::Payload(None));
Task {
@ -92,6 +92,7 @@ impl Task {
let mut extra = 0;
let body = msg.replace_body(Body::Empty);
let version = msg.version().unwrap_or_else(|| req.version());
match body {
Body::Empty => {
@ -122,7 +123,7 @@ impl Task {
}
Body::Streaming => {
if msg.chunked() {
if msg.version < Version::HTTP_11 {
if version < Version::HTTP_11 {
error!("Chunked transfer encoding is forbidden for {:?}", msg.version);
}
msg.headers.remove(CONTENT_LENGTH);
@ -144,10 +145,10 @@ impl Task {
}
// 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"));
}
} else if msg.version >= Version::HTTP_11 {
} else if version >= Version::HTTP_11 {
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;
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");
} else {
let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status);