backtalk/
request.rs

1use super::{JsonObject, JsonValue, Reply, Error};
2use reply::make_reply;
3use futures::future::{IntoFuture, ok, FutureResult, AndThen, Future, BoxFuture};
4
5/**
6A type of request, for instance "List" or "Post".
7
8These mostly correspond to the HTTP methods, with the addition of `List`, `Listen`, and `Action`.
9
10- `List` is a `GET` request with an ID on a resource, such as `GET /cats`.
11- `Listen` is a `GET`
12request with a `Accept: text/event-stream` header. `Listen` requests may or may not have IDs, so
13both `GET /cats` and `GET /cats/123` with the `event-stream` header would be a `Listen` request.
14- `Action` is a custom action on a specific resource ID. For instance, `POST /cats/123/feed` would
15be `Action("feed")`.
16
17Note that we don't support `PUT` requests currently, for simplicity.
18*/
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum Method {
21  /// `GET /resource`, indempotent
22  List,
23  /// `GET /resource/123`, indempotent
24  Get,
25  /// `DELETE /resource/123`, indempotent
26  Delete,
27  /// `POST /resource`
28  Post,
29  /// `PATCH /resource/123`
30  Patch,
31  /// Either `GET /resource/` or `GET /resource/123`, with the `Accept: text/event-stream` header
32  Listen,
33  /// `POST /resource/123/actionname`
34  Action(String),
35}
36
37impl Method {
38  pub fn as_string(&self) -> String {
39    match self {
40      &Method::List => "list",
41      &Method::Get => "get",
42      &Method::Delete => "delete",
43      &Method::Post => "post",
44      &Method::Patch => "patch",
45      &Method::Listen => "listen",
46      &Method::Action(ref action) => action,
47    }.to_string()
48  }
49}
50
51/**
52A request containing data from the client.
53*/
54#[derive(Debug)]
55pub struct Request {
56  id: Option<String>,
57  params: JsonObject,
58  data: JsonObject,
59  resource: String,
60  method: Method,
61  null: JsonValue,
62}
63
64impl Request {
65  pub fn new(resource: String, method: Method, id: Option<String>, data: JsonObject, params: JsonObject) -> Request {
66    Request {
67      resource: resource,
68      method: method,
69      id: id,
70      data: data,
71      params: params,
72      null: JsonValue::Null,
73    }
74  }
75
76  pub fn into_reply(self, reply: JsonObject) -> Reply {
77    make_reply(self, reply)
78  }
79
80  // TODO data_then accepts a function that returns a future<JsonValue, Error>
81
82  pub fn method(&self) -> Method {
83    self.method.clone()
84  }
85
86  pub fn resource(&self) -> &str {
87    &self.resource
88  }
89
90  pub fn id(&self) -> &Option<String> {
91    &self.id
92  }
93
94  pub fn params(&self) -> &JsonObject {
95    &self.params
96  }
97
98  pub fn params_mut(&mut self) -> &mut JsonObject {
99    &mut self.params
100  }
101
102  pub fn param(&self, key: &str) -> &JsonValue {
103    self.params.get(key).unwrap_or(&self.null)
104  }
105
106  pub fn set_param(&mut self, key: String, val: JsonValue) {
107    self.params.insert(key, val);
108  }
109
110  pub fn data(&self) -> &JsonObject {
111    &self.data
112  }
113
114  pub fn data_mut(&mut self) -> &mut JsonObject {
115    &mut self.data
116  }
117
118  pub fn boxed(self) -> BoxFuture<Request, Error> {
119    ok(self).boxed()
120  }
121
122  pub fn and_then<F, B>(self, f: F) -> AndThen<FutureResult<Request, Error>, B, F>
123    where F: FnOnce(Request) -> B,
124          B: IntoFuture<Error=Error>
125  {
126    ok::<Request, Error>(self).and_then(f)
127  }
128}
129
130impl IntoFuture for Request {
131  type Item = Request;
132  type Error = Error;
133  type Future = FutureResult<Request, Error>;
134  fn into_future(self) -> Self::Future {
135    ok(self)
136  }
137}
138