Skip to content

Commit

Permalink
use custom headers map; more optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Apr 6, 2019
1 parent 4ef46e2 commit 748289f
Show file tree
Hide file tree
Showing 35 changed files with 670 additions and 182 deletions.
4 changes: 2 additions & 2 deletions actix-files/src/named.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ impl Responder for NamedFile {
// check last modified
let not_modified = if !none_match(etag.as_ref(), req) {
true
} else if req.headers().contains_key(header::IF_NONE_MATCH) {
} else if req.headers().contains_key(&header::IF_NONE_MATCH) {
false
} else if let (Some(ref m), Some(header::IfModifiedSince(ref since))) =
(last_modified, req.get_header())
Expand Down Expand Up @@ -378,7 +378,7 @@ impl Responder for NamedFile {
let mut offset = 0;

// check for range header
if let Some(ranges) = req.headers().get(header::RANGE) {
if let Some(ranges) = req.headers().get(&header::RANGE) {
if let Ok(rangesheader) = ranges.to_str() {
if let Ok(rangesvec) = HttpRange::parse(rangesheader, length) {
length = rangesvec[0].length;
Expand Down
1 change: 1 addition & 0 deletions actix-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ bitflags = "1.0"
bytes = "0.4"
byteorder = "1.2"
derive_more = "0.14"
either = "1.5.2"
encoding = "0.2"
futures = "0.1"
hashbrown = "0.1.8"
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/client/h2proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ where
let mut head = ResponseHead::default();
head.version = parts.version;
head.status = parts.status;
head.headers = parts.headers;
head.headers = parts.headers.into();

Ok((head, payload))
})
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/encoding/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ where
#[inline]
pub fn from_headers(stream: S, headers: &HeaderMap) -> Decoder<S> {
// check content-encoding
let encoding = if let Some(enc) = headers.get(CONTENT_ENCODING) {
let encoding = if let Some(enc) = headers.get(&CONTENT_ENCODING) {
if let Ok(enc) = enc.to_str() {
ContentEncoding::from(enc)
} else {
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/encoding/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<B: MessageBody> Encoder<B> {
head: &mut ResponseHead,
body: ResponseBody<B>,
) -> ResponseBody<Encoder<B>> {
let can_encode = !(head.headers().contains_key(CONTENT_ENCODING)
let can_encode = !(head.headers().contains_key(&CONTENT_ENCODING)
|| head.status == StatusCode::SWITCHING_PROTOCOLS
|| encoding == ContentEncoding::Identity
|| encoding == ContentEncoding::Auto);
Expand Down
64 changes: 30 additions & 34 deletions actix-http/src/h1/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use crate::response::Response;
bitflags! {
struct Flags: u8 {
const HEAD = 0b0000_0001;
const KEEPALIVE_ENABLED = 0b0000_1000;
const STREAM = 0b0001_0000;
const KEEPALIVE_ENABLED = 0b0000_0010;
const STREAM = 0b0000_0100;
}
}

Expand All @@ -39,8 +39,8 @@ pub struct Codec {

// encoder part
flags: Flags,
headers_size: u32,
encoder: encoder::MessageEncoder<Response<()>>,
// headers_size: u32,
}

impl Default for Codec {
Expand Down Expand Up @@ -73,7 +73,7 @@ impl Codec {
ctype: ConnectionType::Close,

flags,
headers_size: 0,
// headers_size: 0,
encoder: encoder::MessageEncoder::default(),
}
}
Expand Down Expand Up @@ -159,37 +159,33 @@ impl Encoder for Codec {
) -> Result<(), Self::Error> {
match item {
Message::Item((mut res, length)) => {
if res.head().status == StatusCode::CONTINUE {
dst.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
} else {
// set response version
res.head_mut().version = self.version;

// connection status
self.ctype = if let Some(ct) = res.head().ctype() {
if ct == ConnectionType::KeepAlive {
self.ctype
} else {
ct
}
} else {
// set response version
res.head_mut().version = self.version;

// connection status
self.ctype = if let Some(ct) = res.head().ctype() {
if ct == ConnectionType::KeepAlive {
self.ctype
};

// encode message
let len = dst.len();
self.encoder.encode(
dst,
&mut res,
self.flags.contains(Flags::HEAD),
self.flags.contains(Flags::STREAM),
self.version,
length,
self.ctype,
&self.config,
)?;
self.headers_size = (dst.len() - len) as u32;
}
} else {
ct
}
} else {
self.ctype
};

// encode message
let len = dst.len();
self.encoder.encode(
dst,
&mut res,
self.flags.contains(Flags::HEAD),
self.flags.contains(Flags::STREAM),
self.version,
length,
self.ctype,
&self.config,
)?;
// self.headers_size = (dst.len() - len) as u32;
}
Message::Chunk(Some(bytes)) => {
self.encoder.encode_chunk(bytes.as_ref(), dst)?;
Expand Down
19 changes: 13 additions & 6 deletions actix-http/src/h1/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use actix_codec::Decoder;
use bytes::{Bytes, BytesMut};
use futures::{Async, Poll};
use http::header::{HeaderName, HeaderValue};
use http::{header, HeaderMap, HttpTryFrom, Method, StatusCode, Uri, Version};
use http::{header, HttpTryFrom, Method, StatusCode, Uri, Version};
use httparse;
use log::{debug, error, trace};

use crate::error::ParseError;
use crate::header::HeaderMap;
use crate::message::{ConnectionType, ResponseHead};
use crate::request::Request;

Expand Down Expand Up @@ -630,6 +631,7 @@ mod tests {

use super::*;
use crate::error::ParseError;
use crate::http::header::{HeaderName, SET_COOKIE};
use crate::httpmessage::HttpMessage;

impl PayloadType {
Expand Down Expand Up @@ -790,7 +792,13 @@ mod tests {
assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET);
assert_eq!(req.path(), "/test");
assert_eq!(req.headers().get("test").unwrap().as_bytes(), b"value");
assert_eq!(
req.headers()
.get(HeaderName::try_from("test").unwrap())
.unwrap()
.as_bytes(),
b"value"
);
}

#[test]
Expand All @@ -805,12 +813,11 @@ mod tests {

let val: Vec<_> = req
.headers()
.get_all("Set-Cookie")
.iter()
.get_all(SET_COOKIE)
.map(|v| v.to_str().unwrap().to_owned())
.collect();
assert_eq!(val[0], "c1=cookie1");
assert_eq!(val[1], "c2=cookie2");
assert_eq!(val[1], "c1=cookie1");
assert_eq!(val[0], "c2=cookie2");
}

#[test]
Expand Down
81 changes: 55 additions & 26 deletions actix-http/src/h1/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ use std::str::FromStr;
use std::{cmp, fmt, io, mem};

use bytes::{BufMut, Bytes, BytesMut};
use http::header::{
HeaderValue, ACCEPT_ENCODING, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING,
};
use http::{HeaderMap, Method, StatusCode, Version};

use crate::body::BodySize;
use crate::config::ServiceConfig;
use crate::header::map;
use crate::header::ContentEncoding;
use crate::helpers;
use crate::http::header::{
HeaderValue, ACCEPT_ENCODING, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING,
};
use crate::http::{HeaderMap, Method, StatusCode, Version};
use crate::message::{ConnectionType, Head, RequestHead, ResponseHead};
use crate::request::Request;
use crate::response::Response;
Expand Down Expand Up @@ -109,7 +110,7 @@ pub(crate) trait MessageType: Sized {
let mut has_date = false;
let mut remaining = dst.remaining_mut();
let mut buf = unsafe { &mut *(dst.bytes_mut() as *mut [u8]) };
for (key, value) in self.headers() {
for (key, value) in self.headers().inner.iter() {
match *key {
CONNECTION => continue,
TRANSFER_ENCODING | CONTENT_LENGTH if skip_len => continue,
Expand All @@ -118,31 +119,59 @@ pub(crate) trait MessageType: Sized {
}
_ => (),
}

let v = value.as_ref();
let k = key.as_str().as_bytes();
let len = k.len() + v.len() + 4;
if len > remaining {
unsafe {
dst.advance_mut(pos);
match value {
map::Value::One(ref val) => {
let v = val.as_ref();
let len = k.len() + v.len() + 4;
if len > remaining {
unsafe {
dst.advance_mut(pos);
}
pos = 0;
dst.reserve(len);
remaining = dst.remaining_mut();
unsafe {
buf = &mut *(dst.bytes_mut() as *mut _);
}
}
buf[pos..pos + k.len()].copy_from_slice(k);
pos += k.len();
buf[pos..pos + 2].copy_from_slice(b": ");
pos += 2;
buf[pos..pos + v.len()].copy_from_slice(v);
pos += v.len();
buf[pos..pos + 2].copy_from_slice(b"\r\n");
pos += 2;
remaining -= len;
}
pos = 0;
dst.reserve(len);
remaining = dst.remaining_mut();
unsafe {
buf = &mut *(dst.bytes_mut() as *mut _);
map::Value::Multi(ref vec) => {
for val in vec {
let v = val.as_ref();
let len = k.len() + v.len() + 4;
if len > remaining {
unsafe {
dst.advance_mut(pos);
}
pos = 0;
dst.reserve(len);
remaining = dst.remaining_mut();
unsafe {
buf = &mut *(dst.bytes_mut() as *mut _);
}
}
buf[pos..pos + k.len()].copy_from_slice(k);
pos += k.len();
buf[pos..pos + 2].copy_from_slice(b": ");
pos += 2;
buf[pos..pos + v.len()].copy_from_slice(v);
pos += v.len();
buf[pos..pos + 2].copy_from_slice(b"\r\n");
pos += 2;
remaining -= len;
}
}
}

buf[pos..pos + k.len()].copy_from_slice(k);
pos += k.len();
buf[pos..pos + 2].copy_from_slice(b": ");
pos += 2;
buf[pos..pos + v.len()].copy_from_slice(v);
pos += v.len();
buf[pos..pos + 2].copy_from_slice(b"\r\n");
pos += 2;
remaining -= len;
}
unsafe {
dst.advance_mut(pos);
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/h2/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ where
head.uri = parts.uri;
head.method = parts.method;
head.version = parts.version;
head.headers = parts.headers;
head.headers = parts.headers.into();
tokio_current_thread::spawn(ServiceResponse::<S::Future, B> {
state: ServiceResponseState::ServiceCall(
self.service.call(req),
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/header/common/cache_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Header for CacheControl {
where
T: crate::HttpMessage,
{
let directives = from_comma_delimited(msg.headers().get_all(Self::name()))?;
let directives = from_comma_delimited(msg.headers().get_all(&Self::name()))?;
if !directives.is_empty() {
Ok(CacheControl(directives))
} else {
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/header/common/content_disposition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl Header for ContentDisposition {
}

fn parse<T: crate::HttpMessage>(msg: &T) -> Result<Self, crate::error::ParseError> {
if let Some(h) = msg.headers().get(Self::name()) {
if let Some(h) = msg.headers().get(&Self::name()) {
Self::from_raw(&h)
} else {
Err(crate::error::ParseError::Header)
Expand Down
4 changes: 2 additions & 2 deletions actix-http/src/header/common/if_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ impl Header for IfRange {
T: HttpMessage,
{
let etag: Result<EntityTag, _> =
from_one_raw_str(msg.headers().get(header::IF_RANGE));
from_one_raw_str(msg.headers().get(&header::IF_RANGE));
if let Ok(etag) = etag {
return Ok(IfRange::EntityTag(etag));
}
let date: Result<HttpDate, _> =
from_one_raw_str(msg.headers().get(header::IF_RANGE));
from_one_raw_str(msg.headers().get(&header::IF_RANGE));
if let Ok(date) = date {
return Ok(IfRange::Date(date));
}
Expand Down
Loading

0 comments on commit 748289f

Please sign in to comment.