mirror of
https://github.com/yuzu-emu/liftinstall.git
synced 2024-11-29 15:24:22 +01: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
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 installer::InstallerFramework;
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
mod rest;
|
pub mod rest;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
/// Launches the main web server + UI. Returns when the framework has been consumed + web UI closed.
|
/// 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.
|
//! Contains the main web server used within the application.
|
||||||
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
mod services;
|
pub mod services;
|
||||||
|
@ -4,21 +4,22 @@
|
|||||||
//!
|
//!
|
||||||
//! This endpoint should be usable directly from a <script> tag during loading.
|
//! 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::Future;
|
||||||
use frontend::rest::services::Request;
|
use frontend::rest::services::Request;
|
||||||
use frontend::rest::services::Response;
|
use frontend::rest::services::Response;
|
||||||
use frontend::rest::services::WebService;
|
use frontend::rest::services::WebService;
|
||||||
|
|
||||||
use hyper::header::{ContentLength, ContentType};
|
use hyper::header::{ContentLength, ContentType};
|
||||||
use hyper::StatusCode;
|
|
||||||
|
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
use http;
|
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
|
|
||||||
|
use http::build_async_client;
|
||||||
|
|
||||||
|
use futures::stream::Stream;
|
||||||
|
use futures::Future as _;
|
||||||
|
|
||||||
pub fn handle(service: &WebService, _req: Request) -> Future {
|
pub fn handle(service: &WebService, _req: Request) -> Future {
|
||||||
let framework_url = {
|
let framework_url = {
|
||||||
service
|
service
|
||||||
@ -30,45 +31,54 @@ pub fn handle(service: &WebService, _req: Request) -> Future {
|
|||||||
|
|
||||||
info!("Downloading configuration from {:?}...", framework_url);
|
info!("Downloading configuration from {:?}...", framework_url);
|
||||||
|
|
||||||
default_future(
|
let framework = service.framework.clone();
|
||||||
match http::download_text(&framework_url).map(|x| Config::from_toml_str(&x)) {
|
|
||||||
Ok(Ok(config)) => {
|
// Hyper doesn't allow for clients to do sync network operations in a async future.
|
||||||
service.get_framework_write().config = Some(config.clone());
|
// 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.");
|
info!("Configuration file downloaded successfully.");
|
||||||
|
|
||||||
let file = service
|
let file = framework
|
||||||
.get_framework_read()
|
|
||||||
.get_config()
|
.get_config()
|
||||||
.log_expect("Config should be loaded by now")
|
.log_expect("Config should be loaded by now")
|
||||||
.to_json_str()
|
.to_json_str()
|
||||||
.log_expect("Failed to render JSON representation of config");
|
.log_expect("Failed to render JSON representation of config");
|
||||||
|
|
||||||
Response::new()
|
Ok(Response::new()
|
||||||
.with_header(ContentLength(file.len() as u64))
|
.with_header(ContentLength(file.len() as u64))
|
||||||
.with_header(ContentType::json())
|
.with_header(ContentType::json())
|
||||||
.with_body(file)
|
.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)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
19
src/http.rs
19
src/http.rs
@ -7,6 +7,7 @@ use reqwest::header::CONTENT_LENGTH;
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use reqwest::async::Client as AsyncClient;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
/// Asserts that a URL is valid HTTPS, else returns an error.
|
/// 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))
|
.map_err(|x| format!("Unable to build client: {:?}", x))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Downloads a text file from the specified URL.
|
/// Builds a customised async HTTP client.
|
||||||
pub fn download_text(url: &str) -> Result<String, String> {
|
pub fn build_async_client() -> Result<AsyncClient, String> {
|
||||||
assert_ssl(url)?;
|
AsyncClient::builder()
|
||||||
|
.timeout(Duration::from_secs(8))
|
||||||
let mut client = build_client()?
|
.build()
|
||||||
.get(url)
|
.map_err(|x| format!("Unable to build client: {:?}", x))
|
||||||
.send()
|
|
||||||
.map_err(|x| format!("Failed to GET resource: {:?}", x))?;
|
|
||||||
|
|
||||||
client
|
|
||||||
.text()
|
|
||||||
.map_err(|v| format!("Failed to get text from resource: {:?}", v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Streams a file from a HTTP server.
|
/// Streams a file from a HTTP server.
|
||||||
|
Loading…
Reference in New Issue
Block a user