mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 13:44:15 +00:00
web: Use json serialization for templating
This commit is contained in:
parent
0cf9ec3b7a
commit
26a8231fa3
2 changed files with 61 additions and 28 deletions
|
@ -2,6 +2,8 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
extern crate rink;
|
||||
extern crate iron;
|
||||
extern crate router;
|
||||
|
@ -12,6 +14,11 @@ extern crate staticfile;
|
|||
extern crate mount;
|
||||
extern crate ipc_channel;
|
||||
extern crate libc;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
pub mod worker;
|
||||
|
||||
|
@ -26,7 +33,7 @@ use staticfile::Static;
|
|||
use std::collections::BTreeMap;
|
||||
use params::{Params, Value};
|
||||
use std::env;
|
||||
use worker::eval;
|
||||
use worker::{eval_text, eval_json};
|
||||
|
||||
fn root(req: &mut Request) -> IronResult<Response> {
|
||||
let mut data = BTreeMap::new();
|
||||
|
@ -34,7 +41,8 @@ fn root(req: &mut Request) -> IronResult<Response> {
|
|||
let map = req.get_ref::<Params>().unwrap();
|
||||
match map.find(&["q"]) {
|
||||
Some(&Value::String(ref query)) => {
|
||||
let reply = eval(query);
|
||||
let reply = eval_json(query);
|
||||
println!("{}", reply.pretty());
|
||||
data.insert("content".to_owned(), reply);
|
||||
},
|
||||
_ => (),
|
||||
|
@ -52,7 +60,7 @@ fn api(req: &mut Request) -> IronResult<Response> {
|
|||
_ => return Ok(Response::with((acao, status::BadRequest))),
|
||||
};
|
||||
|
||||
let reply = eval(query);
|
||||
let reply = eval_text(query);
|
||||
|
||||
Ok(Response::with((acao, status::Ok, reply)))
|
||||
}
|
||||
|
|
|
@ -1,15 +1,32 @@
|
|||
use libc;
|
||||
use std::io::Error;
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcSender, IpcReceiver};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::env;
|
||||
use rink;
|
||||
use rink::reply::{QueryReply, QueryError};
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
use std::io;
|
||||
use rustc_serialize;
|
||||
use serde_json;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum Error {
|
||||
Rink(QueryError),
|
||||
Time,
|
||||
Memory,
|
||||
Generic(String),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Error {
|
||||
Error::Generic(format!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn worker(server_name: &str, query: &str) -> ! {
|
||||
let tx = IpcSender::connect(server_name.to_owned()).unwrap();
|
||||
|
||||
tx.send("".to_owned()).unwrap();
|
||||
tx.send(Err(QueryError::Generic("".to_owned()))).unwrap();
|
||||
|
||||
unsafe {
|
||||
let limit = libc::rlimit {
|
||||
|
@ -19,7 +36,7 @@ pub fn worker(server_name: &str, query: &str) -> ! {
|
|||
};
|
||||
let res = libc::setrlimit(libc::RLIMIT_AS, &limit);
|
||||
if res == -1 {
|
||||
panic!("Setrlimit RLIMIT_AS failed: {}", Error::last_os_error())
|
||||
panic!("Setrlimit RLIMIT_AS failed: {}", io::Error::last_os_error())
|
||||
}
|
||||
let limit = libc::rlimit {
|
||||
// 15 seconds
|
||||
|
@ -28,22 +45,21 @@ pub fn worker(server_name: &str, query: &str) -> ! {
|
|||
};
|
||||
let res = libc::setrlimit(libc::RLIMIT_CPU, &limit);
|
||||
if res == -1 {
|
||||
panic!("Setrlimit RLIMIT_AS failed: {}", Error::last_os_error())
|
||||
panic!("Setrlimit RLIMIT_AS failed: {}", io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
let mut ctx = rink::load().unwrap();
|
||||
ctx.short_output = true;
|
||||
let reply = match rink::one_line(&mut ctx, query) {
|
||||
Ok(v) => v,
|
||||
Err(e) => e
|
||||
};
|
||||
let mut iter = rink::text_query::TokenIterator::new(query).peekable();
|
||||
let expr = rink::text_query::parse_query(&mut iter);
|
||||
let reply = ctx.eval_outer(&expr);
|
||||
tx.send(reply).unwrap();
|
||||
|
||||
::std::process::exit(0)
|
||||
}
|
||||
|
||||
pub fn eval(query: &str) -> String {
|
||||
pub fn eval(query: &str) -> Result<QueryReply, Error> {
|
||||
let (server, server_name) = IpcOneShotServer::new().unwrap();
|
||||
|
||||
let res = Command::new(env::current_exe().unwrap())
|
||||
|
@ -54,28 +70,22 @@ pub fn eval(query: &str) -> String {
|
|||
.stderr(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.env("RUST_BACKTRACE", "1")
|
||||
.spawn()
|
||||
.map_err(|x| format!("{}", x));
|
||||
let child = match res {
|
||||
Ok(s) => s,
|
||||
Err(e) => return format!("Failed to run sandbox: {}", e)
|
||||
};
|
||||
.spawn();
|
||||
let child = try!(res);
|
||||
let (rx, _) = server.accept().unwrap();
|
||||
let rx: IpcReceiver<Result<QueryReply, QueryError>> = rx;
|
||||
|
||||
match rx.recv() {
|
||||
Ok(s) => s,
|
||||
Ok(s) => s.map_err(Error::Rink),
|
||||
Err(e) => {
|
||||
let output = match child.wait_with_output() {
|
||||
Ok(v) => v,
|
||||
Err(e) => return format!("{}", e)
|
||||
};
|
||||
let output = try!(child.wait_with_output());
|
||||
match output.status.signal() {
|
||||
Some(libc::SIGXCPU) => return format!("Calculation went over time limit"),
|
||||
Some(libc::SIGXCPU) => return Err(Error::Time),
|
||||
// SIGABRT doesn't necessarily mean OOM, but GMP will raise it when it happens
|
||||
Some(libc::SIGABRT) => return format!("Calculation ran out of memory"),
|
||||
Some(libc::SIGABRT) => return Err(Error::Memory),
|
||||
_ => ()
|
||||
};
|
||||
format!(
|
||||
Err(Error::Generic(format!(
|
||||
"Receiving reply from sandbox failed: {}\n\
|
||||
Signal: {}\n\
|
||||
Sandbox stdout: {}\n\
|
||||
|
@ -84,7 +94,22 @@ pub fn eval(query: &str) -> String {
|
|||
output.status.signal().map(|x| format!("{}", x)).unwrap_or("None".to_owned()),
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_text(query: &str) -> String {
|
||||
match eval(query) {
|
||||
Ok(v) => format!("{}", v),
|
||||
Err(Error::Generic(e)) => format!("{}", e),
|
||||
Err(Error::Memory) => format!("Calculation ran out of memory"),
|
||||
Err(Error::Time) => format!("Calculation timed out"),
|
||||
Err(Error::Rink(e)) => format!("{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_json(query: &str) -> rustc_serialize::json::Json {
|
||||
let res = eval(query);
|
||||
rustc_serialize::json::Json::from_str(&serde_json::ser::to_string(&res).unwrap()).unwrap()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue