diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 4afa60b0..32ab0786 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -11,7 +11,7 @@ use rbx_dom_weak::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, rbx_session::RbxSession, - web::PublicInstanceMetadata, + web::api::PublicInstanceMetadata, }; static GRAPHVIZ_HEADER: &str = r#" diff --git a/server/src/web.rs b/server/src/web/api.rs similarity index 71% rename from server/src/web.rs rename to server/src/web/api.rs index 0e46e79f..9b1950c9 100644 --- a/server/src/web.rs +++ b/server/src/web/api.rs @@ -1,5 +1,5 @@ -//! Defines Rojo's web interface that all clients use to communicate with a -//! running live-sync session. +//! Defines Rojo's HTTP API, all under /api. These endpoints generally return +//! JSON. use std::{ borrow::Cow, @@ -8,7 +8,6 @@ use std::{ }; use serde_derive::{Serialize, Deserialize}; -use log::trace; use rouille::{ self, router, @@ -16,18 +15,14 @@ use rouille::{ Response, }; use rbx_dom_weak::{RbxId, RbxInstance}; -use ritz::{html}; use crate::{ live_session::LiveSession, session_id::SessionId, snapshot_reconciler::InstanceChanges, - visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, rbx_session::{MetadataPerInstance}, }; -static HOME_CSS: &str = include_str!("../assets/index.css"); - /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -83,14 +78,14 @@ pub struct SubscribeResponse<'a> { pub messages: Cow<'a, [InstanceChanges]>, } -pub struct Server { +pub struct ApiServer { live_session: Arc, server_version: &'static str, } -impl Server { - pub fn new(live_session: Arc) -> Server { - Server { +impl ApiServer { + pub fn new(live_session: Arc) -> ApiServer { + ApiServer { live_session, server_version: env!("CARGO_PKG_VERSION"), } @@ -98,12 +93,7 @@ impl Server { #[allow(unreachable_code)] pub fn handle_request(&self, request: &Request) -> Response { - trace!("Request {} {}", request.method(), request.url()); - router!(request, - (GET) (/) => { - self.handle_home() - }, (GET) (/api/rojo) => { self.handle_api_rojo() }, @@ -118,51 +108,10 @@ impl Server { self.handle_api_read(requested_ids) }, - (GET) (/visualize/rbx) => { - self.handle_visualize_rbx() - }, - (GET) (/visualize/imfs) => { - self.handle_visualize_imfs() - }, _ => Response::empty_404() ) } - pub fn listen(self, port: u16) { - let address = format!("0.0.0.0:{}", port); - - rouille::start_server(address, move |request| self.handle_request(request)); - } - - fn handle_home(&self) -> Response { - let page = html! { - - - "Rojo" - - - - -
-

- "Rojo Live Sync is up and running!" -

-

- "Version " { self.server_version } -

- - "Rojo Documentation" - -
- - - }; - - Response::html(format!("{}", page)) - } - /// Get a summary of information about the server fn handle_api_rojo(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); @@ -260,24 +209,4 @@ impl Server { instances, }) } - - fn handle_visualize_rbx(&self) -> Response { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), - } - } - - fn handle_visualize_imfs(&self) -> Response { - let imfs = self.live_session.imfs.lock().unwrap(); - let dot_source = format!("{}", VisualizeImfs(&imfs)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), - } - } } \ No newline at end of file diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs new file mode 100644 index 00000000..24f8b6d0 --- /dev/null +++ b/server/src/web/interface.rs @@ -0,0 +1,97 @@ +//! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. + +use std::sync::Arc; + +use rouille::{ + self, + router, + Request, + Response, +}; +use ritz::{html}; + +use crate::{ + live_session::LiveSession, + visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, +}; + +static HOME_CSS: &str = include_str!("../../assets/index.css"); + +pub struct InterfaceServer { + live_session: Arc, + server_version: &'static str, +} + +impl InterfaceServer { + pub fn new(live_session: Arc) -> InterfaceServer { + InterfaceServer { + live_session, + server_version: env!("CARGO_PKG_VERSION"), + } + } + + #[allow(unreachable_code)] + pub fn handle_request(&self, request: &Request) -> Response { + router!(request, + (GET) (/) => { + self.handle_home() + }, + (GET) (/visualize/rbx) => { + self.handle_visualize_rbx() + }, + (GET) (/visualize/imfs) => { + self.handle_visualize_imfs() + }, + _ => Response::empty_404() + ) + } + + fn handle_home(&self) -> Response { + let page = html! { + + + "Rojo" + + + + +
+

+ "Rojo Live Sync is up and running!" +

+

+ "Version " { self.server_version } +

+ + "Rojo Documentation" + +
+ + + }; + + Response::html(format!("{}", page)) + } + + fn handle_visualize_rbx(&self) -> Response { + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } + } + + fn handle_visualize_imfs(&self) -> Response { + let imfs = self.live_session.imfs.lock().unwrap(); + let dot_source = format!("{}", VisualizeImfs(&imfs)); + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } + } +} \ No newline at end of file diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs new file mode 100644 index 00000000..e988b524 --- /dev/null +++ b/server/src/web/mod.rs @@ -0,0 +1,47 @@ +// TODO: This module needs to be public for visualize, we should move +// PublicInstanceMetadata and switch this private! +pub mod api; +mod interface; + +use std::sync::Arc; + +use log::trace; +use rouille::{find_route, Request, Response}; + +use crate::{ + live_session::LiveSession, +}; + +use self::{ + api::ApiServer, + interface::InterfaceServer, +}; + +pub struct Server { + api: api::ApiServer, + interface: interface::InterfaceServer, +} + +impl Server { + pub fn new(live_session: Arc) -> Server { + Server { + api: ApiServer::new(Arc::clone(&live_session)), + interface: InterfaceServer::new(Arc::clone(&live_session)), + } + } + + pub fn handle_request(&self, request: &Request) -> Response { + trace!("Request {} {}", request.method(), request.url()); + + find_route!( + self.api.handle_request(request), + self.interface.handle_request(request) + ) + } + + pub fn listen(self, port: u16) { + let address = format!("0.0.0.0:{}", port); + + rouille::start_server(address, move |request| self.handle_request(request)); + } +} \ No newline at end of file