Fawkes API  Fawkes Development Version
request.cpp
1 
2 /***************************************************************************
3  * request.cpp - Web request
4  *
5  * Created: Mon Jun 17 18:04:04 2013
6  * Copyright 2006-2014 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #include <core/exception.h>
23 #include <webview/request.h>
24 #include <sys/types.h>
25 #include <sys/select.h>
26 #include <unistd.h>
27 #include <stdint.h>
28 #include <microhttpd.h>
29 #include <cstring>
30 #include <netinet/in.h>
31 
32 namespace fawkes {
33 #if 0 /* just to make Emacs auto-indent happy */
34 }
35 #endif
36 
37 /// @cond INTERNAL
38 static int
39 cookie_iterator(void *cls, enum MHD_ValueKind kind,
40  const char *key, const char *value)
41 {
42  WebRequest *request = static_cast<WebRequest *>(cls);
43  request->set_cookie(key, value);
44  return MHD_YES;
45 }
46 
47 static int
48 get_argument_iterator(void *cls, enum MHD_ValueKind kind,
49  const char *key, const char *value)
50 {
51  WebRequest *request = static_cast<WebRequest *>(cls);
52  if (value == NULL) request->set_get_value(key, "");
53  else request->set_get_value(key, value);
54  return MHD_YES;
55 }
56 
57 static int
58 header_iterator(void *cls, enum MHD_ValueKind kind,
59  const char *key, const char *value)
60 {
61  WebRequest *request = static_cast<WebRequest *>(cls);
62  if (value == NULL) request->set_header(key, "");
63  else request->set_header(key, value);
64  return MHD_YES;
65 }
66 /// @endcond
67 
68 /** @class WebRequest <webview/request.h>
69  * Web request meta data carrier.
70  * For incoming web requests this class is instantiate to carry the
71  * necessary information for carriers like URL, request method,
72  * or cookie and POST form values.
73  * @author Tim Niemueller
74  */
75 
76 
77 /** Constructor.
78  * @param uri URI of the request
79  */
80 WebRequest::WebRequest(const char *uri)
81  : pp_(NULL), is_setup_(false), uri_(uri)
82 {
83  reply_size_ = 0;
84 }
85 
86 /** Complete setting up of request.
87  * @param url requested URL
88  * @param method HTTP transfer method
89  * @param version HTTP version string
90  * @param connection MicroHTTPd connection
91  */
92 void
93 WebRequest::setup(const char *url, const char *method,
94  const char *version, MHD_Connection *connection)
95 {
96  url_ = url;
97 
98  if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) {
99  method_ = METHOD_GET;
100  } else if (0 == strcmp(method, MHD_HTTP_METHOD_POST)) {
101  method_ = METHOD_POST;
102  } else if (0 == strcmp(method, MHD_HTTP_METHOD_HEAD)) {
103  method_ = METHOD_HEAD;
104  } else if (0 == strcmp(method, MHD_HTTP_METHOD_DELETE)) {
105  method_ = METHOD_DELETE;
106  } else if (0 == strcmp(method, MHD_HTTP_METHOD_PUT)) {
107  method_ = METHOD_PUT;
108  } else if (0 == strcmp(method, MHD_HTTP_METHOD_CONNECT)) {
109  method_ = METHOD_CONNECT;
110  } else if (0 == strcmp(method, MHD_HTTP_METHOD_OPTIONS)) {
111  method_ = METHOD_OPTIONS;
112  } else if (0 == strcmp(method, MHD_HTTP_METHOD_TRACE)) {
113  method_ = METHOD_TRACE;
114  }
115 
116  if (0 == strcmp(version, MHD_HTTP_VERSION_1_0)) {
117  http_version_ = HTTP_VERSION_1_0;
118  } else if (0 == strcmp(version, MHD_HTTP_VERSION_1_1)) {
119  http_version_ = HTTP_VERSION_1_1;
120  }
121 
122  struct sockaddr *client_addr =
123  MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS)
124  ->client_addr;
125 
126  char addr_str[INET6_ADDRSTRLEN];
127  switch(client_addr->sa_family) {
128  case AF_INET:
129  inet_ntop(AF_INET, &(((struct sockaddr_in *)client_addr)->sin_addr),
130  addr_str, INET6_ADDRSTRLEN);
131  break;
132 
133  case AF_INET6:
134  inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)client_addr)->sin6_addr),
135  addr_str, INET6_ADDRSTRLEN);
136  break;
137 
138  default:
139  strncpy(addr_str, "Unknown AF", INET6_ADDRSTRLEN);
140  }
141 
142  client_addr_ = addr_str;
143 
144  MHD_get_connection_values(connection, MHD_HEADER_KIND, &header_iterator, this);
145  MHD_get_connection_values(connection, MHD_COOKIE_KIND, &cookie_iterator, this);
146  MHD_get_connection_values(connection,
147  MHD_GET_ARGUMENT_KIND, &get_argument_iterator, this);
148 
149  is_setup_ = true;
150 }
151 
152 
153 /** Destructor. */
155 {
156  if (pp_) {
157  MHD_destroy_post_processor(pp_);
158  pp_ = NULL;
159  }
160 }
161 
162 
163 /** Set a POST value.
164  * @param key key of the value
165  * @param data data of the value
166  * @param size size in bytes of @p data
167  */
168 void
169 WebRequest::set_post_value(const char *key, const char *data, size_t size)
170 {
171  std::string val_add(data, size);
172  if (post_values_.find(key) != post_values_.end()) {
173  post_values_[key] += val_add;
174  } else {
175  post_values_[key] = val_add;
176  }
177 }
178 
179 
180 /** Set raw post data.
181  * The data is copied as is without assuming a human-readable string
182  * or even just zero-termination.
183  * @param data data to copy
184  * @param data_size size in bytes of \@p data
185  */
186 void
187 WebRequest::set_raw_post_data(const char *data, size_t data_size)
188 {
189  post_raw_data_ = std::string(data, data_size);
190 }
191 
192 /** Increment reply bytes counter.
193  * @param increment_by number of bytes sent
194  */
195 void
197 {
198  reply_size_ += increment_by;
199 }
200 
201 /** Get number of bytes actually sent out so far.
202  * @return number of bytes sent
203  */
204 size_t
206 {
207  return reply_size_;
208 }
209 
210 
211 /** Get method as string.
212  * @return HTTP method as string
213  */
214 const char *
216 {
217  switch (method_) {
218  case METHOD_CONNECT: return MHD_HTTP_METHOD_CONNECT;
219  case METHOD_DELETE: return MHD_HTTP_METHOD_DELETE;
220  case METHOD_GET: return MHD_HTTP_METHOD_GET;
221  case METHOD_HEAD: return MHD_HTTP_METHOD_HEAD;
222  case METHOD_OPTIONS: return MHD_HTTP_METHOD_OPTIONS;
223  case METHOD_POST: return MHD_HTTP_METHOD_POST;
224  case METHOD_PUT: return MHD_HTTP_METHOD_PUT;
225  case METHOD_TRACE: return MHD_HTTP_METHOD_TRACE;
226  default: return "UNKNOWN_METHOD";
227  }
228 }
229 
230 
231 /** Get HTTP version as string.
232  * @return HTTP version as string.
233  */
234 const char *
236 {
237  switch (http_version_) {
238  case HTTP_VERSION_1_0: return MHD_HTTP_VERSION_1_0;
239  case HTTP_VERSION_1_1: return MHD_HTTP_VERSION_1_1;
240  default: return "UNKNOWN_VERSION";
241  }
242 }
243 
244 
245 /** Set HTTP code of the final reply.
246  * @param code reply code
247  */
248 void
250 {
251  reply_code_ = code;
252 }
253 
254 
255 /** Get HTTP code of reply.
256  * @return HTTP code of reply
257  */
260 {
261  return reply_code_;
262 }
263 
264 } // end namespace fawkes
void set_reply_code(WebReply::Code code)
Set HTTP code of the final reply.
Definition: request.cpp:249
const std::string & client_addr() const
Get client address as string.
Definition: request.h:95
Fawkes library namespace.
WebRequest(const char *uri)
Constructor.
Definition: request.cpp:80
size_t reply_size() const
Get number of bytes actually sent out so far.
Definition: request.cpp:205
Method method() const
Get HTTP transfer method.
Definition: request.h:77
void set_post_value(const char *key, const char *data, size_t size)
Set a POST value.
Definition: request.cpp:169
WebReply::Code reply_code() const
Get HTTP code of reply.
Definition: request.cpp:259
const char * http_version_str() const
Get HTTP version as string.
Definition: request.cpp:235
const char * method_str() const
Get method as string.
Definition: request.cpp:215
void increment_reply_size(size_t increment_by)
Increment reply bytes counter.
Definition: request.cpp:196
~WebRequest()
Destructor.
Definition: request.cpp:154
void set_raw_post_data(const char *data, size_t data_size)
Set raw post data.
Definition: request.cpp:187
const std::string & url() const
Get URL.
Definition: request.h:69
Code
HTTP response code.
Definition: reply.h:40