gauc/web/
mod.rs

1extern crate clap;
2extern crate hyper;
3extern crate iron;
4extern crate params;
5extern crate router;
6extern crate serde;
7extern crate serde_json;
8
9use hyper::header::{ContentType, Headers, ETag, EntityTag};
10use hyper::mime::{Attr, Mime, TopLevel, SubLevel, Value};
11
12use iron::prelude::*;
13use iron::request::Request;
14use iron::response::Response;
15use iron::status;
16// use iron::Handler;
17use iron::IronResult;
18
19use router::Router;
20use serde_json::Map;
21
22use std::io::Read;
23use std::sync::{Arc, Mutex};
24
25use super::client::Client;
26use super::couchbase::types::error_type;
27use super::couchbase::types::instance;
28use super::couchbase::types::response;
29use super::couchbase::types::operation::Operation;
30
31// Bucket REST Interface
32//
33// GET  /bucket/<BUCKET_NAME>/doc - list
34// POST /bucket/<BUCKET_NAME>/flush - flush
35//
36// DELETE  /bucket/<BUCKET_NAME>/doc/<ID>            - delete *
37// GET     /bucket/<BUCKET_NAME>/doc/<ID>            - get *
38// POST    /bucket/<BUCKET_NAME>/doc/<ID>            - upsert *
39// POST    /bucket/<BUCKET_NAME>/doc/<ID>/add        - add *
40// POST    /bucket/<BUCKET_NAME>/doc/<ID>/append     - append *
41// POST    /bucket/<BUCKET_NAME>/doc/<ID>/prepend    - prepend *
42// POST    /bucket/<BUCKET_NAME>/doc/<ID>/replace    - replace *
43// POST    /bucket/<BUCKET_NAME>/doc/<ID>/set        - set *
44// POST    /bucket/<BUCKET_NAME>/doc/<ID>/upsert     - upsert (explitcit) *
45
46pub fn get_meta(cas: &str, version: u16) -> serde_json::Value {
47    json!({
48        "cas": cas.to_string(),
49        "version": u64::from(version)
50    })
51}
52
53pub fn get_error(client: instance::InstancePtr, rc: &error_type::ErrorType) -> Map<String, serde_json::Value> {
54    let error = response::format_error(client, rc);
55
56    let mut res: Map<String, serde_json::Value> = Map::new();
57    res.insert("error".to_string(), serde_json::value::Value::String(error.to_string()));
58
59    res
60}
61
62pub fn handler_get(safe_client: &Arc<Mutex<Client>>, req: &mut iron::request::Request) -> IronResult<Response> {
63    println!("{:?}", &req);
64
65    // let params = req.get_ref::<params::Params>().unwrap();
66
67    let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
68    let mut client = safe_client.lock().unwrap();
69
70    let response = client.get_sync(docid);
71    match response {
72        Ok(result) => {
73            let cas = result.cas.to_string();
74            let value = result.value.unwrap();
75
76            let mut headers = Headers::new();
77            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
78            headers.set(ETag(EntityTag::new(false, cas.to_owned())));
79
80            let doc: serde_json::Value = match serde_json::from_str(&value[..]) {
81                Ok(value) => value,
82                Err(_e) => json!(value)
83            };
84
85            let json = json!({
86                "meta": get_meta(&cas, result.version),
87                "doc": doc
88            });
89
90            let mut response = Response::with((status::Ok, json.to_string()));
91            response.headers = headers;
92            Ok(response)
93        },
94        Err(res) => {
95            let mut headers = Headers::new();
96            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
97
98            let json = serde_json::to_string(
99                &get_error(
100                    client.instance,
101                    &res.0.unwrap().rc
102                )
103            ).unwrap();
104
105            let mut response = Response::with((status::BadRequest, json));
106            response.headers = headers;
107            Ok(response)
108        }
109    }
110}
111
112pub fn handler_remove(safe_client: &Arc<Mutex<Client>>, req: &mut Request) -> IronResult<Response> {
113    debug!("handler_remove() called");
114    let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
115    let mut client = safe_client.lock().unwrap();
116
117    let mut payload = String::new();
118    let _ = req.body.read_to_string(&mut payload).unwrap();
119    let response = client.remove_sync(docid);
120    match response {
121        Ok(result) => {
122            let cas = result.cas.to_string();
123
124            let mut headers = Headers::new();
125            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
126            headers.set(ETag(EntityTag::new(false, cas.to_owned())));
127
128            let mut map = Map::new();
129            map.insert("meta".to_string(), get_meta(&cas, result.version));
130
131            let json = serde_json::to_string(&map).unwrap();
132
133            let mut response = Response::with((status::Ok, json));
134            response.headers = headers;
135            Ok(response)
136        },
137        Err(res) => {
138            let mut headers = Headers::new();
139            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
140
141            let json = serde_json::to_string(
142                &get_error(
143                    client.instance,
144                    &res.0.unwrap().rc
145                )
146            ).unwrap();
147
148            let mut response = Response::with((status::BadRequest, json));
149            response.headers = headers;
150            Ok(response)
151        }
152    }
153}
154
155pub fn handler_store(safe_client: &Arc<Mutex<Client>>, operation: Operation, req: &mut Request) -> IronResult<Response> {
156    let mut cas: u64 = 0;
157    let mut exptime: u32 = 0;
158
159//    TODO: Port this!
160//    if let Ok(hashmap) = req.get_ref::<Params>() {
161//        if hashmap.contains_key("cas") {
162//            let tmp = hashmap.get("cas").unwrap();
163//            cas = match tmp.parse::<u64>() {
164//                Ok(val) => val,
165//                _ => 0
166//            };
167//        }
168//
169//        if hashmap.contains_key("exptime") {
170//            let tmp = hashmap.get("exptime").unwrap();
171//            exptime = match tmp.parse::<u32>() {
172//                Ok(val) => val,
173//                _ => 0
174//            };
175//        }
176//    };
177
178    let docid = req.extensions.get::<Router>().unwrap().find("docid").unwrap_or("");
179    let mut client = safe_client.lock().unwrap();
180
181    let mut payload = String::new();
182    let _ = req.body.read_to_string(&mut payload).unwrap();
183    let response = client.store_sync(docid, &payload[..], operation, cas, exptime);
184
185    match response {
186        Ok(result) => {
187            let cas = result.cas.to_string();
188
189            let mut headers = Headers::new();
190            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
191            headers.set(ETag(EntityTag::new(false, cas.to_owned())));
192
193            let mut map = Map::new();
194            map.insert("meta".to_string(), get_meta(&cas, result.version));
195
196            let json = serde_json::to_string(&map).unwrap();
197
198            let mut response = Response::with((status::Ok, json));
199            response.headers = headers;
200            Ok(response)
201        },
202        Err(res) => {
203            let mut headers = Headers::new();
204            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
205
206            let json = serde_json::to_string(
207                &get_error(
208                    client.instance,
209                    &res.0.unwrap().rc
210                )
211            ).unwrap();
212
213            let mut response = Response::with((status::BadRequest, json));
214            response.headers = headers;
215            Ok(response)
216        }
217    }
218}
219
220pub fn handler_query_view(safe_client: &Arc<Mutex<Client>>, req: &mut Request) -> IronResult<Response> {
221    let ddoc = req.extensions.get::<Router>().unwrap().find("ddoc").unwrap_or("");
222    let view = req.extensions.get::<Router>().unwrap().find("view").unwrap_or("");
223    let mut client = safe_client.lock().unwrap();
224
225    let response = client.query_view_sync(ddoc, view);
226    match response {
227        Err(res) => {
228            let mut headers = Headers::new();
229            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
230
231            let json = serde_json::to_string(
232                &get_error(
233                    client.instance,
234                    &res.0.unwrap().rc
235                )
236            ).unwrap();
237
238            let mut response = Response::with((status::BadRequest, json));
239            response.headers = headers;
240            Ok(response)
241        },
242        Ok(res) => {
243            let cas = res.cas.to_string();
244            let value = res.value.unwrap();
245
246            let mut headers = Headers::new();
247            headers.set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![(Attr::Charset, Value::Utf8)])));
248            headers.set(ETag(EntityTag::new(false, cas.to_owned())));
249
250            let map = json!({
251                "meta": get_meta(&cas, res.version),
252                "doc": &value
253            });
254
255            // TODO: Handle non-json documents
256            let json = serde_json::to_string(&map).unwrap();
257
258            let mut response = Response::with((status::Ok, json));
259            response.headers = headers;
260            Ok(response)
261        }
262    }
263}
264
265#[allow(unused_mut)]
266#[allow(unused_must_use)]
267#[allow(unused_variables)]
268pub fn start_web(c: &Arc<Mutex<Client>>, port: u16) {
269    println!("Starting REST Interface on port {}.", port);
270
271    let mut router = Router::new();
272
273    // Add handler
274    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
275    let add_handler = move |req: &mut Request| -> IronResult<Response> {
276        handler_store(&handler_client, Operation::Add, req)
277    };
278
279    // Append handler
280    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
281    let append_handler = move |req: &mut Request| -> IronResult<Response> {
282        handler_store(&handler_client, Operation::Append, req)
283    };
284
285    // Create handler
286    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
287    let create_handler = move |req: &mut Request| -> IronResult<Response> {
288        handler_store(&handler_client, Operation::Upsert, req)
289    };
290
291    // Get handler
292    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
293    let get_handler = move |req: &mut Request| -> IronResult<Response> {
294        handler_get(&handler_client, req)
295    };
296
297    // Prepend handler
298    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
299    let prepend_handler = move |req: &mut Request| -> IronResult<Response> {
300        handler_store(&handler_client, Operation::Prepend, req)
301    };
302
303    // Remove handler
304    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
305    let remove_handler = move |req: &mut Request| -> IronResult<Response> {
306        handler_remove(&handler_client, req)
307    };
308
309    // Replace handler
310    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
311    let replace_handler = move |req: &mut Request| -> IronResult<Response> {
312        handler_store(&handler_client, Operation::Replace, req)
313    };
314
315    // Set handler
316    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
317    let set_handler = move |req: &mut Request| -> IronResult<Response> {
318        handler_store(&handler_client, Operation::Set, req)
319    };
320
321    // Upsert handler
322    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
323    let upsert_handler = move |req: &mut Request| -> IronResult<Response> {
324        handler_store(&handler_client, Operation::Upsert, req)
325    };
326
327    // View query handler
328    let handler_client = Arc::new(Mutex::new(c.lock().unwrap().clone()));
329    let query_view_handler = move |req: &mut Request| -> IronResult<Response> {
330        handler_query_view(&handler_client, req)
331    };
332
333    // Docs
334    router.get("/bucket/:bucketid/doc/:docid", get_handler, "doc_get");
335    router.post("/bucket/:bucketid/doc/:docid", create_handler, "doc_insert");
336    router.post("/bucket/:bucketid/doc/:docid/add", add_handler, "doc_add");
337    router.post("/bucket/:bucketid/doc/:docid/append", append_handler, "doc_append");
338    router.post("/bucket/:bucketid/doc/:docid/prepend", prepend_handler, "doc_prepend");
339    router.delete("/bucket/:bucketid/doc/:docid", remove_handler, "doc_remove");
340    router.post("/bucket/:bucketid/doc/:docid/replace", replace_handler, "doc_replace");
341    router.post("/bucket/:bucketid/doc/:docid/set", set_handler , "doc_set");
342    router.post("/bucket/:bucketid/doc/:docid/upsert", upsert_handler, "doc_upsert");
343
344    // Views
345    router.get("/bucket/:bucketid/view/:ddoc/:view", query_view_handler, "query_view");
346
347    let address = format!("0.0.0.0:{}", port);
348    match Iron::new(router).http(&address[..]) {
349        Ok(_res) => {
350            // println!("{:?}", res);
351        },
352        Err(res) => {
353            println!("{:?}", res);
354        }
355    }
356}
357