Open Lighting Architecture  Latest Git
HTTPServer.h
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * HTTPServer.h
17  * The Base HTTP Server class.
18  * Copyright (C) 2005 Simon Newton
19  */
20 
21 
22 #ifndef INCLUDE_OLA_HTTP_HTTPSERVER_H_
23 #define INCLUDE_OLA_HTTP_HTTPSERVER_H_
24 
25 #include <ola/Callback.h>
26 #include <ola/base/Macro.h>
27 #include <ola/io/Descriptor.h>
28 #include <ola/io/SelectServer.h>
29 #include <ola/thread/Thread.h>
30 #include <ola/web/Json.h>
31 // 0.4.6 of microhttp doesn't include stdarg so we do it here.
32 #include <stdarg.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35 #ifdef _WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <ola/win/CleanWinSock2.h>
38 #else
39 #include <sys/select.h>
40 #include <sys/socket.h>
41 #endif // _WIN32
42 #include <microhttpd.h>
43 #include <map>
44 #include <set>
45 #include <string>
46 #include <vector>
47 
48 // Beginning with v0.9.71, libmicrohttpd changed the return type of most
49 // functions from int to enum MHD_Result
50 // https://git.gnunet.org/gnunet.git/tree/src/include/gnunet_mhd_compat.h
51 // proposes to define a constant for the return type so it works well
52 // with all versions of libmicrohttpd
53 #if MHD_VERSION >= 0x00097002
54 #define MHD_RESULT enum MHD_Result
55 #else
56 #define MHD_RESULT int
57 #endif
58 
59 namespace ola {
60 namespace http {
61 
62 /*
63  * Represents the HTTP request
64  */
65 class HTTPRequest {
66  public:
67  HTTPRequest(const std::string &url,
68  const std::string &method,
69  const std::string &version,
70  struct MHD_Connection *connection);
71  ~HTTPRequest();
72  bool Init();
73 
74  // accessors
75  const std::string Url() const { return m_url; }
76  const std::string Method() const { return m_method; }
77  const std::string Version() const { return m_version; }
78 
79  void AddHeader(const std::string &key, const std::string &value);
80  void AddPostParameter(const std::string &key, const std::string &value);
81  void ProcessPostData(const char *data, size_t *data_size);
82  const std::string GetHeader(const std::string &key) const;
83  bool CheckParameterExists(const std::string &key) const;
84  const std::string GetParameter(const std::string &key) const;
85  const std::string GetPostParameter(const std::string &key) const;
86 
87  bool InFlight() const { return m_in_flight; }
88  void SetInFlight() { m_in_flight = true; }
89 
90  private:
91  std::string m_url;
92  std::string m_method;
93  std::string m_version;
94  struct MHD_Connection *m_connection;
95  std::map<std::string, std::string> m_headers;
96  std::map<std::string, std::string> m_post_params;
97  struct MHD_PostProcessor *m_processor;
98  bool m_in_flight;
99 
100  static const unsigned int K_POST_BUFFER_SIZE = 1024;
101 
103 };
104 
105 
106 /*
107  * Represents the HTTP Response
108  */
110  public:
111  explicit HTTPResponse(struct MHD_Connection *connection):
112  m_connection(connection),
113  m_status_code(MHD_HTTP_OK) {}
114 
115  void Append(const std::string &data) { m_data.append(data); }
116  void SetContentType(const std::string &type);
117  void SetHeader(const std::string &key, const std::string &value);
118  void SetStatus(unsigned int status) { m_status_code = status; }
119  void SetNoCache();
120  void SetAccessControlAllowOriginAll();
121  int SendJson(const ola::web::JsonValue &json);
122  int Send();
123  struct MHD_Connection *Connection() const { return m_connection; }
124  private:
125  std::string m_data;
126  struct MHD_Connection *m_connection;
127  typedef std::multimap<std::string, std::string> HeadersMultiMap;
128  HeadersMultiMap m_headers;
129  unsigned int m_status_code;
130 
132 };
133 
134 
157  public:
160 
162  public:
163  // The port to listen on
164  uint16_t port;
165  // The root for content served with ServeStaticContent();
166  std::string data_dir;
167 
169  : port(0),
170  data_dir("") {
171  }
172  };
173 
174  explicit HTTPServer(const HTTPServerOptions &options);
175  virtual ~HTTPServer();
176  bool Init();
177  void *Run();
178  void Stop();
179  void UpdateSockets();
180 
185  void HandleHTTPIO() {}
186 
187  int DispatchRequest(const HTTPRequest *request, HTTPResponse *response);
188 
189  // Register a callback handler.
190  bool RegisterHandler(const std::string &path, BaseHTTPCallback *handler);
191 
192  // Register a file handler.
193  bool RegisterFile(const std::string &path,
194  const std::string &content_type);
195  bool RegisterFile(const std::string &path,
196  const std::string &file,
197  const std::string &content_type);
198  // Set the default handler.
199  void RegisterDefaultHandler(BaseHTTPCallback *handler);
200 
201  void Handlers(std::vector<std::string> *handlers) const;
202  const std::string DataDir() const { return m_data_dir; }
203 
204  // Return an error
205  int ServeError(HTTPResponse *response, const std::string &details = "");
206  int ServeNotFound(HTTPResponse *response);
207  static int ServeRedirect(HTTPResponse *response, const std::string &location);
208 
209  // Return the contents of a file.
210  int ServeStaticContent(const std::string &path,
211  const std::string &content_type,
212  HTTPResponse *response);
213 
214  static const char CONTENT_TYPE_PLAIN[];
215  static const char CONTENT_TYPE_HTML[];
216  static const char CONTENT_TYPE_GIF[];
217  static const char CONTENT_TYPE_PNG[];
218  static const char CONTENT_TYPE_ICO[];
219  static const char CONTENT_TYPE_CSS[];
220  static const char CONTENT_TYPE_JS[];
221  static const char CONTENT_TYPE_OCT[];
222  static const char CONTENT_TYPE_XML[];
223  static const char CONTENT_TYPE_JSON[];
224 
225  // Expose the SelectServer
226  ola::io::SelectServer *SelectServer() { return m_select_server.get(); }
227 
228  static struct MHD_Response *BuildResponse(void *data, size_t size);
229 
230  private :
231  typedef struct {
232  std::string file_path;
233  std::string content_type;
234  } static_file_info;
235 
236  struct DescriptorState {
237  public:
238  explicit DescriptorState(ola::io::UnmanagedFileDescriptor *_descriptor)
239  : descriptor(_descriptor), read(0), write(0) {}
240 
242  uint8_t read : 1;
243  uint8_t write : 1;
244  uint8_t : 6;
245  };
246 
247  struct Descriptor_lt {
248  bool operator()(const DescriptorState *d1,
249  const DescriptorState *d2) const {
250  return d1->descriptor->ReadDescriptor() <
251  d2->descriptor->ReadDescriptor();
252  }
253  };
254 
255  typedef std::set<DescriptorState*, Descriptor_lt> SocketSet;
256 
257  struct MHD_Daemon *m_httpd;
258  std::auto_ptr<ola::io::SelectServer> m_select_server;
259  SocketSet m_sockets;
260 
261  std::map<std::string, BaseHTTPCallback*> m_handlers;
262  std::map<std::string, static_file_info> m_static_content;
263  BaseHTTPCallback *m_default_handler;
264  unsigned int m_port;
265  std::string m_data_dir;
266 
267  int ServeStaticContent(static_file_info *file_info,
268  HTTPResponse *response);
269 
270  void InsertSocket(bool is_readable, bool is_writeable, int fd);
271  void FreeSocket(DescriptorState *state);
272 
274 };
275 } // namespace http
276 } // namespace ola
277 #endif // INCLUDE_OLA_HTTP_HTTPSERVER_H_
The base HTTP Server.
Definition: HTTPServer.h:156
The base class for JSON values.
Definition: Json.h:119
void AddHeader(const std::string &key, const std::string &value)
Add a header to the request object.
Definition: HTTPServer.cpp:258
const std::string GetPostParameter(const std::string &key) const
Lookup a post parameter in this request.
Definition: HTTPServer.cpp:351
const std::string GetHeader(const std::string &key) const
Return the value of the header sent with this request.
Definition: HTTPServer.cpp:296
const std::string GetParameter(const std::string &key) const
Return the value of a url parameter.
Definition: HTTPServer.cpp:312
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Creates dummy copy constructor and assignment operator declarations.
Definition: Macro.h:44
Definition: HTTPServer.h:65
Definition: HTTPServer.h:161
void ProcessPostData(const char *data, size_t *data_size)
Process post data.
Definition: HTTPServer.cpp:286
bool CheckParameterExists(const std::string &key) const
Return whether an url parameter exists.
Definition: HTTPServer.cpp:328
Definition: Thread.h:52
Definition: HTTPServer.h:109
A single threaded I/O event management system.
Definition: SelectServer.h:63
Helper macros.
A 2 argument callback which can be called multiple times.
Definition: Callback.h:1895
Allows a FD created by a library to be used with the SelectServer.
Definition: Descriptor.h:247
The namespace containing all OLA symbols.
Definition: Credentials.cpp:44
void AddPostParameter(const std::string &key, const std::string &value)
Add a post parameter.
Definition: HTTPServer.cpp:271
Basic data types used to represent elements in a JSON document.
void HandleHTTPIO()
Definition: HTTPServer.h:185