Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/header/common/accept_ranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ header! {
#[doc="# Example values"]
#[doc="* `bytes`"]
#[doc="* `none`"]
#[doc="* `unknown-unit`"]
#[doc="```"]
(AcceptRanges, "Accept-Ranges") => (RangeUnit)+

test_acccept_ranges {
test_header!(test1, vec![b"bytes"]);
test_header!(test2, vec![b"none"]);
test_header!(test3, vec![b"unknown-unit"]);
test_header!(test4, vec![b"bytes, unknown-unit"]);
}
}

Expand Down
74 changes: 30 additions & 44 deletions src/header/common/connection.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,9 @@
use header::{Header, HeaderFormat};
use std::fmt::{self, Display};
use std::str::FromStr;
use header::parsing::{from_comma_delimited, fmt_comma_delimited};
use unicase::UniCase;

pub use self::ConnectionOption::{KeepAlive, Close, ConnectionHeader};

/// `Connection` header, defined in [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.1)
///
/// The `Connection` header field allows the sender to indicate desired
/// control options for the current connection. In order to avoid
/// confusing downstream recipients, a proxy or gateway MUST remove or
/// replace any received connection options before forwarding the
/// message.
///
/// # ABNF
/// ```plain
/// Connection = 1#connection-option
/// connection-option = token
/// ```
///
/// # Example values
/// * `close`
/// * `upgrade`
/// * `keep-alive`
#[derive(Clone, PartialEq, Debug)]
pub struct Connection(pub Vec<ConnectionOption>);

deref!(Connection => Vec<ConnectionOption>);

/// Values that can be in the `Connection` header.
#[derive(Clone, PartialEq, Debug)]
pub enum ConnectionOption {
Expand All @@ -50,11 +25,11 @@ pub enum ConnectionOption {
impl FromStr for ConnectionOption {
type Err = ();
fn from_str(s: &str) -> Result<ConnectionOption, ()> {
Ok(match s {
"keep-alive" => KeepAlive,
"close" => Close,
s => ConnectionHeader(UniCase(s.to_string())),
})
match s {
"keep-alive" => Ok(KeepAlive),
"close" => Ok(Close),
s => Ok(ConnectionHeader(UniCase(s.to_string())))
}
}
}

Expand All @@ -63,25 +38,36 @@ impl Display for ConnectionOption {
f.write_str(match *self {
KeepAlive => "keep-alive",
Close => "close",
ConnectionHeader(UniCase(ref s)) => s,
ConnectionHeader(UniCase(ref s)) => s.as_ref()
})
}
}

impl Header for Connection {
fn header_name() -> &'static str {
"Connection"
}

fn parse_header(raw: &[Vec<u8>]) -> Option<Connection> {
from_comma_delimited(raw).map(|vec| Connection(vec))
}
}
header! {
#[doc="`Connection` header, defined in"]
#[doc="[RFC7230](http://tools.ietf.org/html/rfc7230#section-6.1)"]
#[doc=""]
#[doc="The `Connection` header field allows the sender to indicate desired"]
#[doc="control options for the current connection. In order to avoid"]
#[doc="confusing downstream recipients, a proxy or gateway MUST remove or"]
#[doc="replace any received connection options before forwarding the"]
#[doc="message."]
#[doc=""]
#[doc="# ABNF"]
#[doc="```plain"]
#[doc="Connection = 1#connection-option"]
#[doc="connection-option = token"]
#[doc=""]
#[doc="# Example values"]
#[doc="* `close`"]
#[doc="* `keep-alive`"]
#[doc="* `upgrade`"]
(Connection, "Connection") => (ConnectionOption)+

impl HeaderFormat for Connection {
fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Connection(ref parts) = *self;
fmt_comma_delimited(f, &parts[..])
test_connection {
test_header!(test1, vec![b"close"]);
test_header!(test2, vec![b"keep-alive"]);
test_header!(test3, vec![b"upgrade"]);
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/header/common/if_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ impl Display for IfRange {
}

#[cfg(test)]
mod test_range {
mod test_if_range {
use std::str;
use header::*;
use super::IfRange as HeaderField;
test_header!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]);
test_header!(test2, vec![b"\"xyzzy\""]);
test_header!(test3, vec![b"this-is-invalid"], None::<IfRange>);
}
2 changes: 0 additions & 2 deletions src/header/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@ macro_rules! header {
if raw.len() == 1 {
if raw[0] == b"*" {
return Some($id::Any)
} else if raw[0] == b"" {
return None
}
}
$crate::header::parsing::from_comma_delimited(raw).map(|vec| $id::Items(vec))
Expand Down
9 changes: 2 additions & 7 deletions src/header/shared/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ use std::fmt::{self, Display};
// 2. in the range %x23 to %x7E, or
// 3. in the range %x80 to %xFF
fn check_slice_validity(slice: &str) -> bool {
for c in slice.bytes() {
match c {
b'\x21' | b'\x23' ... b'\x7e' | b'\x80' ... b'\xff' => (),
_ => { return false; }
}
}
true
slice.bytes().all(|c|
c == b'\x21' || (c >= b'\x23' && c <= b'\x7e') | (c >= b'\x80' && c <= b'\xff'))
}

/// An entity tag, defined in [RFC7232](https://tools.ietf.org/html/rfc7232#section-2.3)
Expand Down
5 changes: 5 additions & 0 deletions src/header/shared/httpdate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ mod tests {
fn test_asctime() {
assert_eq!("Sun Nov 7 08:48:37 1994".parse(), Ok(NOV_07));
}

#[test]
fn test_no_date() {
assert_eq!("this-is-no-date".parse(), Err::<HttpDate, ()>(()));
}
}
6 changes: 6 additions & 0 deletions src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl fmt::Display for Method {
mod tests {
use std::collections::HashMap;
use std::str::FromStr;
use error::Error;
use super::Method;
use super::Method::{Get, Post, Put, Extension};

Expand All @@ -150,6 +151,11 @@ mod tests {
assert_eq!(Get, FromStr::from_str("GET").unwrap());
assert_eq!(Extension("MOVE".to_string()),
FromStr::from_str("MOVE").unwrap());
let x: Result<Method, _> = FromStr::from_str("");
if let Err(Error::Method) = x {
} else {
panic!("An empty method is invalid!")
}
}

#[test]
Expand Down