headers/common/range.rs
1use std::ops::{Bound, RangeBounds};
2
3/// `Range` header, defined in [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1)
4///
5/// The "Range" header field on a GET request modifies the method
6/// semantics to request transfer of only one or more subranges of the
7/// selected representation data, rather than the entire selected
8/// representation data.
9///
10/// # ABNF
11///
12/// ```text
13/// Range = byte-ranges-specifier / other-ranges-specifier
14/// other-ranges-specifier = other-range-unit "=" other-range-set
15/// other-range-set = 1*VCHAR
16///
17/// bytes-unit = "bytes"
18///
19/// byte-ranges-specifier = bytes-unit "=" byte-range-set
20/// byte-range-set = 1#(byte-range-spec / suffix-byte-range-spec)
21/// byte-range-spec = first-byte-pos "-" [last-byte-pos]
22/// first-byte-pos = 1*DIGIT
23/// last-byte-pos = 1*DIGIT
24/// ```
25///
26/// # Example values
27///
28/// * `bytes=1000-`
29/// * `bytes=-2000`
30/// * `bytes=0-1,30-40`
31/// * `bytes=0-10,20-90,-100`
32///
33/// # Examples
34///
35/// ```
36/// # extern crate headers;
37/// use headers::Range;
38///
39///
40/// let range = Range::bytes(0..1234).unwrap();
41/// ```
42#[derive(Clone, Debug, PartialEq)]
43pub struct Range(::HeaderValue);
44
45error_type!(InvalidRange);
46
47impl Range {
48 /// Creates a `Range` header from bounds.
49 pub fn bytes(bounds: impl RangeBounds<u64>) -> Result<Self, InvalidRange> {
50 let v = match (bounds.start_bound(), bounds.end_bound()) {
51 (Bound::Included(start), Bound::Included(end)) => format!("bytes={}-{}", start, end),
52 (Bound::Included(start), Bound::Excluded(&end)) => {
53 format!("bytes={}-{}", start, end - 1)
54 }
55 (Bound::Included(start), Bound::Unbounded) => format!("bytes={}-", start),
56 // These do not directly translate.
57 //(Bound::Unbounded, Bound::Included(end)) => format!("bytes=-{}", end),
58 //(Bound::Unbounded, Bound::Excluded(&end)) => format!("bytes=-{}", end - 1),
59 _ => return Err(InvalidRange { _inner: () }),
60 };
61
62 Ok(Range(::HeaderValue::from_str(&v).unwrap()))
63 }
64
65 /// Iterate the range sets as a tuple of bounds, if valid with length.
66 ///
67 /// The length of the content is passed as an argument, and all ranges
68 /// that can be satisfied will be iterated.
69 pub fn satisfiable_ranges<'a>(
70 &'a self,
71 len: u64,
72 ) -> impl Iterator<Item = (Bound<u64>, Bound<u64>)> + 'a {
73 let s = self
74 .0
75 .to_str()
76 .expect("valid string checked in Header::decode()");
77
78 s["bytes=".len()..].split(',').filter_map(move |spec| {
79 let mut iter = spec.trim().splitn(2, '-');
80 let start = parse_bound(iter.next()?)?;
81 let end = parse_bound(iter.next()?)?;
82
83 // Unbounded ranges in HTTP are actually a suffix
84 // For example, `-100` means the last 100 bytes.
85 if let Bound::Unbounded = start {
86 if let Bound::Included(end) = end {
87 if len < end {
88 // Last N bytes is larger than available!
89 return None;
90 }
91 return Some((Bound::Included(len - end), Bound::Unbounded));
92 }
93 // else fall through
94 }
95
96 Some((start, end))
97 })
98 }
99}
100
101fn parse_bound(s: &str) -> Option<Bound<u64>> {
102 if s.is_empty() {
103 return Some(Bound::Unbounded);
104 }
105
106 s.parse().ok().map(Bound::Included)
107}
108
109impl ::Header for Range {
110 fn name() -> &'static ::HeaderName {
111 &::http::header::RANGE
112 }
113
114 fn decode<'i, I: Iterator<Item = &'i ::HeaderValue>>(values: &mut I) -> Result<Self, ::Error> {
115 values
116 .next()
117 .and_then(|val| {
118 if val.to_str().ok()?.starts_with("bytes=") {
119 Some(Range(val.clone()))
120 } else {
121 None
122 }
123 })
124 .ok_or_else(::Error::invalid)
125 }
126
127 fn encode<E: Extend<::HeaderValue>>(&self, values: &mut E) {
128 values.extend(::std::iter::once(self.0.clone()));
129 }
130}
131
132/*
133
134impl ByteRangeSpec {
135 /// Given the full length of the entity, attempt to normalize the byte range
136 /// into an satisfiable end-inclusive (from, to) range.
137 ///
138 /// The resulting range is guaranteed to be a satisfiable range within the bounds
139 /// of `0 <= from <= to < full_length`.
140 ///
141 /// If the byte range is deemed unsatisfiable, `None` is returned.
142 /// An unsatisfiable range is generally cause for a server to either reject
143 /// the client request with a `416 Range Not Satisfiable` status code, or to
144 /// simply ignore the range header and serve the full entity using a `200 OK`
145 /// status code.
146 ///
147 /// This function closely follows [RFC 7233][1] section 2.1.
148 /// As such, it considers ranges to be satisfiable if they meet the following
149 /// conditions:
150 ///
151 /// > If a valid byte-range-set includes at least one byte-range-spec with
152 /// a first-byte-pos that is less than the current length of the
153 /// representation, or at least one suffix-byte-range-spec with a
154 /// non-zero suffix-length, then the byte-range-set is satisfiable.
155 /// Otherwise, the byte-range-set is unsatisfiable.
156 ///
157 /// The function also computes remainder ranges based on the RFC:
158 ///
159 /// > If the last-byte-pos value is
160 /// absent, or if the value is greater than or equal to the current
161 /// length of the representation data, the byte range is interpreted as
162 /// the remainder of the representation (i.e., the server replaces the
163 /// value of last-byte-pos with a value that is one less than the current
164 /// length of the selected representation).
165 ///
166 /// [1]: https://tools.ietf.org/html/rfc7233
167 pub fn to_satisfiable_range(&self, full_length: u64) -> Option<(u64, u64)> {
168 // If the full length is zero, there is no satisfiable end-inclusive range.
169 if full_length == 0 {
170 return None;
171 }
172 match self {
173 &ByteRangeSpec::FromTo(from, to) => {
174 if from < full_length && from <= to {
175 Some((from, ::std::cmp::min(to, full_length - 1)))
176 } else {
177 None
178 }
179 },
180 &ByteRangeSpec::AllFrom(from) => {
181 if from < full_length {
182 Some((from, full_length - 1))
183 } else {
184 None
185 }
186 },
187 &ByteRangeSpec::Last(last) => {
188 if last > 0 {
189 // From the RFC: If the selected representation is shorter
190 // than the specified suffix-length,
191 // the entire representation is used.
192 if last > full_length {
193 Some((0, full_length - 1))
194 } else {
195 Some((full_length - last, full_length - 1))
196 }
197 } else {
198 None
199 }
200 }
201 }
202 }
203}
204
205impl Range {
206 /// Get the most common byte range header ("bytes=from-to")
207 pub fn bytes(from: u64, to: u64) -> Range {
208 Range::Bytes(vec![ByteRangeSpec::FromTo(from, to)])
209 }
210
211 /// Get byte range header with multiple subranges
212 /// ("bytes=from1-to1,from2-to2,fromX-toX")
213 pub fn bytes_multi(ranges: Vec<(u64, u64)>) -> Range {
214 Range::Bytes(ranges.iter().map(|r| ByteRangeSpec::FromTo(r.0, r.1)).collect())
215 }
216}
217
218
219impl fmt::Display for ByteRangeSpec {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 match *self {
222 ByteRangeSpec::FromTo(from, to) => write!(f, "{}-{}", from, to),
223 ByteRangeSpec::Last(pos) => write!(f, "-{}", pos),
224 ByteRangeSpec::AllFrom(pos) => write!(f, "{}-", pos),
225 }
226 }
227}
228
229
230impl fmt::Display for Range {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 match *self {
233 Range::Bytes(ref ranges) => {
234 try!(write!(f, "bytes="));
235
236 for (i, range) in ranges.iter().enumerate() {
237 if i != 0 {
238 try!(f.write_str(","));
239 }
240 try!(Display::fmt(range, f));
241 }
242 Ok(())
243 },
244 Range::Unregistered(ref unit, ref range_str) => {
245 write!(f, "{}={}", unit, range_str)
246 },
247 }
248 }
249}
250
251impl FromStr for Range {
252 type Err = ::Error;
253
254 fn from_str(s: &str) -> ::Result<Range> {
255 let mut iter = s.splitn(2, '=');
256
257 match (iter.next(), iter.next()) {
258 (Some("bytes"), Some(ranges)) => {
259 let ranges = from_comma_delimited(ranges);
260 if ranges.is_empty() {
261 return Err(::Error::Header);
262 }
263 Ok(Range::Bytes(ranges))
264 }
265 (Some(unit), Some(range_str)) if unit != "" && range_str != "" => {
266 Ok(Range::Unregistered(unit.to_owned(), range_str.to_owned()))
267
268 },
269 _ => Err(::Error::Header)
270 }
271 }
272}
273
274impl FromStr for ByteRangeSpec {
275 type Err = ::Error;
276
277 fn from_str(s: &str) -> ::Result<ByteRangeSpec> {
278 let mut parts = s.splitn(2, '-');
279
280 match (parts.next(), parts.next()) {
281 (Some(""), Some(end)) => {
282 end.parse().or(Err(::Error::Header)).map(ByteRangeSpec::Last)
283 },
284 (Some(start), Some("")) => {
285 start.parse().or(Err(::Error::Header)).map(ByteRangeSpec::AllFrom)
286 },
287 (Some(start), Some(end)) => {
288 match (start.parse(), end.parse()) {
289 (Ok(start), Ok(end)) if start <= end => Ok(ByteRangeSpec::FromTo(start, end)),
290 _ => Err(::Error::Header)
291 }
292 },
293 _ => Err(::Error::Header)
294 }
295 }
296}
297
298fn from_comma_delimited<T: FromStr>(s: &str) -> Vec<T> {
299 s.split(',')
300 .filter_map(|x| match x.trim() {
301 "" => None,
302 y => Some(y)
303 })
304 .filter_map(|x| x.parse().ok())
305 .collect()
306}
307
308impl Header for Range {
309
310 fn header_name() -> &'static str {
311 static NAME: &'static str = "Range";
312 NAME
313 }
314
315 fn parse_header(raw: &Raw) -> ::Result<Range> {
316 from_one_raw_str(raw)
317 }
318
319 fn fmt_header(&self, f: &mut ::Formatter) -> fmt::Result {
320 f.fmt_line(self)
321 }
322
323}
324
325#[test]
326fn test_parse_bytes_range_valid() {
327 let r: Range = Header::parse_header(&"bytes=1-100".into()).unwrap();
328 let r2: Range = Header::parse_header(&"bytes=1-100,-".into()).unwrap();
329 let r3 = Range::bytes(1, 100);
330 assert_eq!(r, r2);
331 assert_eq!(r2, r3);
332
333 let r: Range = Header::parse_header(&"bytes=1-100,200-".into()).unwrap();
334 let r2: Range = Header::parse_header(&"bytes= 1-100 , 101-xxx, 200- ".into()).unwrap();
335 let r3 = Range::Bytes(
336 vec![ByteRangeSpec::FromTo(1, 100), ByteRangeSpec::AllFrom(200)]
337 );
338 assert_eq!(r, r2);
339 assert_eq!(r2, r3);
340
341 let r: Range = Header::parse_header(&"bytes=1-100,-100".into()).unwrap();
342 let r2: Range = Header::parse_header(&"bytes=1-100, ,,-100".into()).unwrap();
343 let r3 = Range::Bytes(
344 vec![ByteRangeSpec::FromTo(1, 100), ByteRangeSpec::Last(100)]
345 );
346 assert_eq!(r, r2);
347 assert_eq!(r2, r3);
348
349 let r: Range = Header::parse_header(&"custom=1-100,-100".into()).unwrap();
350 let r2 = Range::Unregistered("custom".to_owned(), "1-100,-100".to_owned());
351 assert_eq!(r, r2);
352
353}
354
355#[test]
356fn test_parse_unregistered_range_valid() {
357 let r: Range = Header::parse_header(&"custom=1-100,-100".into()).unwrap();
358 let r2 = Range::Unregistered("custom".to_owned(), "1-100,-100".to_owned());
359 assert_eq!(r, r2);
360
361 let r: Range = Header::parse_header(&"custom=abcd".into()).unwrap();
362 let r2 = Range::Unregistered("custom".to_owned(), "abcd".to_owned());
363 assert_eq!(r, r2);
364
365 let r: Range = Header::parse_header(&"custom=xxx-yyy".into()).unwrap();
366 let r2 = Range::Unregistered("custom".to_owned(), "xxx-yyy".to_owned());
367 assert_eq!(r, r2);
368}
369
370#[test]
371fn test_parse_invalid() {
372 let r: ::Result<Range> = Header::parse_header(&"bytes=1-a,-".into());
373 assert_eq!(r.ok(), None);
374
375 let r: ::Result<Range> = Header::parse_header(&"bytes=1-2-3".into());
376 assert_eq!(r.ok(), None);
377
378 let r: ::Result<Range> = Header::parse_header(&"abc".into());
379 assert_eq!(r.ok(), None);
380
381 let r: ::Result<Range> = Header::parse_header(&"bytes=1-100=".into());
382 assert_eq!(r.ok(), None);
383
384 let r: ::Result<Range> = Header::parse_header(&"bytes=".into());
385 assert_eq!(r.ok(), None);
386
387 let r: ::Result<Range> = Header::parse_header(&"custom=".into());
388 assert_eq!(r.ok(), None);
389
390 let r: ::Result<Range> = Header::parse_header(&"=1-100".into());
391 assert_eq!(r.ok(), None);
392}
393
394#[test]
395fn test_fmt() {
396 use Headers;
397
398 let mut headers = Headers::new();
399
400 headers.set(
401 Range::Bytes(
402 vec![ByteRangeSpec::FromTo(0, 1000), ByteRangeSpec::AllFrom(2000)]
403 ));
404 assert_eq!(&headers.to_string(), "Range: bytes=0-1000,2000-\r\n");
405
406 headers.clear();
407 headers.set(Range::Bytes(vec![]));
408
409 assert_eq!(&headers.to_string(), "Range: bytes=\r\n");
410
411 headers.clear();
412 headers.set(Range::Unregistered("custom".to_owned(), "1-xxx".to_owned()));
413
414 assert_eq!(&headers.to_string(), "Range: custom=1-xxx\r\n");
415}
416
417#[test]
418fn test_byte_range_spec_to_satisfiable_range() {
419 assert_eq!(Some((0, 0)), ByteRangeSpec::FromTo(0, 0).to_satisfiable_range(3));
420 assert_eq!(Some((1, 2)), ByteRangeSpec::FromTo(1, 2).to_satisfiable_range(3));
421 assert_eq!(Some((1, 2)), ByteRangeSpec::FromTo(1, 5).to_satisfiable_range(3));
422 assert_eq!(None, ByteRangeSpec::FromTo(3, 3).to_satisfiable_range(3));
423 assert_eq!(None, ByteRangeSpec::FromTo(2, 1).to_satisfiable_range(3));
424 assert_eq!(None, ByteRangeSpec::FromTo(0, 0).to_satisfiable_range(0));
425
426 assert_eq!(Some((0, 2)), ByteRangeSpec::AllFrom(0).to_satisfiable_range(3));
427 assert_eq!(Some((2, 2)), ByteRangeSpec::AllFrom(2).to_satisfiable_range(3));
428 assert_eq!(None, ByteRangeSpec::AllFrom(3).to_satisfiable_range(3));
429 assert_eq!(None, ByteRangeSpec::AllFrom(5).to_satisfiable_range(3));
430 assert_eq!(None, ByteRangeSpec::AllFrom(0).to_satisfiable_range(0));
431
432 assert_eq!(Some((1, 2)), ByteRangeSpec::Last(2).to_satisfiable_range(3));
433 assert_eq!(Some((2, 2)), ByteRangeSpec::Last(1).to_satisfiable_range(3));
434 assert_eq!(Some((0, 2)), ByteRangeSpec::Last(5).to_satisfiable_range(3));
435 assert_eq!(None, ByteRangeSpec::Last(0).to_satisfiable_range(3));
436 assert_eq!(None, ByteRangeSpec::Last(2).to_satisfiable_range(0));
437}
438
439bench_header!(bytes_multi, Range, { vec![b"bytes=1-1001,2001-3001,10001-".to_vec()]});
440bench_header!(custom_unit, Range, { vec![b"other=0-100000".to_vec()]});
441*/
442
443#[test]
444fn test_to_satisfiable_range_suffix() {
445 let range = super::test_decode::<Range>(&["bytes=-100"]).unwrap();
446 let bounds = range.satisfiable_ranges(350).next().unwrap();
447 assert_eq!(bounds, (Bound::Included(250), Bound::Unbounded));
448}
449
450#[test]
451fn test_to_unsatisfiable_range_suffix() {
452 let range = super::test_decode::<Range>(&["bytes=-350"]).unwrap();
453 let bounds = range.satisfiable_ranges(100).next();
454 assert_eq!(bounds, None);
455}