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:
parent
0e6a67fc26
commit
8b1fdeb8c9
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
13
src/task.rs
13
src/task.rs
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user