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