Source: On Http 301 response, update Source.uri .

This commit is contained in:
Jordan Petridis 2018-01-23 16:43:02 +02:00
parent 1c4138c166
commit e74a2df27f
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6

View File

@ -4,7 +4,8 @@ use rss::Channel;
use hyper; use hyper;
use hyper::{Client, Method, Request, Response, StatusCode, Uri}; use hyper::{Client, Method, Request, Response, StatusCode, Uri};
use hyper::client::HttpConnector; use hyper::client::HttpConnector;
use hyper::header::{ETag, EntityTag, HttpDate, IfModifiedSince, IfNoneMatch, LastModified}; use hyper::header::{ETag, EntityTag, HttpDate, IfModifiedSince, IfNoneMatch, LastModified,
Location};
use hyper_tls::HttpsConnector; use hyper_tls::HttpsConnector;
// use futures::future::ok; // use futures::future::ok;
@ -42,6 +43,11 @@ impl Source {
&self.uri &self.uri
} }
/// Set the `uri` field value.
pub fn set_uri(&mut self, uri: String) {
self.uri = uri;
}
/// Represents the Http Last-Modified Header field. /// Represents the Http Last-Modified Header field.
/// ///
/// See [RFC 7231](https://tools.ietf.org/html/rfc7231#section-7.2) for more. /// See [RFC 7231](https://tools.ietf.org/html/rfc7231#section-7.2) for more.
@ -72,7 +78,7 @@ impl Source {
let db = connection(); let db = connection();
let con = db.get()?; let con = db.get()?;
Ok(self.save_changes::<Source>(&con)?) self.save_changes::<Source>(&con).map_err(From::from)
} }
/// Extract Etag and LastModifier from res, and update self and the /// Extract Etag and LastModifier from res, and update self and the
@ -92,6 +98,50 @@ impl Source {
Ok(()) Ok(())
} }
// TODO match on more stuff
// 301: Moved Permanently
// 304: Up to date Feed, checked with the Etag
// 307: Temporary redirect of the url
// 308: Permanent redirect of the url
// 401: Unathorized
// 403: Forbidden
// 408: Timeout
// 410: Feed deleted
fn match_status(&mut self, res: &Response) -> Result<()> {
let code = res.status();
match code {
StatusCode::NotModified => bail!("304: skipping.."),
StatusCode::MovedPermanently => {
error!("Feed was moved permanently.");
self.handle_301(res)?;
bail!("301: Feed was moved permanently.")
}
StatusCode::TemporaryRedirect => debug!("307: Temporary Redirect."),
StatusCode::PermanentRedirect => warn!("308: Permanent Redirect."),
StatusCode::Unauthorized => bail!("401: Unauthorized."),
StatusCode::Forbidden => bail!("403: Forbidden."),
StatusCode::NotFound => bail!("404: Not found."),
StatusCode::RequestTimeout => bail!("408: Request Timeout."),
StatusCode::Gone => bail!("410: Feed was deleted."),
_ => info!("HTTP StatusCode: {}", code),
};
Ok(())
}
fn handle_301(&mut self, res: &Response) -> Result<()> {
let headers = res.headers();
if let Some(url) = headers.get::<Location>() {
self.set_uri(url.to_string());
self.save()?;
info!("Feed url was updated succesfully.");
// TODO: Refresh in place instead of next time, Not a priority.
info!("New content will be fetched with the next refesh.");
}
Ok(())
}
/// Construct a new `Source` with the given `uri` and index it. /// Construct a new `Source` with the given `uri` and index it.
/// ///
/// This only indexes the `Source` struct, not the Podcast Feed. /// This only indexes the `Source` struct, not the Podcast Feed.
@ -118,10 +168,7 @@ impl Source {
.map_err(From::from) .map_err(From::from)
.and_then(move |res| { .and_then(move |res| {
self.update_etag(&res)?; self.update_etag(&res)?;
Ok(res) self.match_status(&res)?;
})
.and_then(|res| {
match_status(res.status())?;
Ok(res) Ok(res)
}) })
.and_then(move |res| response_to_channel(res, pool)) .and_then(move |res| response_to_channel(res, pool))
@ -181,34 +228,6 @@ fn response_to_channel(
Box::new(cpu_chan) Box::new(cpu_chan)
} }
// TODO match on more stuff
// 301: Moved Permanently
// 304: Up to date Feed, checked with the Etag
// 307: Temporary redirect of the url
// 308: Permanent redirect of the url
// 401: Unathorized
// 403: Forbidden
// 408: Timeout
// 410: Feed deleted
fn match_status(code: StatusCode) -> Result<()> {
match code {
StatusCode::NotModified => bail!("304: skipping.."),
StatusCode::TemporaryRedirect => debug!("307: Temporary Redirect."),
// TODO: Change the source uri to the new one
StatusCode::MovedPermanently | StatusCode::PermanentRedirect => {
warn!("Feed was moved permanently.");
bail!("308: Feed was moved permanently.")
}
StatusCode::Unauthorized => bail!("401: Unauthorized."),
StatusCode::Forbidden => bail!("403: Forbidden."),
StatusCode::NotFound => bail!("404: Not found."),
StatusCode::RequestTimeout => bail!("408: Request Timeout."),
StatusCode::Gone => bail!("410: Feed was deleted."),
_ => info!("HTTP StatusCode: {}", code),
};
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;