web: Add config file + opensearch support

This commit is contained in:
Tiffany Bennett 2016-10-10 12:23:30 -04:00
parent 914f3a8dc2
commit 37925d59c3
5 changed files with 68 additions and 7 deletions

View file

@ -33,3 +33,4 @@ serde = "0.8"
limiter = "0.2" limiter = "0.2"
logger = "0.1.0" logger = "0.1.0"
url = "1.2.0" url = "1.2.0"
toml = { version = "0.2", features = ["serde"] }

6
web/rink-web.toml.sample Normal file
View file

@ -0,0 +1,6 @@
# The absolute URL of the place this instance will be hosted. It may
# have an explicit protocol, but usually you'll want the // prefix
# instead. It should not have a trailing slash. Note that rink-web
# does not currently support being placed under a directory, it must
# have a subdomain to itself.
baseurl = "//rink.tiffnix.com"

View file

@ -20,6 +20,7 @@ extern crate serde_json;
extern crate limiter; extern crate limiter;
extern crate logger; extern crate logger;
extern crate url; extern crate url;
extern crate toml;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@ -41,10 +42,15 @@ use std::env;
use worker::{eval_text, eval_json}; use worker::{eval_text, eval_json};
use limiter::RequestLimit; use limiter::RequestLimit;
use logger::Logger; use logger::Logger;
use rustc_serialize::json::ToJson; use rustc_serialize::json::{ToJson, Json};
use std::sync::Arc; use std::sync::Arc;
use std::fs::File;
fn root(req: &mut Request) -> IronResult<Response> { struct Rink {
config: Json,
}
fn root(rink: &Rink, req: &mut Request) -> IronResult<Response> {
let mut data = BTreeMap::new(); let mut data = BTreeMap::new();
let map = req.get_ref::<Params>().unwrap(); let map = req.get_ref::<Params>().unwrap();
@ -64,10 +70,12 @@ fn root(req: &mut Request) -> IronResult<Response> {
data.insert("main-page".to_owned(), true.to_json()); data.insert("main-page".to_owned(), true.to_json());
} }
data.insert("config".to_owned(), rink.config.to_json());
Ok(Response::with((status::Ok, Template::new("index", data)))) Ok(Response::with((status::Ok, Template::new("index", data))))
} }
struct ErrorMiddleware; struct ErrorMiddleware(Arc<Rink>);
impl AfterMiddleware for ErrorMiddleware { impl AfterMiddleware for ErrorMiddleware {
fn catch(&self, _req: &mut Request, err: IronError) -> IronResult<Response> { fn catch(&self, _req: &mut Request, err: IronError) -> IronResult<Response> {
@ -79,12 +87,13 @@ impl AfterMiddleware for ErrorMiddleware {
} }
error.insert("message".to_owned(), format!("{}", err.error)); error.insert("message".to_owned(), format!("{}", err.error));
data.insert("error".to_owned(), error.to_json()); data.insert("error".to_owned(), error.to_json());
data.insert("config".to_owned(), self.0.config.to_json());
println!("{:#?}", data); println!("{:#?}", data);
Ok(err.response.set(Template::new("index", data))) Ok(err.response.set(Template::new("index", data)))
} }
} }
fn api(req: &mut Request) -> IronResult<Response> { fn api(_rink: &Rink, req: &mut Request) -> IronResult<Response> {
let acao = Header(headers::AccessControlAllowOrigin::Any); let acao = Header(headers::AccessControlAllowOrigin::Any);
let map = req.get_ref::<Params>().unwrap(); let map = req.get_ref::<Params>().unwrap();
@ -98,6 +107,13 @@ fn api(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((acao, status::Ok, reply))) Ok(Response::with((acao, status::Ok, reply)))
} }
fn opensearch(rink: &Rink, _req: &mut Request) -> IronResult<Response> {
let mut data = BTreeMap::new();
data.insert("config".to_owned(), rink.config.to_json());
Ok(Response::with((status::Ok, Template::new("opensearch", data))))
}
fn ifnot1helper( fn ifnot1helper(
c: &handlebars::Context, c: &handlebars::Context,
h: &handlebars::Helper, h: &handlebars::Helper,
@ -175,13 +191,35 @@ fn main() {
worker::worker(&server, &query); worker::worker(&server, &query);
} }
let config = {
use std::io::Read;
let mut file = File::open("rink-web.toml").expect(
"Config file rink-web.toml does not exist. You \
must create it with the keys specified in the \
sample."
);
let mut buf = String::new();
file.read_to_string(&mut buf).unwrap();
let res = toml::Parser::new(&buf).parse().unwrap();
rustc_serialize::json::Json::from_str(
&serde_json::ser::to_string(&res).unwrap()
).unwrap()
};
let rink = Arc::new(Rink {
config: config,
});
let (logger_before, logger_after) = Logger::new(None); let (logger_before, logger_after) = Logger::new(None);
let mut mount = Mount::new(); let mut mount = Mount::new();
let mut router = Router::new(); let mut router = Router::new();
router.get("/", root, "root"); let rink2 = rink.clone();
router.get("/api", api, "api"); router.get("/", move |req: &mut Request| root(&rink2, req), "root");
let rink2 = rink.clone();
router.get("/api", move |req: &mut Request| api(&rink2, req), "api");
let rink2 = rink.clone();
router.get("/opensearch.xml", move |req: &mut Request| opensearch(&rink2, req), "opensearch.xml");
mount.mount("/", router); mount.mount("/", router);
mount.mount("/static", Static::new("./static/")); mount.mount("/static", Static::new("./static/"));
@ -204,7 +242,7 @@ fn main() {
chain.link_before(logger_before); chain.link_before(logger_before);
chain.link_before(limiter); chain.link_before(limiter);
chain.link_after(ErrorMiddleware); chain.link_after(ErrorMiddleware(rink.clone()));
chain.link_after(hbse); chain.link_after(hbse);
chain.link_after(logger_after); chain.link_after(logger_after);
let addr = first.as_ref().map(|x| &**x).unwrap_or("localhost:8000"); let addr = first.as_ref().map(|x| &**x).unwrap_or("localhost:8000");

View file

@ -17,6 +17,10 @@
rel="stylesheet" /> rel="stylesheet" />
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.css" <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.css"
rel="stylesheet" /> rel="stylesheet" />
<link rel="search"
type="application/opensearchdescription+xml"
href="{{config.baseurl}}/opensearch.xml"
title="Rink Search" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>Rink</ShortName>
<Description>Perform a Rink calculation</Description>
<Url type="text/html" method="get" template="{{config.baseurl}}/?q={searchTerms}"/>
<moz:SearchForm>{{config.baseurl}}/</moz:SearchForm>
<InputEncoding>UTF-8</InputEncoding>
<Url type="application/opensearchdescription+xml"
rel="self"
template="{{config.baseurl}}/opensearch.xml"/>
</OpenSearchDescription>