1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +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
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() {
ContentEncoding::Auto => {
// negotiate content-encoding
@ -362,7 +362,8 @@ impl PayloadEncoder {
}
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
} else {
ContentEncoding::Identity
@ -377,8 +378,8 @@ impl PayloadEncoder {
if resp.chunked() {
error!("Chunked transfer is enabled but body is set to Empty");
}
resp.headers.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
resp.headers.remove(TRANSFER_ENCODING);
resp.headers_mut().insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::length(0)
},
Body::Binary(ref mut bytes) => {
@ -399,31 +400,31 @@ impl PayloadEncoder {
let _ = enc.write_eof();
let b = enc.get_mut().take();
resp.headers.insert(
resp.headers_mut().insert(
CONTENT_LENGTH,
HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap());
*bytes = Binary::from(b);
encoding = ContentEncoding::Identity;
TransferEncoding::eof()
} else {
resp.headers.insert(
resp.headers_mut().insert(
CONTENT_LENGTH,
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)
}
}
Body::Streaming(_) | Body::StreamingContext => {
if resp.chunked() {
resp.headers.remove(CONTENT_LENGTH);
resp.headers_mut().remove(CONTENT_LENGTH);
if version != Version::HTTP_11 {
error!("Chunked transfer encoding is forbidden for {:?}", version);
}
if version == Version::HTTP_2 {
resp.headers.remove(TRANSFER_ENCODING);
resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::eof()
} else {
resp.headers.insert(
resp.headers_mut().insert(
TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
TransferEncoding::chunked()
}
@ -447,11 +448,12 @@ impl PayloadEncoder {
if version == Version::HTTP_2 {
error!("Connection upgrade is forbidden for HTTP/2");
} else {
resp.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
resp.headers_mut().insert(
CONNECTION, HeaderValue::from_static("upgrade"));
}
if encoding != ContentEncoding::Identity {
encoding = ContentEncoding::Identity;
resp.headers.remove(CONTENT_ENCODING);
resp.headers_mut().remove(CONTENT_ENCODING);
}
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)
-> Result<WriterState, io::Error>
{
trace!("Prepare response with status: {:?}", msg.status);
trace!("Prepare response with status: {:?}", msg.status());
// prepare task
self.started = true;
@ -126,32 +126,32 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
// Connection upgrade
let version = msg.version().unwrap_or_else(|| req.version());
if msg.upgrade() {
msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade"));
}
// keep-alive
else if self.keepalive {
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 {
msg.headers.insert(CONNECTION, HeaderValue::from_static("close"));
msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("close"));
}
// render message
{
let buffer = self.encoder.get_mut();
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 {
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");
} 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();
buffer.extend(t);
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
// 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.extend(b"Date: ");
let mut bytes = [0u8; 29];
@ -171,7 +171,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
}
// 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());
}

View File

@ -108,7 +108,7 @@ impl Writer for H2Writer {
fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse)
-> Result<WriterState, io::Error>
{
trace!("Prepare response with status: {:?}", msg.status);
trace!("Prepare response with status: {:?}", msg.status());
// prepare response
self.started = true;
@ -116,25 +116,25 @@ impl Writer for H2Writer {
self.eof = if let Body::Empty = *msg.body() { true } else { false };
// http2 specific
msg.headers.remove(CONNECTION);
msg.headers.remove(TRANSFER_ENCODING);
msg.headers_mut().remove(CONNECTION);
msg.headers_mut().remove(TRANSFER_ENCODING);
// using http::h1::date is quite a lot faster than generating
// 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];
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
if !msg.headers.contains_key(CONTENT_TYPE) {
msg.headers.insert(
if !msg.headers().contains_key(CONTENT_TYPE) {
msg.headers_mut().insert(
CONTENT_TYPE, HeaderValue::from_static("application/octet-stream"));
}
let mut resp = Response::new(());
*resp.status_mut() = msg.status;
*resp.status_mut() = msg.status();
*resp.version_mut() = Version::HTTP_2;
for (key, value) in msg.headers().iter() {
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)
}
/// 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]
fn as_mut(&mut self) -> &mut HttpMessage {
#[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();
#[allow(mutable_transmutes)]
unsafe{mem::transmute(r)}
}
@ -158,18 +160,8 @@ impl<S> HttpRequest<S> {
self.0.uri.path()
}
/// Get previously loaded *ConnectionInfo*.
#[inline]
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 {
/// Get *ConnectionInfo* for currect request.
pub fn connection_info(&self) -> &ConnectionInfo {
if self.0.info.is_none() {
let info: ConnectionInfo<'static> = unsafe{
mem::transmute(ConnectionInfo::new(self))};
@ -178,7 +170,7 @@ impl<S> HttpRequest<S> {
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>,
I: AsRef<str>,
{
@ -187,7 +179,7 @@ impl<S> HttpRequest<S> {
} else {
let path = self.router().unwrap().resource_path(name, elements)?;
if path.starts_with('/') {
let conn = self.load_connection_info();
let conn = self.connection_info();
Ok(Url::parse(&format!("{}://{}{}", conn.scheme(), conn.host(), path))?)
} else {
Ok(Url::parse(&path)?)

View File

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

View File

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