Created
June 17, 2020 21:51
-
-
Save rvolosatovs/7699e96db7f33b84011c9de11ce6b636 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTE: Adapted from https://github.com/rust-syndication/syndication/blob/fb9820a3bb7d3d3d9832c1e3b976ce59b0f0a98c/src/lib.rs#L3-L21. | |
#[derive(Debug)] | |
pub enum Feed { | |
Atom(atom::Feed), | |
RSS(rss::Channel), | |
} | |
#[derive(Error, Debug)] | |
#[error("failed to parse XML as either Atom or RSS feed")] | |
pub struct FromStrError; | |
impl FromStr for Feed { | |
type Err = FromStrError; | |
fn from_str(s: &str) -> Result<Self, Self::Err> { | |
match atom_syndication::Feed::from_str(s) { | |
Ok(feed) => Ok(Feed::Atom(feed)), | |
_ => match rss::Channel::from_str(s) { | |
Ok(feed) => Ok(Feed::RSS(feed)), | |
_ => Err(FromStrError), | |
}, | |
} | |
} | |
} | |
#[derive(Error, Debug)] | |
pub enum FromURLError { | |
#[error("HTTP request failed")] | |
Reqwest(#[from] reqwest::Error), | |
#[error("failed to parse request body")] | |
Parse(#[from] FromStrError), | |
} | |
struct FeedFromHTTP<'a> { | |
pub feed: Feed, | |
pub etag: Option<&'a str>, | |
pub last_modified: Option<time::OffsetDateTime>, | |
} | |
fn parse_header<T, N, E, F>(headers: &HeaderMap, name: N, parse: F) -> Option<T> | |
where | |
N: AsHeaderName + std::fmt::Display, | |
E: Sized + std::fmt::Display, | |
F: FnOnce(&HeaderValue) -> Result<T, E>, | |
{ | |
match headers.get(name).map(parse)? { | |
Ok(v) => Some(v), | |
Err(e) => { | |
error!("Failed to parse `{}` header: {}", name, e); | |
None | |
} | |
} | |
} | |
impl Feed { | |
pub async fn from_url<'a, T: reqwest::IntoUrl>( | |
url: T, | |
) -> Result<FeedFromHTTP<'a>, FromURLError> { | |
let resp = reqwest::get(url).await?; | |
let feed = resp.text().await?.parse::<Self>()?; | |
let headers = resp.headers(); | |
Ok(FeedFromHTTP { | |
feed, | |
etag: parse_header(headers, "ETag", HeaderValue::to_str), | |
//last_modified: parse_header(headers, "Last-Modified"), | |
last_modified: None, | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Fails with: