diff --git a/service/src/commands/status.rs b/service/src/commands/status.rs index 5584811bb..36b5fc018 100644 --- a/service/src/commands/status.rs +++ b/service/src/commands/status.rs @@ -20,7 +20,7 @@ use hyper::{Uri, Method, StatusCode}; use colored::*; use crate::store::Store; -use crate::webclient::*; +use crate::httpclient::*; use crate::service::ServiceStatus; use crate::{GlobalFlags, HTTP_API_OBJECT_SIZE_LIMIT}; @@ -48,6 +48,6 @@ pub(crate) async fn run(store: Arc, global_flags: GlobalFlags, client: Ht Ok(0) }, - _ => Err(Box::new(UnexpectedStatusCodeError(res.status()))) + _ => Err(Box::new(UnexpectedStatusCodeError(res.status(), ""))) } } diff --git a/service/src/webclient.rs b/service/src/httpclient.rs similarity index 93% rename from service/src/webclient.rs rename to service/src/httpclient.rs index b602c0cda..07c08396d 100644 --- a/service/src/webclient.rs +++ b/service/src/httpclient.rs @@ -40,13 +40,17 @@ impl std::fmt::Display for IncorrectAuthTokenError { } #[derive(Debug)] -pub(crate) struct UnexpectedStatusCodeError(pub StatusCode); +pub(crate) struct UnexpectedStatusCodeError(pub StatusCode, pub &'static str); impl Error for UnexpectedStatusCodeError {} impl std::fmt::Display for UnexpectedStatusCodeError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "unexpected status code: {} {}", self.0.as_str(), self.0.canonical_reason().unwrap_or("???")) + if self.1.is_empty() { + write!(f, "unexpected status code: {} {}", self.0.as_str(), self.0.canonical_reason().unwrap_or("???")) + } else { + write!(f, "unexpected status code: {} {} ({})", self.0.as_str(), self.0.canonical_reason().unwrap_or("???"), self.1) + } } } @@ -109,7 +113,7 @@ pub(crate) async fn request(client: &HttpClient, method: Method, uri: Uri, data: if res.status() == StatusCode::UNAUTHORIZED { let auth = res.headers().get(hyper::header::WWW_AUTHENTICATE); if auth.is_none() { - return Ok(res); // return the 401 reply + return Err(Box::new(UnexpectedStatusCodeError(StatusCode::UNAUTHORIZED, "host returned 401 but no WWW-Authenticate header found"))) } let auth = auth.unwrap().to_str(); if auth.is_err() { diff --git a/service/src/weblistener.rs b/service/src/httplistener.rs similarity index 92% rename from service/src/weblistener.rs rename to service/src/httplistener.rs index f1c241449..67fbd04aa 100644 --- a/service/src/weblistener.rs +++ b/service/src/httplistener.rs @@ -26,22 +26,22 @@ use crate::service::Service; use std::os::unix::io::AsRawFd; /// Handles API dispatch and other HTTP handler stuff. -async fn web_handler(service: Service, req: Request) -> Result, Infallible> { +async fn http_handler(service: Service, req: Request) -> Result, Infallible> { Ok(Response::new("Hello, World".into())) } /// Listener for http connections to the API or for TCP P2P. /// Dropping a listener initiates shutdown of the background hyper Server instance, /// but it might not shut down instantly as this occurs asynchronously. -pub(crate) struct WebListener { +pub(crate) struct HttpListener { pub address: SocketAddr, shutdown_tx: RefCell>>, server: JoinHandle>, } -impl WebListener { +impl HttpListener { /// Create a new "background" TCP WebListener using the current tokio reactor async runtime. - pub async fn new(_device_name: &str, address: SocketAddr, service: &Service) -> Result> { + pub async fn new(_device_name: &str, address: SocketAddr, service: &Service) -> Result> { let listener = if addr.is_ipv4() { let listener = socket2::Socket::new(socket2::Domain::ipv4(), socket2::Type::stream(), Some(socket2::Protocol::tcp())); if listener.is_err() { @@ -100,13 +100,13 @@ impl WebListener { Ok::<_, Infallible>(service_fn(move |req: Request| { let service = service.clone(); async move { - web_handler(service, req).await + http_handler(service, req).await } })) } })).with_graceful_shutdown(async { let _ = shutdown_rx.await; })); - Ok(WebListener { + Ok(HttpListener { address, shutdown_tx: RefCell::new(Some(shutdown_tx)), server, @@ -114,7 +114,7 @@ impl WebListener { } } -impl Drop for WebListener { +impl Drop for HttpListener { fn drop(&mut self) { let _ = self.shutdown_tx.take().map(|tx| { let _ = tx.send(()); diff --git a/service/src/main.rs b/service/src/main.rs index 22a17fff0..5f65e0472 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -21,8 +21,8 @@ mod network; mod vnic; mod service; mod utils; -mod webclient; -mod weblistener; +mod httplistener; +mod httpclient; #[allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, improper_ctypes)] mod osdep; // bindgen generated @@ -324,7 +324,7 @@ fn main() { println!("{}.{}.{}", ver.0, ver.1, ver.2); 0 } - ("status", _) => crate::webclient::run_command(make_store(&cli_args), get_global_flags(&cli_args), crate::commands::status::run), + ("status", _) => crate::httpclient::run_command(make_store(&cli_args), get_global_flags(&cli_args), crate::commands::status::run), ("set", Some(sub_cli_args)) => { 0 } ("peer", Some(sub_cli_args)) => { 0 } ("network", Some(sub_cli_args)) => { 0 } diff --git a/service/src/service.rs b/service/src/service.rs index 7a990b14e..c1fd64280 100644 --- a/service/src/service.rs +++ b/service/src/service.rs @@ -30,7 +30,7 @@ use crate::log::Log; use crate::network::Network; use crate::store::Store; use crate::utils::{ms_since_epoch, ms_monotonic}; -use crate::weblistener::WebListener; +use crate::httplistener::HttpListener; /// How often to check for major configuration changes. This shouldn't happen /// too often since it uses a bit of CPU. @@ -244,8 +244,8 @@ async fn run_async(store: Arc, log: Arc, local_config: Arc = BTreeMap::new(); - let mut web_listeners: BTreeMap = BTreeMap::new(); - let mut local_web_listeners: (Option, Option) = (None, None); // IPv4, IPv6 + let mut web_listeners: BTreeMap = BTreeMap::new(); + let mut local_web_listeners: (Option, Option) = (None, None); // IPv4, IPv6 let (interrupt_tx, mut interrupt_rx) = futures::channel::mpsc::channel::<()>(1); let mut service = Service { @@ -430,7 +430,7 @@ async fn run_async(store: Arc, log: Arc, local_config: Arc, log: Arc, local_config: Arc