rikitiki  v0.1.67
Build C++ web server modules that allow easy routing and deployment.
restAdv.h
1 /* Copyright (C) 2012-2013 Justin Berger
2  The full license is available in the LICENSE file at the root of this project and is also available at http://opensource.org/licenses/MIT. */
3 #pragma once
4 #include <rikitiki/rikitiki>
5 #include <rikitiki/mongoose/mongoose>
6 #include <rikitiki/rest/rest>
7 #include <rikitiki/jsoncpp/jsoncpp>
8 #include <rikitiki/configuration/configuration>
9 #include <tuple>
10 #include <sqlite3.h>
11 #include <mxcomp/tuples.h>
12 #include <cxxabi.h>
13 using namespace rikitiki;
14 using namespace rikitiki::mongoose;
15 
16 
17  inline static std::string prettyName(const std::type_info& ti){
18  char buf[1024];
19  size_t size=1024;
20  int status;
21  char* res = abi::__cxa_demangle (ti.name(),
22  buf,
23  &size,
24  &status);
25  return std::string(res);
26  }
27 
28 namespace rikitiki {
29  struct Book {
30 
31  std::string name;
32  std::string author;
33  std::string isbn;
34  Book() {}
35  Book(const std::string& _name, const std::string& _author, const std::string& _isbn) :
36  name(_name), author(_author), isbn(_isbn) {}
37  };
38 
39 }
40 
41 namespace mxcomp {
42  METACLASS(Book){
43  MEMBERS(FIELD(name),
44  FIELD(author),
45  FIELD(isbn));
46  };
47 }
48 namespace rikitiki {
49  namespace examples {
50  struct GetType {
51  template <typename T>
52  auto operator()(const T& t) const -> typename std::enable_if<std::is_base_of<Field, T>::value, std::string>::type
53  { return prettyName(typeid(T)); }
54 
55  template <typename T>
56  auto operator()(const T& t) const -> typename std::enable_if<std::is_base_of<Field, T>::value == false, std::string>::type
57  { return prettyName(typeid(T)) + "!!!"; }
58  };
59 
66  struct RestAdvModule {
67  std::vector<Book> books;
68 
70  void POST(ConnContext& ctx){
71  Book newBook;
72  ctx >> newBook;
73  books.push_back(newBook);
74  ctx << books.size() - 1;
75  }
76 
78  void GET(ConnContext& ctx){
79  ctx << books;
80  }
81 
82  void GET(ConnContext& ctx, int id){
83  if(id < 0 || id >= (int)books.size())
84  ctx << HttpStatus::Bad_Request;
85  else
86  ctx << books[id];
87  }
88 
89  void DELETE(ConnContext& ctx){
90  books.clear();
91  ctx.handled = true; // If we don't write anything to ctx, it doesn't count as handled.
92  }
93 
94  struct PrintFunctor {
95  ConnContext& ctx;
96  Book& book;
97 
98  PrintFunctor(ConnContext& _ctx, Book& _book) : ctx(_ctx), book(_book) {}
99  template <typename S>
100  inline void operator()( const Field_<Book, S>& field){
101  ctx << field.get(book);
102  }
103  };
104 
105  void operator()(ConnContext& ctx, int id, const std::string& prop){
106  if(id < 0 || id >= (int)books.size())
107  ctx << HttpStatus::Bad_Request;
108  else {
109  auto mt = mxcomp::tuples::make_mapped([](const Member& m) { return m.name; },
110  MetaClass_<Book>::fields());
111  mt.findAndRun(prop, PrintFunctor(ctx, books[id]));
112  }
113  }
114 
115  void Register(Server& server){
116  typedef RestAdvModule T;
117  rikitiki::rest::Register(server, "/book-adv", this);
118  server.AddHandler(CreateRoute<int, std::string>::With(this, "/book-adv/{id}/{property}"));
119  }
120  };
121 
122  }
123 }