libutil++  1.9.3
 All Classes Functions Variables
helpers.cpp
1 /*
2 ** libutil++
3 ** $Id: helpers.cpp 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: helpers.cpp 1653 2016-02-28 19:54:59Z sella $";
10 
11 #include "helpers.h"
12 #include "../util/CommonMacro.h"
13 #include "../util/Log.h"
14 #include "../util/String.h"
15 #include "../net/IPAddressPort.h"
16 
17 using namespace sella::server;
18 
19 sella::variant::Variant http::parseURI(const HTTPConnection::shared &connection, bool addHeader, bool addSession, bool addCRUD, bool addBody) throw () {
21 
22  const HTTPRequest &req = connection->getRequest();
23 
24  auto &uri = data["_uri"];
25  const std::string &ruri = req.getURI();
26  const std::string &path = req.getPath();
27  const std::string &query = req.getQuery();
28  const std::string &host = req.getHost();
29  const auto &headers = req.getHeaders();
30  sella::net::IPAddressPort local = connection->getLocalIPAddressPort();
31  sella::net::IPAddressPort remote = connection->getRemoteIPAddressPort();
32  std::vector<std::string> parts;
33 
34  /* Variables first. */
35  parts = sella::util::String::split(query, '&', false);
36  for (auto p = parts.begin(); p != parts.end(); ++p) {
37  const auto &kv = sella::util::String::split(*p, '=', true, 2);
38 
39  if (kv.size() == 1) {
40  uri[kv.at(0)];
41  } else if (kv.size() == 2) {
42  uri[kv.at(0)] = sella::variant::Variant(kv.at(1), sella::variant::Variant::TypeAuto);
43  }
44  }
45 
46  /* URI second, since it takes priority over variable names, which may overlap. */
47  parts = sella::util::String::split(path, '/', false);
48  for (size_t i = 0; i < parts.size(); i++) {
49  uri[sella::util::String::sprintf("%zd", i + 2)] = parts.at(i);
50  }
51 
52  if (connection->isSecure()) {
53  uri["0"] = std::string("https://").append(host).append(ruri);
54  } else {
55  uri["0"] = std::string("http://").append(host).append(ruri);
56  }
57 
58  uri["1"] = host;
59 
60  if (addHeader) {
61  auto &header = data["_header"];
62 
63  for (auto h = headers.begin(); h != headers.end(); ++h) {
64  std::vector<std::string> parts = sella::util::String::split(*h, ": ", true, true);
65 
66  if (parts.size() == 2) {
67  header[parts[0]] = parts[1];
68  } else if (parts.size() == 1) {
69  header[parts[0]];
70  }
71  }
72  }
73 
74  if (addSession) {
75  auto &session = data["_session"];
76 
77  try {
78  size_t pos = host.find_last_of(':'), pos2 = host.find_last_of(']');
79 
80  if (pos == std::string::npos || (pos2 != std::string::npos && pos2 > pos)) {
81  session["vhost"] = host;
82  session["port"] = local.getPort().str();
83  } else {
84  session["vhost"] = host.substr(0, pos);
85  session["port"] = host.substr(pos + 1);
86  }
87  } catch (std::out_of_range &e) {
88  if (addSession && !session.contains("vhost")) {
89  session["vhost"] = "default";
90  }
91  }
92 
93  session["secure"] = connection->isSecure();
94  session["method"] = req.getMethodRaw();
95  session["version"] = req.getVersion();
96  session["uri"] = ruri;
97  session["path"] = path;
98  session["query"] = query;
99  session["local"] = local.str();
100  session["local-ip"] = local.getIPAddress().str();
101  session["local-port"] = local.getPort().str();
102  session["remote"] = remote.str();
103  session["remote-ip"] = remote.getIPAddress().str();
104  session["remote-port"] = remote.getPort().str();
105  }
106 
107  if (addCRUD) {
108  auto &session = data["_session"];
109 
110  switch (req.getMethod()) { /* http://en.wikipedia.org/wiki/Create,_read,_update_and_delete */
111  case HTTPRequest::Post:
112  session["function"] = CRUD::Create;
113  session["function-name"] = "create";
114  break;
115 
116  case HTTPRequest::Get:
117  session["function"] = CRUD::Read;
118  session["function-name"] = "read";
119  break;
120 
121  case HTTPRequest::Patch:
122  case HTTPRequest::Put: /* Should be interpreted as create, if new URL. */
123  session["function"] = CRUD::Update;
124  session["function-name"] = "update";
125  break;
126 
127  case HTTPRequest::Delete:
128  session["function"] = CRUD::Delete;
129  session["function-name"] = "delete";
130  break;
131 
132  default:
133  session["function"] = CRUD::None;
134  session["function-name"] = "none";
135  break;
136  }
137  }
138 
139  if (addBody) {
140  data["_body"] = sella::variant::Variant(req.getBody(), sella::variant::Variant::TypeAuto);
141  }
142 
143  return data;
144 }
145 
146 std::string http::buildOutput(const HTTPConnection::shared &connection, sella::variant::Variant &data) throw (ServerException) {
147  std::string output;
148  const HTTPRequest &request = connection->getRequest();
149 
150  switch (request.getAcceptType()) {
151  case HTTPRequest::AcceptType::JSON:
152  output = data.json();
153 
154  break;
155 
156  case HTTPRequest::AcceptType::XML:
157  output = data.xml();
158 
159  break;
160 
161  case HTTPRequest::AcceptType::CSV:
162  output = data.csv();
163 
164  break;
165 
166  default:
167  output = data.str();
168 
169  break;
170  }
171 
172  return output;
173 }
174 
175 /*
176 ** vim: noet ts=3 sw=3
177 */