From 86d6cc5259434ff9dfd7c0b84566746933eb342a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 5 Apr 2018 12:06:04 -0700 Subject: [PATCH] Factor out general web utilities to web_util --- server/src/lib.rs | 1 + server/src/web.rs | 70 +---------------------------------------- server/src/web_util.rs | 71 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 69 deletions(-) create mode 100644 server/src/web_util.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 1d9e0325..06158882 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -13,6 +13,7 @@ extern crate tempfile; pub mod rbx_session; pub mod id; pub mod web; +pub mod web_util; pub mod core; pub mod project; pub mod pathext; diff --git a/server/src/web.rs b/server/src/web.rs index 1f0fec2d..a22d4212 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,16 +1,12 @@ -use std::io::Read; use std::sync::{Arc, Mutex}; use rouille; -use serde; -use serde_json; use project::Project; use vfs::{VfsSession, VfsChange}; use rbx::RbxInstance; use middleware::MiddlewareChain; - -static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB +use web_util::{json, read_json}; /// The set of configuration the web server needs to start. pub struct WebConfig { @@ -52,70 +48,6 @@ struct WriteSpecifier { item: RbxInstance, } -fn json(value: T) -> rouille::Response { - let data = serde_json::to_string(&value).unwrap(); - rouille::Response::from_data("application/json", data) -} - -/// Pulls text that may be JSON out of a Rouille Request object. -/// -/// Doesn't do any actual parsing -- all this method does is verify the content -/// type of the request and read the request's body. -fn read_json_text(request: &rouille::Request) -> Option { - // Bail out if the request body isn't marked as JSON - match request.header("Content-Type") { - Some(header) => if !header.starts_with("application/json") { - return None; - }, - None => return None, - } - - let body = match request.data() { - Some(v) => v, - None => return None, - }; - - // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. - let mut out = Vec::new(); - match body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out) { - Ok(_) => {}, - Err(_) => return None, - } - - // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to - // process it. - if out.len() > MAX_BODY_SIZE { - return None; - } - - let parsed = match String::from_utf8(out) { - Ok(v) => v, - Err(_) => return None, - }; - - Some(parsed) -} - -/// Reads the body out of a Rouille Request and attempts to turn it into JSON. -fn read_json(request: &rouille::Request) -> Option -where - T: serde::de::DeserializeOwned, -{ - let body = match read_json_text(&request) { - Some(v) => v, - None => return None, - }; - - let parsed = match serde_json::from_str(&body) { - Ok(v) => v, - Err(_) => return None, - }; - - // TODO: Change return type to some sort of Result - - Some(parsed) -} - /// Start the Rojo web server and park our current thread. pub fn start(config: WebConfig, project: Project, middleware_chain: &'static MiddlewareChain, vfs: Arc>) { let address = format!("localhost:{}", config.port); diff --git a/server/src/web_util.rs b/server/src/web_util.rs new file mode 100644 index 00000000..7feacaa1 --- /dev/null +++ b/server/src/web_util.rs @@ -0,0 +1,71 @@ +use std::io::Read; + +use rouille; +use serde; +use serde_json; + +static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB + +pub fn json(value: T) -> rouille::Response { + let data = serde_json::to_string(&value).unwrap(); + rouille::Response::from_data("application/json", data) +} + +/// Pulls text that may be JSON out of a Rouille Request object. +/// +/// Doesn't do any actual parsing -- all this method does is verify the content +/// type of the request and read the request's body. +pub fn read_json_text(request: &rouille::Request) -> Option { + // Bail out if the request body isn't marked as JSON + match request.header("Content-Type") { + Some(header) => if !header.starts_with("application/json") { + return None; + }, + None => return None, + } + + let body = match request.data() { + Some(v) => v, + None => return None, + }; + + // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. + let mut out = Vec::new(); + match body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out) { + Ok(_) => {}, + Err(_) => return None, + } + + // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to + // process it. + if out.len() > MAX_BODY_SIZE { + return None; + } + + let parsed = match String::from_utf8(out) { + Ok(v) => v, + Err(_) => return None, + }; + + Some(parsed) +} + +/// Reads the body out of a Rouille Request and attempts to turn it into JSON. +pub fn read_json(request: &rouille::Request) -> Option +where + T: serde::de::DeserializeOwned, +{ + let body = match read_json_text(&request) { + Some(v) => v, + None => return None, + }; + + let parsed = match serde_json::from_str(&body) { + Ok(v) => v, + Err(_) => return None, + }; + + // TODO: Change return type to some sort of Result + + Some(parsed) +}