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