mirror of
https://github.com/actix/actix-web.git
synced 2024-12-19 22:56:39 +00:00
simplify api
This commit is contained in:
parent
dff7618f35
commit
0abb3863dc
6 changed files with 49 additions and 57 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
let r: &HttpMessage = self.0.as_ref();
|
||||
#[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)}
|
||||
}
|
||||
|
||||
|
@ -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)?)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,13 +236,12 @@ 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() {
|
||||
if let Some(remote) = req.connection_info().remote() {
|
||||
return remote.fmt(fmt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"-".fmt(fmt)
|
||||
}
|
||||
}
|
||||
FormatText::RequestTime => {
|
||||
entry_time.strftime("[%d/%b/%Y:%H:%M:%S %z]")
|
||||
.unwrap()
|
||||
|
|
Loading…
Reference in a new issue