1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use valico::json_dsl;
use valico::json_schema;
use backend;
use errors;
use json::{JsonValue};
use framework::nesting::{self, Nesting, Node};
use framework;
use framework::path;
use batteries::schemes;
pub struct Namespace {
pub handlers: framework::ApiHandlers,
pub path: path::Path,
pub coercer: Option<json_dsl::Builder>,
before: framework::Callbacks,
before_validation: framework::Callbacks,
after_validation: framework::Callbacks,
after: framework::Callbacks
}
impl_nesting!(Namespace);
impl Namespace {
pub fn new(path: &str) -> Namespace {
Namespace {
handlers: vec![],
path: path::Path::parse(path, false).unwrap(),
coercer: None,
before: vec![],
before_validation: vec![],
after_validation: vec![],
after: vec![]
}
}
pub fn params<F>(&mut self, builder: F) where F: FnOnce(&mut json_dsl::Builder) {
self.coercer = Some(json_dsl::Builder::build(builder));
}
pub fn build<F>(path: &str, builder: F) -> Namespace where F: FnOnce(&mut Namespace) {
let mut namespace = Namespace::new(path);
builder(&mut namespace);
return namespace;
}
fn validate(&self, params: &mut JsonValue, scope: Option<&json_schema::Scope>) -> backend::HandleResult<()> {
if self.coercer.is_some() {
let coercer = self.coercer.as_ref().unwrap();
let state = coercer.process(params, &scope);
if state.is_strictly_valid() {
Ok(())
} else {
if state.missing.len() > 0 {
warn!("There are some missing JSON schemes: {:?}", state.missing);
}
Err(error_response!(errors::Validation{ reason: state.errors }))
}
} else {
Ok(())
}
}
}
impl framework::ApiHandler for Namespace {
fn api_call<'a, 'r>(
&'a self,
rest_path: &str,
params: &mut JsonValue,
req: &'r mut (backend::Request + 'r),
info: &mut framework::CallInfo<'a>
) -> backend::HandleResult<backend::Response> {
let rest_path: &str = match self.path.is_match(rest_path) {
Some(captures) => {
let captured_length = captures.at(0).map_or(0, |c| c.len());
self.path.apply_captures(params, captures);
path::normalize(&rest_path[(captured_length)..])
},
None => return Err(error_response!(errors::NotMatch))
};
try!(self.validate(params, info.app.ext.get::<schemes::SchemesScope>()));
self.push_node(info);
self.call_handlers(rest_path, params, req, info)
}
}