mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
simplify api
This commit is contained in:
parent
dff7618f35
commit
0abb3863dc
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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 {
|
#[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();
|
let r: &HttpMessage = self.0.as_ref();
|
||||||
#[allow(mutable_transmutes)]
|
|
||||||
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)?)
|
||||||
|
@ -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,
|
||||||
|
@ -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,12 +236,11 @@ 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]")
|
||||||
|
Loading…
Reference in New Issue
Block a user