1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

simplify api

This commit is contained in:
Nikolay Kim 2017-12-07 17:38:18 -08:00
parent dff7618f35
commit 0abb3863dc
6 changed files with 49 additions and 57 deletions

View File

@ -346,7 +346,7 @@ impl PayloadEncoder {
}; };
// Enable content encoding only if response does not contain Content-Encoding header // Enable content encoding only if response does not contain Content-Encoding header
let mut encoding = if has_body && !resp.headers.contains_key(CONTENT_ENCODING) { let mut encoding = if has_body && !resp.headers().contains_key(CONTENT_ENCODING) {
let encoding = match *resp.content_encoding() { let encoding = match *resp.content_encoding() {
ContentEncoding::Auto => { ContentEncoding::Auto => {
// negotiate content-encoding // negotiate content-encoding
@ -362,7 +362,8 @@ impl PayloadEncoder {
} }
encoding => encoding, encoding => encoding,
}; };
resp.headers.insert(CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str())); resp.headers_mut().insert(
CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
encoding encoding
} else { } else {
ContentEncoding::Identity ContentEncoding::Identity
@ -377,8 +378,8 @@ impl PayloadEncoder {
if resp.chunked() { if resp.chunked() {
error!("Chunked transfer is enabled but body is set to Empty"); error!("Chunked transfer is enabled but body is set to Empty");
} }
resp.headers.insert(CONTENT_LENGTH, HeaderValue::from_static("0")); resp.headers_mut().insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
resp.headers.remove(TRANSFER_ENCODING); resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::length(0) TransferEncoding::length(0)
}, },
Body::Binary(ref mut bytes) => { Body::Binary(ref mut bytes) => {
@ -399,31 +400,31 @@ impl PayloadEncoder {
let _ = enc.write_eof(); let _ = enc.write_eof();
let b = enc.get_mut().take(); let b = enc.get_mut().take();
resp.headers.insert( resp.headers_mut().insert(
CONTENT_LENGTH, CONTENT_LENGTH,
HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap()); HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap());
*bytes = Binary::from(b); *bytes = Binary::from(b);
encoding = ContentEncoding::Identity; encoding = ContentEncoding::Identity;
TransferEncoding::eof() TransferEncoding::eof()
} else { } else {
resp.headers.insert( resp.headers_mut().insert(
CONTENT_LENGTH, CONTENT_LENGTH,
HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap()); HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap());
resp.headers.remove(TRANSFER_ENCODING); resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::length(bytes.len() as u64) TransferEncoding::length(bytes.len() as u64)
} }
} }
Body::Streaming(_) | Body::StreamingContext => { Body::Streaming(_) | Body::StreamingContext => {
if resp.chunked() { if resp.chunked() {
resp.headers.remove(CONTENT_LENGTH); resp.headers_mut().remove(CONTENT_LENGTH);
if version != Version::HTTP_11 { if version != Version::HTTP_11 {
error!("Chunked transfer encoding is forbidden for {:?}", version); error!("Chunked transfer encoding is forbidden for {:?}", version);
} }
if version == Version::HTTP_2 { if version == Version::HTTP_2 {
resp.headers.remove(TRANSFER_ENCODING); resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::eof() TransferEncoding::eof()
} else { } else {
resp.headers.insert( resp.headers_mut().insert(
TRANSFER_ENCODING, HeaderValue::from_static("chunked")); TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
TransferEncoding::chunked() TransferEncoding::chunked()
} }
@ -447,11 +448,12 @@ impl PayloadEncoder {
if version == Version::HTTP_2 { if version == Version::HTTP_2 {
error!("Connection upgrade is forbidden for HTTP/2"); error!("Connection upgrade is forbidden for HTTP/2");
} else { } else {
resp.headers.insert(CONNECTION, HeaderValue::from_static("upgrade")); resp.headers_mut().insert(
CONNECTION, HeaderValue::from_static("upgrade"));
} }
if encoding != ContentEncoding::Identity { if encoding != ContentEncoding::Identity {
encoding = ContentEncoding::Identity; encoding = ContentEncoding::Identity;
resp.headers.remove(CONTENT_ENCODING); resp.headers_mut().remove(CONTENT_ENCODING);
} }
TransferEncoding::eof() TransferEncoding::eof()
} }

View File

@ -116,7 +116,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse) fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse)
-> Result<WriterState, io::Error> -> Result<WriterState, io::Error>
{ {
trace!("Prepare response with status: {:?}", msg.status); trace!("Prepare response with status: {:?}", msg.status());
// prepare task // prepare task
self.started = true; self.started = true;
@ -126,32 +126,32 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
// Connection upgrade // Connection upgrade
let version = msg.version().unwrap_or_else(|| req.version()); let version = msg.version().unwrap_or_else(|| req.version());
if msg.upgrade() { if msg.upgrade() {
msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade")); msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade"));
} }
// keep-alive // keep-alive
else if self.keepalive { else if self.keepalive {
if version < Version::HTTP_11 { if version < Version::HTTP_11 {
msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive")); msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("keep-alive"));
} }
} else if version >= Version::HTTP_11 { } else if version >= Version::HTTP_11 {
msg.headers.insert(CONNECTION, HeaderValue::from_static("close")); msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("close"));
} }
// render message // render message
{ {
let buffer = self.encoder.get_mut(); let buffer = self.encoder.get_mut();
if let Body::Binary(ref bytes) = *msg.body() { if let Body::Binary(ref bytes) = *msg.body() {
buffer.reserve(100 + msg.headers.len() * AVERAGE_HEADER_SIZE + bytes.len()); buffer.reserve(100 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len());
} else { } else {
buffer.reserve(100 + msg.headers.len() * AVERAGE_HEADER_SIZE); buffer.reserve(100 + msg.headers().len() * AVERAGE_HEADER_SIZE);
} }
if version == Version::HTTP_11 && msg.status == StatusCode::OK { if version == Version::HTTP_11 && msg.status() == StatusCode::OK {
buffer.extend(b"HTTP/1.1 200 OK\r\n"); buffer.extend(b"HTTP/1.1 200 OK\r\n");
} else { } else {
let _ = write!(buffer, "{:?} {}\r\n", version, msg.status); let _ = write!(buffer, "{:?} {}\r\n", version, msg.status());
} }
for (key, value) in &msg.headers { for (key, value) in msg.headers() {
let t: &[u8] = key.as_ref(); let t: &[u8] = key.as_ref();
buffer.extend(t); buffer.extend(t);
buffer.extend(b": "); buffer.extend(b": ");
@ -161,7 +161,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
// using http::h1::date is quite a lot faster than generating // using http::h1::date is quite a lot faster than generating
// a unique Date header each time like req/s goes up about 10% // a unique Date header each time like req/s goes up about 10%
if !msg.headers.contains_key(DATE) { if !msg.headers().contains_key(DATE) {
buffer.reserve(date::DATE_VALUE_LENGTH + 8); buffer.reserve(date::DATE_VALUE_LENGTH + 8);
buffer.extend(b"Date: "); buffer.extend(b"Date: ");
let mut bytes = [0u8; 29]; let mut bytes = [0u8; 29];
@ -171,7 +171,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
} }
// default content-type // default content-type
if !msg.headers.contains_key(CONTENT_TYPE) { if !msg.headers().contains_key(CONTENT_TYPE) {
buffer.extend(b"ContentType: application/octet-stream\r\n".as_ref()); buffer.extend(b"ContentType: application/octet-stream\r\n".as_ref());
} }

View File

@ -108,7 +108,7 @@ impl Writer for H2Writer {
fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse) fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse)
-> Result<WriterState, io::Error> -> Result<WriterState, io::Error>
{ {
trace!("Prepare response with status: {:?}", msg.status); trace!("Prepare response with status: {:?}", msg.status());
// prepare response // prepare response
self.started = true; self.started = true;
@ -116,25 +116,25 @@ impl Writer for H2Writer {
self.eof = if let Body::Empty = *msg.body() { true } else { false }; self.eof = if let Body::Empty = *msg.body() { true } else { false };
// http2 specific // http2 specific
msg.headers.remove(CONNECTION); msg.headers_mut().remove(CONNECTION);
msg.headers.remove(TRANSFER_ENCODING); msg.headers_mut().remove(TRANSFER_ENCODING);
// using http::h1::date is quite a lot faster than generating // using http::h1::date is quite a lot faster than generating
// a unique Date header each time like req/s goes up about 10% // a unique Date header each time like req/s goes up about 10%
if !msg.headers.contains_key(DATE) { if !msg.headers().contains_key(DATE) {
let mut bytes = [0u8; 29]; let mut bytes = [0u8; 29];
date::extend(&mut bytes[..]); date::extend(&mut bytes[..]);
msg.headers.insert(DATE, HeaderValue::try_from(&bytes[..]).unwrap()); msg.headers_mut().insert(DATE, HeaderValue::try_from(&bytes[..]).unwrap());
} }
// default content-type // default content-type
if !msg.headers.contains_key(CONTENT_TYPE) { if !msg.headers().contains_key(CONTENT_TYPE) {
msg.headers.insert( msg.headers_mut().insert(
CONTENT_TYPE, HeaderValue::from_static("application/octet-stream")); CONTENT_TYPE, HeaderValue::from_static("application/octet-stream"));
} }
let mut resp = Response::new(()); let mut resp = Response::new(());
*resp.status_mut() = msg.status; *resp.status_mut() = msg.status();
*resp.version_mut() = Version::HTTP_2; *resp.version_mut() = Version::HTTP_2;
for (key, value) in msg.headers().iter() { for (key, value) in msg.headers().iter() {
resp.headers_mut().insert(key, value.clone()); resp.headers_mut().insert(key, value.clone());

View File

@ -97,11 +97,13 @@ impl<S> HttpRequest<S> {
HttpRequest(Rc::clone(&self.0), Rc::new(()), None) HttpRequest(Rc::clone(&self.0), Rc::new(()), None)
} }
/// get mutable reference for inner message // get mutable reference for inner message
// mutable reference should not be returned as result for request's method
#[inline] #[inline]
fn as_mut(&mut self) -> &mut HttpMessage {
let r: &HttpMessage = self.0.as_ref();
#[allow(mutable_transmutes)] #[allow(mutable_transmutes)]
#[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref))]
fn as_mut(&self) -> &mut HttpMessage {
let r: &HttpMessage = self.0.as_ref();
unsafe{mem::transmute(r)} unsafe{mem::transmute(r)}
} }
@ -158,18 +160,8 @@ impl<S> HttpRequest<S> {
self.0.uri.path() self.0.uri.path()
} }
/// Get previously loaded *ConnectionInfo*. /// Get *ConnectionInfo* for currect request.
#[inline] pub fn connection_info(&self) -> &ConnectionInfo {
pub fn connection_info(&self) -> Option<&ConnectionInfo> {
if self.0.info.is_none() {
None
} else {
self.0.info.as_ref()
}
}
/// Load *ConnectionInfo* for currect request.
pub fn load_connection_info(&mut self) -> &ConnectionInfo {
if self.0.info.is_none() { if self.0.info.is_none() {
let info: ConnectionInfo<'static> = unsafe{ let info: ConnectionInfo<'static> = unsafe{
mem::transmute(ConnectionInfo::new(self))}; mem::transmute(ConnectionInfo::new(self))};
@ -178,7 +170,7 @@ impl<S> HttpRequest<S> {
self.0.info.as_ref().unwrap() self.0.info.as_ref().unwrap()
} }
pub fn url_for<U, I>(&mut self, name: &str, elements: U) -> Result<Url, UrlGenerationError> pub fn url_for<U, I>(&self, name: &str, elements: U) -> Result<Url, UrlGenerationError>
where U: IntoIterator<Item=I>, where U: IntoIterator<Item=I>,
I: AsRef<str>, I: AsRef<str>,
{ {
@ -187,7 +179,7 @@ impl<S> HttpRequest<S> {
} else { } else {
let path = self.router().unwrap().resource_path(name, elements)?; let path = self.router().unwrap().resource_path(name, elements)?;
if path.starts_with('/') { if path.starts_with('/') {
let conn = self.load_connection_info(); let conn = self.connection_info();
Ok(Url::parse(&format!("{}://{}{}", conn.scheme(), conn.host(), path))?) Ok(Url::parse(&format!("{}://{}{}", conn.scheme(), conn.host(), path))?)
} else { } else {
Ok(Url::parse(&path)?) Ok(Url::parse(&path)?)

View File

@ -29,9 +29,9 @@ pub enum ConnectionType {
/// An HTTP Response /// An HTTP Response
pub struct HttpResponse { pub struct HttpResponse {
pub version: Option<Version>, version: Option<Version>,
pub headers: HeaderMap, headers: HeaderMap,
pub status: StatusCode, status: StatusCode,
reason: Option<&'static str>, reason: Option<&'static str>,
body: Body, body: Body,
chunked: bool, chunked: bool,

View File

@ -102,7 +102,6 @@ impl Logger {
impl Middleware for Logger { impl Middleware for Logger {
fn start(&self, req: &mut HttpRequest) -> Started { fn start(&self, req: &mut HttpRequest) -> Started {
req.load_connection_info();
req.extensions().insert(StartTime(time::now())); req.extensions().insert(StartTime(time::now()));
Started::Done Started::Done
} }
@ -237,13 +236,12 @@ impl FormatText {
fmt.write_fmt(format_args!("{:.6}", response_time_ms)) fmt.write_fmt(format_args!("{:.6}", response_time_ms))
}, },
FormatText::RemoteAddr => { FormatText::RemoteAddr => {
if let Some(addr) = req.connection_info() { if let Some(remote) = req.connection_info().remote() {
if let Some(remote) = addr.remote() {
return remote.fmt(fmt); return remote.fmt(fmt);
} } else {
}
"-".fmt(fmt) "-".fmt(fmt)
} }
}
FormatText::RequestTime => { FormatText::RequestTime => {
entry_time.strftime("[%d/%b/%Y:%H:%M:%S %z]") entry_time.strftime("[%d/%b/%Y:%H:%M:%S %z]")
.unwrap() .unwrap()