mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-25 23:26:19 +00:00
Break apart web interface between UI and API
This commit is contained in:
@@ -11,7 +11,7 @@ use rbx_dom_weak::RbxId;
|
|||||||
use crate::{
|
use crate::{
|
||||||
imfs::{Imfs, ImfsItem},
|
imfs::{Imfs, ImfsItem},
|
||||||
rbx_session::RbxSession,
|
rbx_session::RbxSession,
|
||||||
web::PublicInstanceMetadata,
|
web::api::PublicInstanceMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GRAPHVIZ_HEADER: &str = r#"
|
static GRAPHVIZ_HEADER: &str = r#"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Defines Rojo's web interface that all clients use to communicate with a
|
//! Defines Rojo's HTTP API, all under /api. These endpoints generally return
|
||||||
//! running live-sync session.
|
//! JSON.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@@ -8,7 +8,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde_derive::{Serialize, Deserialize};
|
use serde_derive::{Serialize, Deserialize};
|
||||||
use log::trace;
|
|
||||||
use rouille::{
|
use rouille::{
|
||||||
self,
|
self,
|
||||||
router,
|
router,
|
||||||
@@ -16,18 +15,14 @@ use rouille::{
|
|||||||
Response,
|
Response,
|
||||||
};
|
};
|
||||||
use rbx_dom_weak::{RbxId, RbxInstance};
|
use rbx_dom_weak::{RbxId, RbxInstance};
|
||||||
use ritz::{html};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
live_session::LiveSession,
|
live_session::LiveSession,
|
||||||
session_id::SessionId,
|
session_id::SessionId,
|
||||||
snapshot_reconciler::InstanceChanges,
|
snapshot_reconciler::InstanceChanges,
|
||||||
visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg},
|
|
||||||
rbx_session::{MetadataPerInstance},
|
rbx_session::{MetadataPerInstance},
|
||||||
};
|
};
|
||||||
|
|
||||||
static HOME_CSS: &str = include_str!("../assets/index.css");
|
|
||||||
|
|
||||||
/// Contains the instance metadata relevant to Rojo clients.
|
/// Contains the instance metadata relevant to Rojo clients.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -83,14 +78,14 @@ pub struct SubscribeResponse<'a> {
|
|||||||
pub messages: Cow<'a, [InstanceChanges]>,
|
pub messages: Cow<'a, [InstanceChanges]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct ApiServer {
|
||||||
live_session: Arc<LiveSession>,
|
live_session: Arc<LiveSession>,
|
||||||
server_version: &'static str,
|
server_version: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl ApiServer {
|
||||||
pub fn new(live_session: Arc<LiveSession>) -> Server {
|
pub fn new(live_session: Arc<LiveSession>) -> ApiServer {
|
||||||
Server {
|
ApiServer {
|
||||||
live_session,
|
live_session,
|
||||||
server_version: env!("CARGO_PKG_VERSION"),
|
server_version: env!("CARGO_PKG_VERSION"),
|
||||||
}
|
}
|
||||||
@@ -98,12 +93,7 @@ impl Server {
|
|||||||
|
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
pub fn handle_request(&self, request: &Request) -> Response {
|
pub fn handle_request(&self, request: &Request) -> Response {
|
||||||
trace!("Request {} {}", request.method(), request.url());
|
|
||||||
|
|
||||||
router!(request,
|
router!(request,
|
||||||
(GET) (/) => {
|
|
||||||
self.handle_home()
|
|
||||||
},
|
|
||||||
(GET) (/api/rojo) => {
|
(GET) (/api/rojo) => {
|
||||||
self.handle_api_rojo()
|
self.handle_api_rojo()
|
||||||
},
|
},
|
||||||
@@ -118,51 +108,10 @@ impl Server {
|
|||||||
|
|
||||||
self.handle_api_read(requested_ids)
|
self.handle_api_read(requested_ids)
|
||||||
},
|
},
|
||||||
(GET) (/visualize/rbx) => {
|
|
||||||
self.handle_visualize_rbx()
|
|
||||||
},
|
|
||||||
(GET) (/visualize/imfs) => {
|
|
||||||
self.handle_visualize_imfs()
|
|
||||||
},
|
|
||||||
_ => Response::empty_404()
|
_ => 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! {
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>"Rojo"</title>
|
|
||||||
<style>
|
|
||||||
{ ritz::UnescapedText::new(HOME_CSS) }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="main">
|
|
||||||
<h1 class="title">
|
|
||||||
"Rojo Live Sync is up and running!"
|
|
||||||
</h1>
|
|
||||||
<h2 class="subtitle">
|
|
||||||
"Version " { self.server_version }
|
|
||||||
</h2>
|
|
||||||
<a class="docs" href="https://lpghatguy.github.io/rojo">
|
|
||||||
"Rojo Documentation"
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
};
|
|
||||||
|
|
||||||
Response::html(format!("<!DOCTYPE html>{}", page))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a summary of information about the server
|
/// Get a summary of information about the server
|
||||||
fn handle_api_rojo(&self) -> Response {
|
fn handle_api_rojo(&self) -> Response {
|
||||||
let rbx_session = self.live_session.rbx_session.lock().unwrap();
|
let rbx_session = self.live_session.rbx_session.lock().unwrap();
|
||||||
@@ -260,24 +209,4 @@ impl Server {
|
|||||||
instances,
|
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
97
server/src/web/interface.rs
Normal file
97
server/src/web/interface.rs
Normal file
@@ -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<LiveSession>,
|
||||||
|
server_version: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InterfaceServer {
|
||||||
|
pub fn new(live_session: Arc<LiveSession>) -> 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! {
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>"Rojo"</title>
|
||||||
|
<style>
|
||||||
|
{ ritz::UnescapedText::new(HOME_CSS) }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<h1 class="title">
|
||||||
|
"Rojo Live Sync is up and running!"
|
||||||
|
</h1>
|
||||||
|
<h2 class="subtitle">
|
||||||
|
"Version " { self.server_version }
|
||||||
|
</h2>
|
||||||
|
<a class="docs" href="https://lpghatguy.github.io/rojo">
|
||||||
|
"Rojo Documentation"
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
};
|
||||||
|
|
||||||
|
Response::html(format!("<!DOCTYPE html>{}", 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
server/src/web/mod.rs
Normal file
47
server/src/web/mod.rs
Normal file
@@ -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<LiveSession>) -> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user