Retry network related stuff if failing
This commit is contained in:
86
src/main.rs
86
src/main.rs
@@ -14,7 +14,7 @@ use std::collections::HashMap;
|
|||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use reqwest::{Client, Response, RedirectPolicy};
|
use reqwest::{Client, Response, RedirectPolicy, RequestBuilder};
|
||||||
use reqwest::header::{Cookie, Charset, SetCookie};
|
use reqwest::header::{Cookie, Charset, SetCookie};
|
||||||
use reqwest::header::{ContentDisposition, DispositionType, DispositionParam};
|
use reqwest::header::{ContentDisposition, DispositionType, DispositionParam};
|
||||||
use zip::ZipArchive;
|
use zip::ZipArchive;
|
||||||
@@ -34,7 +34,8 @@ mod catalogs {
|
|||||||
|
|
||||||
// TODO: use clap for proper CLI
|
// TODO: use clap for proper CLI
|
||||||
// TODO: replace unwraps with descriptive expects
|
// TODO: replace unwraps with descriptive expects
|
||||||
// TODO: retry some things if sensible
|
|
||||||
|
const MAX_RETRIES: u8 = 10;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref CLIENT: Client = {
|
static ref CLIENT: Client = {
|
||||||
@@ -107,10 +108,10 @@ fn get_auth(username: &str, password: &str) -> String {
|
|||||||
form_data.insert("UserName", username);
|
form_data.insert("UserName", username);
|
||||||
form_data.insert("Password", password);
|
form_data.insert("Password", password);
|
||||||
|
|
||||||
let res = CLIENT.post("https://streams.tum.de/Mediasite/Login")
|
let res = try_to_get_response(|client| {
|
||||||
|
client.post("https://streams.tum.de/Mediasite/Login")
|
||||||
.form(&form_data)
|
.form(&form_data)
|
||||||
.send()
|
});
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let set_cookie: &SetCookie = res.headers().get().unwrap();
|
let set_cookie: &SetCookie = res.headers().get().unwrap();
|
||||||
let cookie = cookie::Cookie::parse(set_cookie.0[0].to_string()).unwrap();
|
let cookie = cookie::Cookie::parse(set_cookie.0[0].to_string()).unwrap();
|
||||||
@@ -139,11 +140,9 @@ fn get_catalog_id(name: &str, auth: &str) -> String {
|
|||||||
println!("Fetching catalog id!");
|
println!("Fetching catalog id!");
|
||||||
|
|
||||||
let url = format!("https://streams.tum.de/Mediasite/Catalog/catalogs/{}", name);
|
let url = format!("https://streams.tum.de/Mediasite/Catalog/catalogs/{}", name);
|
||||||
let res = CLIENT.get(&url)
|
let mut res = try_to_get_response(|client| client.get(&url).header(construct_cookie(auth)));
|
||||||
.header(construct_cookie(auth))
|
|
||||||
.send();
|
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
res.unwrap().read_to_string(&mut string).unwrap();
|
res.read_to_string(&mut string).unwrap();
|
||||||
|
|
||||||
let prefix = "CatalogId: '";
|
let prefix = "CatalogId: '";
|
||||||
let idx = string.find(prefix).unwrap();
|
let idx = string.find(prefix).unwrap();
|
||||||
@@ -155,14 +154,15 @@ fn get_catalog_id(name: &str, auth: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn download_presentation(presentation: &Presentation, out_dir: &Path, auth: &str) {
|
fn download_presentation(presentation: &Presentation, out_dir: &Path, auth: &str) {
|
||||||
fn try_download(presentation: &Presentation, auth: &str) -> Option<(Response, String)> {
|
let response =
|
||||||
let response = CLIENT.get(&presentation.download_url)
|
try_to_get_valid_response(|client| {
|
||||||
|
client.get(&presentation.download_url)
|
||||||
.header(construct_cookie(auth))
|
.header(construct_cookie(auth))
|
||||||
.send()
|
},
|
||||||
.unwrap();
|
|resp| resp.headers().get::<ContentDisposition>().is_some());
|
||||||
|
|
||||||
let filename = if let Some(content_disposition) =
|
let filename = {
|
||||||
response.headers().get::<ContentDisposition>() {
|
let content_disposition = response.headers().get::<ContentDisposition>().unwrap();
|
||||||
assert_eq!(content_disposition.disposition, DispositionType::Attachment);
|
assert_eq!(content_disposition.disposition, DispositionType::Attachment);
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
for param in &content_disposition.parameters {
|
for param in &content_disposition.parameters {
|
||||||
@@ -175,31 +175,8 @@ fn download_presentation(presentation: &Presentation, out_dir: &Path, auth: &str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
name.expect("Missing filename in ContentDisposition!")
|
name.expect("Missing filename in ContentDisposition!")
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((response, filename))
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut tries = 0;
|
|
||||||
let mut tuple = None;
|
|
||||||
while tries < 8 {
|
|
||||||
if tries > 0 {
|
|
||||||
println!("Failed to start download! Retrying!");
|
|
||||||
}
|
|
||||||
let try = try_download(presentation, auth);
|
|
||||||
if try.is_some() {
|
|
||||||
tuple = try;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tries += 1;
|
|
||||||
}
|
|
||||||
if tuple.is_none() {
|
|
||||||
panic!("Failed to get a proper response while trying to download presentation!");
|
|
||||||
}
|
|
||||||
let (response, filename) = tuple.unwrap();
|
|
||||||
|
|
||||||
let mut path = PathBuf::from(out_dir);
|
let mut path = PathBuf::from(out_dir);
|
||||||
path.push(fix_filename(&filename));
|
path.push(fix_filename(&filename));
|
||||||
println!("Output file: {:?}", path);
|
println!("Output file: {:?}", path);
|
||||||
@@ -274,12 +251,13 @@ fn get_json(catalog_id: &str, auth: &str) -> String {
|
|||||||
data.insert("CurrentFolderId", catalog_id);
|
data.insert("CurrentFolderId", catalog_id);
|
||||||
data.insert("ItemsPerPage", "500");
|
data.insert("ItemsPerPage", "500");
|
||||||
|
|
||||||
let res = CLIENT.post("https://streams.tum.de/Mediasite/Catalog/Data/GetPresentationsForFolder")
|
let mut res = try_to_get_response(|client| {
|
||||||
|
client.post("https://streams.tum.de/Mediasite/Catalog/Data/GetPresentationsForFolder")
|
||||||
.header(construct_cookie(auth))
|
.header(construct_cookie(auth))
|
||||||
.json(&data)
|
.json(&data)
|
||||||
.send();
|
});
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
res.unwrap().read_to_string(&mut string).unwrap();
|
res.read_to_string(&mut string).unwrap();
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,3 +271,29 @@ fn zip_is_valid(path: &Path) -> bool {
|
|||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
ZipArchive::new(file).is_ok()
|
ZipArchive::new(file).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_to_get_response<F>(f: F) -> Response
|
||||||
|
where F: Fn(&Client) -> RequestBuilder
|
||||||
|
{
|
||||||
|
try_to_get_valid_response(f, |_| true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_to_get_valid_response<F1, F2>(f1: F1, f2: F2) -> Response
|
||||||
|
where F1: Fn(&Client) -> RequestBuilder,
|
||||||
|
F2: Fn(&Response) -> bool
|
||||||
|
{
|
||||||
|
let mut retries = 0;
|
||||||
|
while retries <= MAX_RETRIES {
|
||||||
|
if retries > 0 {
|
||||||
|
println!("Retrying request!");
|
||||||
|
}
|
||||||
|
let response = f1(&*CLIENT).send();
|
||||||
|
if let Ok(response) = response {
|
||||||
|
if f2(&response) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retries += 1;
|
||||||
|
}
|
||||||
|
panic!("Reached maximum amout of retries!")
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user