extern crate clap;
extern crate hyper;
extern crate iron;
extern crate params;
extern crate router;
extern crate serde;
extern crate serde_json;
use hyper::header::{ContentType, Headers, ETag, EntityTag};
use hyper::mime::{Attr, Mime, TopLevel, SubLevel, Value};
use iron::prelude::*;
use iron::request::Request;
use iron::response::Response;
use iron::status;
use iron::IronResult;
use router::Router;
use serde_json::Map;
use std::io::Read;
use std::sync::{Arc, Mutex};
use super::client::Client;
use super::couchbase::types::error_type;
use super::couchbase::types::instance;
use super::couchbase::types::response;
use super::couchbase::types::operation::Operation;
pub fn get_meta(cas: &str, version: u16) -> serde_json::Value {
json!({
"cas": cas.to_string(),
"version": u64::from(version)
})
}
pub fn get_error(client: instance::InstancePtr, rc: &error_type::ErrorType) -> Map<String, serde_json::Value> {
let error = response::format_error(client, rc);
let mut res: Map<String, serde_json::Value> = Map::new();
res.insert("error".to_string(), serde_json::value::Value::String(error.to_string()));
res
}
pub fn handler_get(safe_client: &Arc<Mutex<Client>>, req: &mut iron::request::Request) -> IronResult<Response> {
println!("{:?}", &req);
let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
let mut client = safe_client.lock().unwrap();
let response = client.get_sync(docid);
match response {
Ok(result) => {
let cas = result.cas.to_string();
let value = result.value.unwrap();
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
headers.set(ETag(EntityTag::new(false, cas.to_owned())));
let doc: serde_json::Value = match serde_json::from_str(&value[..]) {
Ok(value) => value,
Err(_e) => json!(value)
};
let json = json!({
"meta": get_meta(&cas, result.version),
"doc": doc
});
let mut response = Response::with((status::Ok, json.to_string()));
response.headers = headers;
Ok(response)
},
Err(res) => {
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
let json = serde_json::to_string(
&get_error(
client.instance,
&res.0.unwrap().rc
)
).unwrap();
let mut response = Response::with((status::BadRequest, json));
response.headers = headers;
Ok(response)
}
}
}
pub fn handler_remove(safe_client: &Arc<Mutex<Client>>, req: &mut Request) -> IronResult<Response> {
debug!("handler_remove() called");
let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
let mut client = safe_client.lock().unwrap();
let mut payload = String::new();
let _ = req.body.read_to_string(&mut payload).unwrap();
let response = client.remove_sync(docid);
match response {
Ok(result) => {
let cas = result.cas.to_string();
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
headers.set(ETag(EntityTag::new(false, cas.to_owned())));
let mut map = Map::new();
map.insert("meta".to_string(), get_meta(&cas, result.version));
let json = serde_json::to_string(&map).unwrap();
let mut response = Response::with((status::Ok, json));
response.headers = headers;
Ok(response)
},
Err(res) => {
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
let json = serde_json::to_string(
&get_error(
client.instance,
&res.0.unwrap().rc
)
).unwrap();
let mut response = Response::with((status::BadRequest, json));
response.headers = headers;
Ok(response)
}
}
}
pub fn handler_store(safe_client: &Arc<Mutex<Client>>, operation: Operation, req: &mut Request) -> IronResult<Response> {
let mut cas: u64 = 0;
let mut exptime: u32 = 0;
let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
let mut client = safe_client.lock().unwrap();
let mut payload = String::new();
let _ = req.body.read_to_string(&mut payload).unwrap();
let response = client.store_sync(docid, &payload[..], operation, cas, exptime);
match response {
Ok(result) => {
let cas = result.cas.to_string();
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
headers.set(ETag(EntityTag::new(false, cas.to_owned())));
let mut map = Map::new();
map.insert("meta".to_string(), get_meta(&cas, result.version));
let json = serde_json::to_string(&map).unwrap();
let mut response = Response::with((status::Ok, json));
response.headers = headers;
Ok(response)
},
Err(res) => {
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
let json = serde_json::to_string(
&get_error(
client.instance,
&res.0.unwrap().rc
)
).unwrap();
let mut response = Response::with((status::BadRequest, json));
response.headers = headers;
Ok(response)
}
}
}
pub fn handler_query_view(safe_client: &Arc<Mutex<Client>>, req: &mut Request) -> IronResult<Response> {
let ddoc = req.extensions.get::<Router>().unwrap().find("ddoc").unwrap_or("");
let view = req.extensions.get::<Router>().unwrap().find("view").unwrap_or("");
let mut client = safe_client.lock().unwrap();
let response = client.query_view_sync(ddoc, view);
match response {
Err(res) => {
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
let json = serde_json::to_string(
&get_error(
client.instance,
&res.0.unwrap().rc
)
).unwrap();
let mut response = Response::with((status::BadRequest, json));
response.headers = headers;
Ok(response)
},
Ok(res) => {
let cas = res.cas.to_string();
let value = res.value.unwrap();
let mut headers = Headers::new();
headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
headers.set(ETag(EntityTag::new(false, cas.to_owned())));
let map = json!({
"meta": get_meta(&cas, res.version),
"doc": &value
});
let json = serde_json::to_string(&map).unwrap();
let mut response = Response::with((status::Ok, json));
response.headers = headers;
Ok(response)
}
}
}
#[allow(unused_mut)]
#[allow(unused_must_use)]
#[allow(unused_variables)]
pub fn start_web(c: &Arc<Mutex<Client>>, port: u16) {
println!("Starting REST Interface on port {}.", port);
let mut router = Router::new();
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let add_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Add, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let append_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Append, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let create_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Upsert, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let get_handler = move |req: &mut Request| -> IronResult<Response> {
handler_get(&handler_client, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let prepend_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Prepend, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let remove_handler = move |req: &mut Request| -> IronResult<Response> {
handler_remove(&handler_client, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let replace_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Replace, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let set_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Set, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let upsert_handler = move |req: &mut Request| -> IronResult<Response> {
handler_store(&handler_client, Operation::Upsert, req)
};
let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
let query_view_handler = move |req: &mut Request| -> IronResult<Response> {
handler_query_view(&handler_client, req)
};
router.get("/bucket/:bucketid/doc/:docid", get_handler, "doc_get");
router.post("/bucket/:bucketid/doc/:docid", create_handler, "doc_insert");
router.post("/bucket/:bucketid/doc/:docid/add", add_handler, "doc_add");
router.post("/bucket/:bucketid/doc/:docid/append", append_handler, "doc_append");
router.post("/bucket/:bucketid/doc/:docid/prepend", prepend_handler, "doc_prepend");
router.delete("/bucket/:bucketid/doc/:docid", remove_handler, "doc_remove");
router.post("/bucket/:bucketid/doc/:docid/replace", replace_handler, "doc_replace");
router.post("/bucket/:bucketid/doc/:docid/set", set_handler , "doc_set");
router.post("/bucket/:bucketid/doc/:docid/upsert", upsert_handler, "doc_upsert");
router.get("/bucket/:bucketid/view/:ddoc/:view", query_view_handler, "query_view");
let address = format!("0.0.0.0:{}", port);
match Iron::new(router).http(&address[..]) {
Ok(_res) => {
},
Err(res) => {
println!("{:?}", res);
}
}
}