/// `Range` header, defined in [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1) /// /// The "Range" header field on a GET request modifies the method /// semantics to request transfer of only one or more subranges of the /// selected representation data, rather than the entire selected /// representation data. /// /// # ABNF /// /// ```text /// Range = byte-ranges-specifier / other-ranges-specifier /// other-ranges-specifier = other-range-unit "=" other-range-set /// other-range-set = 1*VCHAR /// /// bytes-unit = "bytes" /// /// byte-ranges-specifier = bytes-unit "=" byte-range-set /// byte-range-set = 1#(byte-range-spec / suffix-byte-range-spec) /// byte-range-spec = first-byte-pos "-" [last-byte-pos] /// first-byte-pos = 1*DIGIT /// last-byte-pos = 1*DIGIT /// ``` /// /// # Example values /// /// * `bytes=1000-` /// * `bytes=-2000` /// * `bytes=0-1,30-40` /// * `bytes=0-10,20-90,-100` /// /// # Examples /// /// ``` /// # extern crate headers; /// use headers::Range; /// /// /// let range = Range::bytes(0..1234).unwrap(); /// ``` #[derive(Clone, Debug, PartialEq)] pubstruct Range(::HeaderValue);
error_type!(InvalidRange);
impl Range { /// Creates a `Range` header from bounds. pubfn bytes(bounds: impl RangeBounds<u64>) -> Result<Self, InvalidRange> { let v = match (bounds.start_bound(), bounds.end_bound()) {
(Bound::Unbounded, Bound::Included(end)) => format!("bytes=-{}", end),
(Bound::Unbounded, Bound::Excluded(&end)) => format!("bytes=-{}", end - 1),
(Bound::Included(start), Bound::Included(end)) => format!("bytes={}-{}", start, end),
(Bound::Included(start), Bound::Excluded(&end)) => {
format!("bytes={}-{}", start, end - 1)
}
(Bound::Included(start), Bound::Unbounded) => format!("bytes={}-", start),
_ => return Err(InvalidRange { _inner: () }),
};
Ok(Range(::HeaderValue::from_str(&v).unwrap()))
}
/// Iterate the range sets as a tuple of bounds. pubfn iter<'a>(&'a self) -> impl Iterator<Item = (Bound<u64>, Bound<u64>)> + 'a { let s = self
.0
.to_str()
.expect("valid string checked in Header::decode()");
implByteRangeSpec{ /// Given the full length of the entity, attempt to normalize the byte range /// into an satisfiable end-inclusive (from, to) range. /// /// The resulting range is guaranteed to be a satisfiable range within the bounds /// of `0 <= from <= to < full_length`. /// /// If the byte range is deemed unsatisfiable, `None` is returned. /// An unsatisfiable range is generally cause for a server to either reject /// the client request with a `416 Range Not Satisfiable` status code, or to /// simply ignore the range header and serve the full entity using a `200 OK` /// status code. /// /// This function closely follows [RFC 7233][1] section 2.1. /// As such, it considers ranges to be satisfiable if they meet the following /// conditions: /// /// > If a valid byte-range-set includes at least one byte-range-spec with /// a first-byte-pos that is less than the current length of the /// representation, or at least one suffix-byte-range-spec with a /// non-zero suffix-length, then the byte-range-set is satisfiable. /// Otherwise, the byte-range-set is unsatisfiable. /// /// The function also computes remainder ranges based on the RFC: /// /// > If the last-byte-pos value is /// absent, or if the value is greater than or equal to the current /// length of the representation data, the byte range is interpreted as /// the remainder of the representation (i.e., the server replaces the /// value of last-byte-pos with a value that is one less than the current /// length of the selected representation). /// /// [1]: https://tools.ietf.org/html/rfc7233 pubfnto_satisfiable_range(&self,full_length:u64)->Option<(u64,u64)>{ // If the full length is zero, there is no satisfiable end-inclusive range. iffull_length==0{ returnNone; } matchself{ &ByteRangeSpec::FromTo(from,to)=>{ iffrom<full_length&&from<=to{ Some((from,::std::cmp::min(to,full_length-1))) }else{ None } }, &ByteRangeSpec::AllFrom(from)=>{ iffrom<full_length{ Some((from,full_length-1)) }else{ None } }, &ByteRangeSpec::Last(last)=>{ iflast>0{ // From the RFC: If the selected representation is shorter // than the specified suffix-length, // the entire representation is used. iflast>full_length{ Some((0,full_length-1)) }else{ Some((full_length-last,full_length-1)) } }else{ None } } } } }
implRange{ /// Get the most common byte range header ("bytes=from-to") pubfnbytes(from:u64,to:u64)->Range{ Range::Bytes(vec![ByteRangeSpec::FromTo(from,to)]) }
/// Get byte range header with multiple subranges /// ("bytes=from1-to1,from2-to2,fromX-toX") pubfnbytes_multi(ranges:Vec<(u64,u64)>)->Range{ Range::Bytes(ranges.iter().map(|r|ByteRangeSpec::FromTo(r.0,r.1)).collect()) } }
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.