mirror of
https://github.com/yuzu-emu/liftinstall
synced 2024-11-23 13:43:40 +00:00
Update packages, use async client for downloading config
While this has a hell of a lot more boilerplate, this is quite a bit cleaner.
This commit is contained in:
parent
a447ef25b6
commit
4d50a0f8f8
5 changed files with 542 additions and 477 deletions
918
Cargo.lock
generated
918
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ use std::sync::{Arc, RwLock};
|
|||
use installer::InstallerFramework;
|
||||
use logging::LoggingErrors;
|
||||
|
||||
mod rest;
|
||||
pub mod rest;
|
||||
mod ui;
|
||||
|
||||
/// Launches the main web server + UI. Returns when the framework has been consumed + web UI closed.
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
//! Contains the main web server used within the application.
|
||||
|
||||
pub mod server;
|
||||
mod services;
|
||||
pub mod services;
|
||||
|
|
|
@ -4,21 +4,22 @@
|
|||
//!
|
||||
//! This endpoint should be usable directly from a <script> tag during loading.
|
||||
|
||||
use frontend::rest::services::default_future;
|
||||
use frontend::rest::services::Future;
|
||||
use frontend::rest::services::Request;
|
||||
use frontend::rest::services::Response;
|
||||
use frontend::rest::services::WebService;
|
||||
|
||||
use hyper::header::{ContentLength, ContentType};
|
||||
use hyper::StatusCode;
|
||||
|
||||
use logging::LoggingErrors;
|
||||
|
||||
use http;
|
||||
|
||||
use config::Config;
|
||||
|
||||
use http::build_async_client;
|
||||
|
||||
use futures::stream::Stream;
|
||||
use futures::Future as _;
|
||||
|
||||
pub fn handle(service: &WebService, _req: Request) -> Future {
|
||||
let framework_url = {
|
||||
service
|
||||
|
@ -30,45 +31,54 @@ pub fn handle(service: &WebService, _req: Request) -> Future {
|
|||
|
||||
info!("Downloading configuration from {:?}...", framework_url);
|
||||
|
||||
default_future(
|
||||
match http::download_text(&framework_url).map(|x| Config::from_toml_str(&x)) {
|
||||
Ok(Ok(config)) => {
|
||||
service.get_framework_write().config = Some(config.clone());
|
||||
let framework = service.framework.clone();
|
||||
|
||||
// Hyper doesn't allow for clients to do sync network operations in a async future.
|
||||
// This smallish pipeline joins the two together.
|
||||
Box::new(
|
||||
build_async_client()
|
||||
.log_expect("Failed to build async client")
|
||||
.get(&framework_url)
|
||||
.send()
|
||||
.map_err(|x| {
|
||||
error!("HTTP error while downloading configuration file: {:?}", x);
|
||||
hyper::Error::Incomplete
|
||||
})
|
||||
.and_then(|x| {
|
||||
x.into_body().concat2().map_err(|x| {
|
||||
error!("HTTP error while parsing configuration file: {:?}", x);
|
||||
hyper::Error::Incomplete
|
||||
})
|
||||
})
|
||||
.and_then(move |x| {
|
||||
let x = String::from_utf8(x.to_vec()).map_err(|x| {
|
||||
error!("UTF-8 error while parsing configuration file: {:?}", x);
|
||||
hyper::Error::Incomplete
|
||||
})?;
|
||||
|
||||
let config = Config::from_toml_str(&x).map_err(|x| {
|
||||
error!("Serde error while parsing configuration file: {:?}", x);
|
||||
hyper::Error::Incomplete
|
||||
})?;
|
||||
|
||||
let mut framework = framework
|
||||
.write()
|
||||
.log_expect("Failed to get write lock for framework");
|
||||
|
||||
framework.config = Some(config);
|
||||
|
||||
info!("Configuration file downloaded successfully.");
|
||||
|
||||
let file = service
|
||||
.get_framework_read()
|
||||
let file = framework
|
||||
.get_config()
|
||||
.log_expect("Config should be loaded by now")
|
||||
.to_json_str()
|
||||
.log_expect("Failed to render JSON representation of config");
|
||||
|
||||
Response::new()
|
||||
Ok(Response::new()
|
||||
.with_header(ContentLength(file.len() as u64))
|
||||
.with_header(ContentType::json())
|
||||
.with_body(file)
|
||||
}
|
||||
Ok(Err(v)) => {
|
||||
error!("Bad configuration file: {:?}", v);
|
||||
|
||||
Response::new()
|
||||
.with_status(StatusCode::ServiceUnavailable)
|
||||
.with_header(ContentType::plaintext())
|
||||
.with_body("Bad HTTP response")
|
||||
}
|
||||
Err(v) => {
|
||||
error!(
|
||||
"General connectivity error while downloading config: {:?}",
|
||||
v
|
||||
);
|
||||
|
||||
Response::new()
|
||||
.with_status(StatusCode::ServiceUnavailable)
|
||||
.with_header(ContentLength(v.len() as u64))
|
||||
.with_header(ContentType::plaintext())
|
||||
.with_body(v)
|
||||
}
|
||||
},
|
||||
.with_body(file))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
19
src/http.rs
19
src/http.rs
|
@ -7,6 +7,7 @@ use reqwest::header::CONTENT_LENGTH;
|
|||
use std::io::Read;
|
||||
use std::time::Duration;
|
||||
|
||||
use reqwest::async::Client as AsyncClient;
|
||||
use reqwest::Client;
|
||||
|
||||
/// Asserts that a URL is valid HTTPS, else returns an error.
|
||||
|
@ -26,18 +27,12 @@ pub fn build_client() -> Result<Client, String> {
|
|||
.map_err(|x| format!("Unable to build client: {:?}", x))
|
||||
}
|
||||
|
||||
/// Downloads a text file from the specified URL.
|
||||
pub fn download_text(url: &str) -> Result<String, String> {
|
||||
assert_ssl(url)?;
|
||||
|
||||
let mut client = build_client()?
|
||||
.get(url)
|
||||
.send()
|
||||
.map_err(|x| format!("Failed to GET resource: {:?}", x))?;
|
||||
|
||||
client
|
||||
.text()
|
||||
.map_err(|v| format!("Failed to get text from resource: {:?}", v))
|
||||
/// Builds a customised async HTTP client.
|
||||
pub fn build_async_client() -> Result<AsyncClient, String> {
|
||||
AsyncClient::builder()
|
||||
.timeout(Duration::from_secs(8))
|
||||
.build()
|
||||
.map_err(|x| format!("Unable to build client: {:?}", x))
|
||||
}
|
||||
|
||||
/// Streams a file from a HTTP server.
|
||||
|
|
Loading…
Reference in a new issue