Change signature of insertion/appending of headers

Currently the insert and append functions on Headers panics on illegal
header value encoding. This commit exposes that failure mode to the
library users by wrapping the return in a result instead.

This change exposes a possible optimization in places where insert/append
is called with values known to be safe by creating unsafe
insertion/appending functions. This commit does not implement any such
extensions.
This commit is contained in:
Erik Funder Carstensen 2021-10-30 18:19:44 +02:00
parent 0127e5bdfd
commit 0937e60091
30 changed files with 167 additions and 82 deletions

View File

@ -129,7 +129,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(AUTHORIZATION, "<nori ate the tag. yum.>");
headers
.insert(AUTHORIZATION, "<nori ate the tag. yum.>")
.unwrap();
let err = Authorization::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -135,7 +135,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(AUTHORIZATION, "<nori ate the tag. yum.>");
headers
.insert(AUTHORIZATION, "<nori ate the tag. yum.>")
.unwrap();
let err = BasicAuth::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -156,7 +156,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(WWW_AUTHENTICATE, "<nori ate the tag. yum.>");
headers
.insert(WWW_AUTHENTICATE, "<nori ate the tag. yum.>")
.unwrap();
let err = WwwAuthenticate::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

2
src/cache/age.rs vendored
View File

@ -102,7 +102,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(AGE, "<nori ate the tag. yum.>");
headers.insert(AGE, "<nori ate the tag. yum.>").unwrap();
let err = Age::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -37,7 +37,7 @@ mod test {
#[test]
fn ignore_unkonwn_directives() -> crate::Result<()> {
let mut headers = Headers::new();
headers.insert(CACHE_CONTROL, "barrel_roll");
headers.insert(CACHE_CONTROL, "barrel_roll").unwrap();
let entries = CacheControl::from_headers(headers)?.unwrap();
let mut entries = entries.iter();
assert!(entries.next().is_none());
@ -47,7 +47,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(CACHE_CONTROL, "min-fresh=0.9"); // floats are not supported
headers.insert(CACHE_CONTROL, "min-fresh=0.9").unwrap(); // floats are not supported
let err = CacheControl::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -278,7 +278,8 @@ mod test {
#[test]
fn parse_quotes_correctly() -> crate::Result<()> {
let mut res = Response::new(200);
res.insert_header("clear-site-data", r#""cookies""#);
res.insert_header("clear-site-data", r#""cookies""#)
.unwrap();
let entries = ClearSiteData::from_headers(res)?.unwrap();
assert!(!entries.wildcard());
@ -286,7 +287,7 @@ mod test {
assert_eq!(entries.next().unwrap(), &ClearDirective::Cookies);
let mut res = Response::new(200);
res.insert_header("clear-site-data", r#""*""#);
res.insert_header("clear-site-data", r#""*""#).unwrap();
let entries = ClearSiteData::from_headers(res)?.unwrap();
assert!(entries.wildcard());

View File

@ -107,7 +107,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(EXPIRES, "<nori ate the tag. yum.>");
headers.insert(EXPIRES, "<nori ate the tag. yum.>").unwrap();
let err = Expires::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -164,7 +164,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(ETAG, "<nori ate the tag. yum.>");
headers.insert(ETAG, "<nori ate the tag. yum.>").unwrap();
let err = ETag::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}
@ -179,7 +179,7 @@ mod test {
fn assert_entry_err(s: &str, msg: &str) {
let mut headers = Headers::new();
headers.insert(ETAG, s);
headers.insert(ETAG, s).unwrap();
let err = ETag::from_headers(headers).unwrap_err();
assert_eq!(format!("{}", err), msg);
}

View File

@ -104,7 +104,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(IF_MODIFIED_SINCE, "<nori ate the tag. yum.>");
headers
.insert(IF_MODIFIED_SINCE, "<nori ate the tag. yum.>")
.unwrap();
let err = IfModifiedSince::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -104,7 +104,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(IF_UNMODIFIED_SINCE, "<nori ate the tag. yum.>");
headers
.insert(IF_UNMODIFIED_SINCE, "<nori ate the tag. yum.>")
.unwrap();
let err = IfUnmodifiedSince::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -103,7 +103,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(LAST_MODIFIED, "<nori ate the tag. yum.>");
headers
.insert(LAST_MODIFIED, "<nori ate the tag. yum.>")
.unwrap();
let err = LastModified::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -94,7 +94,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(CONTENT_LENGTH, "<nori ate the tag. yum.>");
headers
.insert(CONTENT_LENGTH, "<nori ate the tag. yum.>")
.unwrap();
let err = ContentLength::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -118,7 +118,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(CONTENT_LOCATION, "htt://<nori ate the tag. yum.>");
headers
.insert(CONTENT_LOCATION, "htt://<nori ate the tag. yum.>")
.unwrap();
let err =
ContentLocation::from_headers(Url::parse("https://example.net").unwrap(), headers)
.unwrap_err();

View File

@ -127,7 +127,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(CONTENT_TYPE, "<nori ate the tag. yum.>");
headers
.insert(CONTENT_TYPE, "<nori ate the tag. yum.>")
.unwrap();
let err = ContentType::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -15,7 +15,10 @@ pub trait Header {
fn apply_header<H: AsMut<Headers>>(&self, mut headers: H) {
let name = self.header_name();
let value = self.header_value();
headers.as_mut().insert(name, value);
// The value should already have been validated when it was created, so this should
// possibly be done with an unsafe call
headers.as_mut().insert(name, value).unwrap();
}
}

View File

@ -172,7 +172,8 @@ mod tests {
#[test]
fn pass_name_by_ref() {
let mut res = crate::Response::new(200);
res.insert_header(&crate::headers::HOST, "127.0.0.1");
res.insert_header(&crate::headers::HOST, "127.0.0.1")
.unwrap();
}
#[test]

View File

@ -49,27 +49,32 @@ impl Headers {
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> Option<HeaderValues> {
) -> crate::Result<Option<HeaderValues>> {
let name = name.into();
let values: HeaderValues = values.to_header_values().unwrap().collect();
self.headers.insert(name, values)
let values: HeaderValues = values.to_header_values()?.collect();
Ok(self.headers.insert(name, values))
}
/// Append a header to the headers.
///
/// Unlike `insert` this function will not override the contents of a header, but insert a
/// header if there aren't any. Or else append to the existing list of headers.
pub fn append(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
pub fn append(
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<()> {
let name = name.into();
match self.get_mut(&name) {
Some(headers) => {
let mut values: HeaderValues = values.to_header_values().unwrap().collect();
let mut values: HeaderValues = values.to_header_values()?.collect();
headers.append(&mut values);
}
None => {
self.insert(name, values);
self.insert(name, values)?;
}
}
Ok(())
}
/// Get a reference to a header.
@ -208,9 +213,9 @@ mod tests {
let non_static_header = HeaderName::from_str("hello")?;
let mut headers = Headers::new();
headers.append(STATIC_HEADER, "foo0");
headers.append(static_header.clone(), "foo1");
headers.append(non_static_header.clone(), "foo2");
headers.append(STATIC_HEADER, "foo0").unwrap();
headers.append(static_header.clone(), "foo1").unwrap();
headers.append(non_static_header.clone(), "foo2").unwrap();
assert_eq!(headers[STATIC_HEADER], ["foo0", "foo1", "foo2",][..]);
assert_eq!(headers[static_header], ["foo0", "foo1", "foo2",][..]);
@ -222,7 +227,7 @@ mod tests {
#[test]
fn index_into_headers() {
let mut headers = Headers::new();
headers.insert("hello", "foo0");
headers.insert("hello", "foo0").unwrap();
assert_eq!(headers["hello"], "foo0");
assert_eq!(headers.get("hello").unwrap(), "foo0");
}
@ -230,15 +235,15 @@ mod tests {
#[test]
fn test_debug_single() {
let mut headers = Headers::new();
headers.insert("single", "foo0");
headers.insert("single", "foo0").unwrap();
assert_eq!(format!("{:?}", headers), r#"{"single": "foo0"}"#);
}
#[test]
fn test_debug_multiple() {
let mut headers = Headers::new();
headers.append("multi", "foo0");
headers.append("multi", "foo1");
headers.append("multi", "foo0").unwrap();
headers.append("multi", "foo1").unwrap();
assert_eq!(format!("{:?}", headers), r#"{"multi": ["foo0", "foo1"]}"#);
}
}

View File

@ -129,7 +129,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(DATE, "<nori ate the tag. yum.>");
headers.insert(DATE, "<nori ate the tag. yum.>").unwrap();
let err = Date::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -87,7 +87,7 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(EXPECT, "<nori ate the tag. yum.>");
headers.insert(EXPECT, "<nori ate the tag. yum.>").unwrap();
let err = Expect::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -123,7 +123,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(REFERER, "htt://<nori ate the tag. yum.>");
headers
.insert(REFERER, "htt://<nori ate the tag. yum.>")
.unwrap();
let err =
Referer::from_headers(Url::parse("https://example.net").unwrap(), headers).unwrap_err();
assert_eq!(err.status(), 500);
@ -132,7 +134,7 @@ mod test {
#[test]
fn fallback_works() -> crate::Result<()> {
let mut headers = Headers::new();
headers.insert(REFERER, "/test.json");
headers.insert(REFERER, "/test.json").unwrap();
let base_url = Url::parse("https://fallback.net/")?;
let referer = Referer::from_headers(base_url, headers)?.unwrap();
@ -142,7 +144,9 @@ mod test {
);
let mut headers = Headers::new();
headers.insert(REFERER, "https://example.com/test.json");
headers
.insert(REFERER, "https://example.com/test.json")
.unwrap();
let base_url = Url::parse("https://fallback.net/")?;
let referer = Referer::from_headers(base_url, headers)?.unwrap();

View File

@ -120,7 +120,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(SOURCE_MAP, "htt://<nori ate the tag. yum.>");
headers
.insert(SOURCE_MAP, "htt://<nori ate the tag. yum.>")
.unwrap();
let err = SourceMap::from_headers(Url::parse("https://example.net").unwrap(), headers)
.unwrap_err();
assert_eq!(err.status(), 500);
@ -129,7 +131,7 @@ mod test {
#[test]
fn fallback_works() -> crate::Result<()> {
let mut headers = Headers::new();
headers.insert(SOURCE_MAP, "/test.json");
headers.insert(SOURCE_MAP, "/test.json").unwrap();
let base_url = Url::parse("https://fallback.net/")?;
let source_map = SourceMap::from_headers(base_url, headers)?.unwrap();
@ -139,7 +141,9 @@ mod test {
);
let mut headers = Headers::new();
headers.insert(SOURCE_MAP, "https://example.com/test.json");
headers
.insert(SOURCE_MAP, "https://example.com/test.json")
.unwrap();
let base_url = Url::parse("https://fallback.net/")?;
let source_map = SourceMap::from_headers(base_url, headers)?.unwrap();

View File

@ -567,7 +567,7 @@ mod tests {
#[test]
fn bad_parse_from_headers() -> Result<()> {
let mut response = Response::new(200);
response.append_header("forwarded", "uh oh");
response.append_header("forwarded", "uh oh").unwrap();
assert_eq!(
Forwarded::from_headers(&response).unwrap_err().to_string(),
"unable to parse forwarded header: parse error in forwarded-pair"
@ -581,9 +581,13 @@ mod tests {
#[test]
fn from_x_headers() -> Result<()> {
let mut request = Request::new(Get, Url::parse("http://_/")?);
request.append_header(X_FORWARDED_FOR, "192.0.2.43, 2001:db8:cafe::17");
request.append_header(X_FORWARDED_PROTO, "gopher");
request.append_header(X_FORWARDED_HOST, "example.com");
request
.append_header(X_FORWARDED_FOR, "192.0.2.43, 2001:db8:cafe::17")
.unwrap();
request.append_header(X_FORWARDED_PROTO, "gopher").unwrap();
request
.append_header(X_FORWARDED_HOST, "example.com")
.unwrap();
let forwarded = Forwarded::from_headers(&request)?.unwrap();
assert_eq!(
forwarded.to_string(),
@ -632,7 +636,7 @@ mod tests {
#[test]
fn from_request() -> Result<()> {
let mut request = Request::new(Get, Url::parse("http://_/")?);
request.append_header("Forwarded", "for=for");
request.append_header("Forwarded", "for=for").unwrap();
let forwarded = Forwarded::from_headers(&request)?.unwrap();
assert_eq!(forwarded.forwarded_for(), vec!["for"]);
@ -644,7 +648,9 @@ mod tests {
fn owned_can_outlive_request() -> Result<()> {
let forwarded = {
let mut request = Request::new(Get, Url::parse("http://_/")?);
request.append_header("Forwarded", "for=for;by=by;host=host;proto=proto");
request
.append_header("Forwarded", "for=for;by=by;host=host;proto=proto")
.unwrap();
Forwarded::from_headers(&request)?.unwrap().into_owned()
};
assert_eq!(forwarded.by(), Some("by"));

View File

@ -440,7 +440,7 @@ impl Request {
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> Option<HeaderValues> {
) -> crate::Result<Option<HeaderValues>> {
self.headers.insert(name, values)
}
@ -462,7 +462,11 @@ impl Request {
/// #
/// # Ok(()) }
/// ```
pub fn append_header(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
pub fn append_header(
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<()> {
self.headers.append(name, values)
}
@ -472,7 +476,7 @@ impl Request {
let value: HeaderValue = mime.into();
// A Mime instance is guaranteed to be valid header name.
self.insert_header(CONTENT_TYPE, value)
self.insert_header(CONTENT_TYPE, value).unwrap()
}
/// Copy MIME data from the body.
@ -1025,14 +1029,16 @@ mod tests {
#[test]
fn when_only_one_x_forwarded_hosts_exist() {
let mut request = build_test_request();
request.insert_header("x-forwarded-host", "expected.host");
request
.insert_header("x-forwarded-host", "expected.host")
.unwrap();
assert_eq!(request.host(), Some("expected.host"));
}
#[test]
fn when_host_header_is_set() {
let mut request = build_test_request();
request.insert_header("host", "host.header");
request.insert_header("host", "host.header").unwrap();
assert_eq!(request.host(), Some("host.header"));
}
@ -1132,7 +1138,9 @@ mod tests {
"127.0.0.1:8000".parse::<std::net::SocketAddr>().unwrap(),
));
request.insert_header("Forwarded", "this is an improperly ;;; formatted header");
request
.insert_header("Forwarded", "this is an improperly ;;; formatted header")
.unwrap();
assert_eq!(request.forwarded_for(), None);
assert_eq!(request.remote(), Some("127.0.0.1:8000"));
@ -1184,23 +1192,29 @@ mod tests {
}
fn set_x_forwarded_for(request: &mut Request, client: &'static str) {
request.insert_header(
"x-forwarded-for",
format!("{},proxy.com,other-proxy.com", client),
);
request
.insert_header(
"x-forwarded-for",
format!("{},proxy.com,other-proxy.com", client),
)
.unwrap();
}
fn set_x_forwarded_host(request: &mut Request, host: &'static str) {
request.insert_header(
"x-forwarded-host",
format!("{},proxy.com,other-proxy.com", host),
);
request
.insert_header(
"x-forwarded-host",
format!("{},proxy.com,other-proxy.com", host),
)
.unwrap();
}
fn set_forwarded(request: &mut Request, client: &'static str) {
request.insert_header(
"Forwarded",
format!("by=something.com;for={};host=host.com;proto=http", client),
);
request
.insert_header(
"Forwarded",
format!("by=something.com;for={};host=host.com;proto=http", client),
)
.unwrap();
}
}

View File

@ -119,7 +119,7 @@ impl Response {
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> Option<HeaderValues> {
) -> crate::Result<Option<HeaderValues>> {
self.headers.insert(name, values)
}
@ -141,7 +141,11 @@ impl Response {
/// #
/// # Ok(()) }
/// ```
pub fn append_header(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
pub fn append_header(
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<()> {
self.headers.append(name, values)
}
@ -377,7 +381,7 @@ impl Response {
let value: HeaderValue = mime.into();
// A Mime instance is guaranteed to be valid header name.
self.insert_header(CONTENT_TYPE, value)
self.insert_header(CONTENT_TYPE, value).unwrap()
}
/// Copy MIME data from the body.

View File

@ -361,6 +361,6 @@ impl ContentSecurityPolicy {
} else {
"Content-Security-Policy"
};
headers.as_mut().insert(name, self.value());
headers.as_mut().insert(name, self.value()).unwrap();
}
}

View File

@ -62,7 +62,11 @@ pub fn default(mut headers: impl AsMut<Headers>) {
// /// ```
#[inline]
pub fn dns_prefetch_control(mut headers: impl AsMut<Headers>) {
headers.as_mut().insert("X-DNS-Prefetch-Control", "on");
// This will never fail, could use an unsafe version of insert.
headers
.as_mut()
.insert("X-DNS-Prefetch-Control", "on")
.unwrap();
}
/// Set the frameguard level.
@ -92,7 +96,8 @@ pub fn frameguard(mut headers: impl AsMut<Headers>, guard: Option<FrameOptions>)
None | Some(FrameOptions::SameOrigin) => "sameorigin",
Some(FrameOptions::Deny) => "deny",
};
headers.as_mut().insert("X-Frame-Options", kind);
// This will never fail, could use an unsafe version of insert.
headers.as_mut().insert("X-Frame-Options", kind).unwrap();
}
/// Removes the `X-Powered-By` header to make it slightly harder for attackers to see what
@ -114,7 +119,8 @@ pub fn powered_by(mut headers: impl AsMut<Headers>, value: Option<HeaderValue>)
let name = HeaderName::from_lowercase_str("X-Powered-By");
match value {
Some(value) => {
headers.as_mut().insert(name, value);
// Can never fail as value is already a HeaderValue, could use unsafe version of insert
headers.as_mut().insert(name, value).unwrap();
}
None => {
headers.as_mut().remove(name);
@ -139,9 +145,11 @@ pub fn powered_by(mut headers: impl AsMut<Headers>, value: Option<HeaderValue>)
// /// ```
#[inline]
pub fn hsts(mut headers: impl AsMut<Headers>) {
// Never fails, could use unsafe version of insert
headers
.as_mut()
.insert("Strict-Transport-Security", "max-age=5184000");
.insert("Strict-Transport-Security", "max-age=5184000")
.unwrap();
}
/// Prevent browsers from trying to guess (“sniff”) the MIME type, which can have security
@ -159,7 +167,11 @@ pub fn hsts(mut headers: impl AsMut<Headers>) {
// /// ```
#[inline]
pub fn nosniff(mut headers: impl AsMut<Headers>) {
headers.as_mut().insert("X-Content-Type-Options", "nosniff");
// Never fails, could use unsafe verison of insert.
headers
.as_mut()
.insert("X-Content-Type-Options", "nosniff")
.unwrap();
}
/// Sets the `X-XSS-Protection` header to prevent reflected XSS attacks.
@ -176,7 +188,11 @@ pub fn nosniff(mut headers: impl AsMut<Headers>) {
// /// ```
#[inline]
pub fn xss_filter(mut headers: impl AsMut<Headers>) {
headers.as_mut().insert("X-XSS-Protection", "1; mode=block");
// Never fails, could use unsafe version of insert.
headers
.as_mut()
.insert("X-XSS-Protection", "1; mode=block")
.unwrap();
}
/// Set the Referrer-Policy level
@ -232,5 +248,6 @@ pub fn referrer_policy(mut headers: impl AsMut<Headers>, referrer: Option<Referr
// We MUST allow for multiple Referrer-Policy headers to be set.
// See: https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values example #13
headers.as_mut().append("Referrer-Policy", policy);
// Never fails, could use unsafe version of append.
headers.as_mut().append("Referrer-Policy", policy).unwrap();
}

View File

@ -296,7 +296,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(TIMING_ALLOW_ORIGIN, "server; <nori ate your param omnom>");
headers
.insert(TIMING_ALLOW_ORIGIN, "server; <nori ate your param omnom>")
.unwrap();
let err = TimingAllowOrigin::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -250,7 +250,9 @@ mod test {
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(SERVER_TIMING, "server; <nori ate your param omnom>");
headers
.insert(SERVER_TIMING, "server; <nori ate your param omnom>")
.unwrap();
let err = ServerTiming::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}

View File

@ -223,7 +223,7 @@ mod test {
#[test]
fn default() -> crate::Result<()> {
let mut headers = crate::headers::Headers::new();
headers.insert(TRACEPARENT, "00-01-deadbeef-00");
headers.insert(TRACEPARENT, "00-01-deadbeef-00").unwrap();
let context = TraceContext::from_headers(&mut headers)?.unwrap();
assert_eq!(context.version(), 0);
assert_eq!(context.trace_id(), 1);
@ -245,7 +245,7 @@ mod test {
#[test]
fn not_sampled() -> crate::Result<()> {
let mut headers = crate::headers::Headers::new();
headers.insert(TRACEPARENT, "00-01-02-00");
headers.insert(TRACEPARENT, "00-01-02-00").unwrap();
let context = TraceContext::from_headers(&mut headers)?.unwrap();
assert!(!context.sampled());
Ok(())
@ -254,7 +254,7 @@ mod test {
#[test]
fn sampled() -> crate::Result<()> {
let mut headers = crate::headers::Headers::new();
headers.insert(TRACEPARENT, "00-01-02-01");
headers.insert(TRACEPARENT, "00-01-02-01").unwrap();
let context = TraceContext::from_headers(&mut headers)?.unwrap();
assert!(context.sampled());
Ok(())

View File

@ -91,7 +91,7 @@ impl Trailers {
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> Option<HeaderValues> {
) -> crate::Result<Option<HeaderValues>> {
self.headers.insert(name, values)
}
@ -112,7 +112,11 @@ impl Trailers {
/// #
/// # Ok(()) }
/// ```
pub fn append(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
pub fn append(
&mut self,
name: impl Into<HeaderName>,
values: impl ToHeaderValues,
) -> crate::Result<()> {
self.headers.append(name, values)
}