Skip to content

Commit 5780f55

Browse files
committed
Return Result<Option<Self>> from ServerTiming::from_headers
1 parent 553dcaf commit 5780f55

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

src/trace/server_timing/mod.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! let mut res = Response::new(200);
1515
//! timings.apply(&mut res);
1616
//!
17-
//! let timings = ServerTiming::from_headers(res).unwrap();
17+
//! let timings = ServerTiming::from_headers(res)?.unwrap();
1818
//! let entry = timings.iter().next().unwrap();
1919
//! assert_eq!(entry.name(), "server");
2020
//! #
@@ -56,7 +56,7 @@ use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, SERVER_TI
5656
/// let mut res = Response::new(200);
5757
/// timings.apply(&mut res);
5858
///
59-
/// let timings = ServerTiming::from_headers(res).unwrap();
59+
/// let timings = ServerTiming::from_headers(res)?.unwrap();
6060
/// let entry = timings.iter().next().unwrap();
6161
/// assert_eq!(entry.name(), "server");
6262
/// #
@@ -74,12 +74,17 @@ impl ServerTiming {
7474
}
7575

7676
/// Create a new instance from headers.
77-
pub fn from_headers(headers: impl AsRef<Headers>) -> Option<Self> {
77+
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
7878
let mut timings = vec![];
79-
for value in headers.as_ref().get(SERVER_TIMING)? {
80-
parse_header(value.as_str(), &mut timings).ok()?;
79+
let headers = match headers.as_ref().get(SERVER_TIMING) {
80+
Some(headers) => headers,
81+
None => return Ok(None),
82+
};
83+
84+
for value in headers {
85+
parse_header(value.as_str(), &mut timings)?;
8186
}
82-
Some(Self { timings })
87+
Ok(Some(Self { timings }))
8388
}
8489

8590
/// Sets the `Server-Timing` header.
@@ -102,6 +107,8 @@ impl ServerTiming {
102107
_ => write!(output, ", {}", timing).unwrap(),
103108
};
104109
}
110+
111+
// SAFETY: the internal string is validated to be ASCII.
105112
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
106113
}
107114

@@ -240,7 +247,7 @@ mod test {
240247
let mut headers = Headers::new();
241248
timings.apply(&mut headers);
242249

243-
let timings = ServerTiming::from_headers(headers).unwrap();
250+
let timings = ServerTiming::from_headers(headers)?.unwrap();
244251
let entry = timings.iter().next().unwrap();
245252
assert_eq!(entry.name(), "server");
246253
Ok(())
@@ -254,9 +261,18 @@ mod test {
254261
let mut headers = Headers::new();
255262
timings.apply(&mut headers);
256263

257-
let timings = ServerTiming::from_headers(headers).unwrap();
264+
let timings = ServerTiming::from_headers(headers)?.unwrap();
258265
let entry = timings.iter().next().unwrap();
259266
assert_eq!(entry.name(), "server");
260267
Ok(())
261268
}
269+
270+
#[test]
271+
fn bad_request_on_parse_error() -> crate::Result<()> {
272+
let mut headers = Headers::new();
273+
headers.insert(SERVER_TIMING, "server; <nori ate your param omnom>");
274+
let err = ServerTiming::from_headers(headers).unwrap_err();
275+
assert_eq!(err.status(), 400);
276+
Ok(())
277+
}
262278
}

src/trace/server_timing/parse.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use std::time::Duration;
22

33
use super::Metric;
4-
use crate::Status;
5-
use crate::{ensure, format_err};
4+
use crate::{ensure, format_err, StatusCode};
65

76
/// Parse multiple entries from a single header.
87
///
98
/// Each entry is comma-delimited.
109
pub(super) fn parse_header(s: &str, entries: &mut Vec<Metric>) -> crate::Result<()> {
1110
for part in s.trim().split(',') {
12-
let entry = parse_entry(part)?;
11+
let entry = parse_entry(part).map_err(|mut e| {
12+
e.set_status(StatusCode::BadRequest);
13+
e
14+
})?;
1315
entries.push(entry);
1416
}
1517
Ok(())
@@ -60,7 +62,7 @@ fn parse_entry(s: &str) -> crate::Result<Metric> {
6062

6163
match name {
6264
"dur" => {
63-
let millis: f64 = value.parse().status(400).map_err(|_| {
65+
let millis: f64 = value.parse().map_err(|_| {
6466
format_err!("Server timing duration params must be a valid double-precision floating-point number.")
6567
})?;
6668
dur = Some(Duration::from_secs_f64(millis / 1000.0));

0 commit comments

Comments
 (0)