Open Lighting Architecture  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * HTTPServer.h
17  * The Base HTTP Server class.
18  * Copyright (C) 2005-2008 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 #include <sys/select.h>
36 #include <sys/socket.h>
37 #include <microhttpd.h>
38 #include <map>
39 #include <set>
40 #include <string>
41 #include <vector>
42 
43 namespace ola {
44 namespace http {
45 
46 /*
47  * Represents the HTTP request
48  */
49 class HTTPRequest {
50  public:
51  HTTPRequest(const std::string &url,
52  const std::string &method,
53  const std::string &version,
54  struct MHD_Connection *connection);
55  ~HTTPRequest();
56  bool Init();
57 
58  // accessors
59  const std::string Url() const { return m_url; }
60  const std::string Method() const { return m_method; }
61  const std::string Version() const { return m_version; }
62 
63  void AddHeader(const std::string &key, const std::string &value);
64  void AddPostParameter(const std::string &key, const std::string &value);
65  void ProcessPostData(const char *data, size_t *data_size);
66  const std::string GetHeader(const std::string &key) const;
67  bool CheckParameterExists(const std::string &key) const;
68  const std::string GetParameter(const std::string &key) const;
69  const std::string GetPostParameter(const std::string &key) const;
70 
71  bool InFlight() const { return m_in_flight; }
72  void SetInFlight() { m_in_flight = true; }
73 
74  private:
75  std::string m_url;
76  std::string m_method;
77  std::string m_version;
78  struct MHD_Connection *m_connection;
79  std::map<std::string, std::string> m_headers;
80  std::map<std::string, std::string> m_post_params;
81  struct MHD_PostProcessor *m_processor;
82  bool m_in_flight;
83 
84  static const unsigned int K_POST_BUFFER_SIZE = 1024;
85 
87 };
88 
89 
90 /*
91  * Represents the HTTP Response
92  */
93 class HTTPResponse {
94  public:
95  explicit HTTPResponse(struct MHD_Connection *connection):
96  m_connection(connection),
97  m_status_code(MHD_HTTP_OK) {}
98 
99  void Append(const std::string &data) { m_data.append(data); }
100  void SetContentType(const std::string &type);
101  void SetHeader(const std::string &key, const std::string &value);
102  void SetStatus(unsigned int status) { m_status_code = status; }
103  void SetNoCache();
104  int SendJson(const ola::web::JsonValue &json);
105  int Send();
106  struct MHD_Connection *Connection() const { return m_connection; }
107  private:
108  std::string m_data;
109  struct MHD_Connection *m_connection;
110  typedef std::multimap<std::string, std::string> HeadersMultiMap;
111  HeadersMultiMap m_headers;
112  unsigned int m_status_code;
113 
115 };
116 
117 
140  public:
143 
145  public:
146  // The port to listen on
147  uint16_t port;
148  // The root for content served with ServeStaticContent();
149  std::string data_dir;
150 
152  : port(0),
153  data_dir("") {
154  }
155  };
156 
157  explicit HTTPServer(const HTTPServerOptions &options);
158  virtual ~HTTPServer();
159  bool Init();
160  void *Run();
161  void Stop();
162  void UpdateSockets();
163 
168  void HandleHTTPIO() {}
169 
170  int DispatchRequest(const HTTPRequest *request, HTTPResponse *response);
171 
172  // Register a callback handler.
173  bool RegisterHandler(const std::string &path, BaseHTTPCallback *handler);
174 
175  // Register a file handler.
176  bool RegisterFile(const std::string &path,
177  const std::string &content_type);
178  bool RegisterFile(const std::string &path,
179  const std::string &file,
180  const std::string &content_type);
181  // Set the default handler.
182  void RegisterDefaultHandler(BaseHTTPCallback *handler);
183 
184  void Handlers(std::vector<std::string> *handlers) const;
185  const std::string DataDir() const { return m_data_dir; }
186 
187  // Return an error
188  int ServeError(HTTPResponse *response, const std::string &details="");
189  int ServeNotFound(HTTPResponse *response);
190  static int ServeRedirect(HTTPResponse *response, const std::string &location);
191 
192  // Return the contents of a file.
193  int ServeStaticContent(const std::string &path,
194  const std::string &content_type,
195  HTTPResponse *response);
196 
197  static const char CONTENT_TYPE_PLAIN[];
198  static const char CONTENT_TYPE_HTML[];
199  static const char CONTENT_TYPE_GIF[];
200  static const char CONTENT_TYPE_PNG[];
201  static const char CONTENT_TYPE_CSS[];
202  static const char CONTENT_TYPE_JS[];
203 
204  // Expose the SelectServer
205  ola::io::SelectServer *SelectServer() { return &m_select_server; }
206 
207  private :
208  typedef struct {
209  std::string file_path;
210  std::string content_type;
211  } static_file_info;
212 
213  typedef std::set<ola::io::UnmanagedFileDescriptor*,
215 
216  struct MHD_Daemon *m_httpd;
217  ola::io::SelectServer m_select_server;
218  SocketSet m_sockets;
219 
220  std::map<std::string, BaseHTTPCallback*> m_handlers;
221  std::map<std::string, static_file_info> m_static_content;
222  BaseHTTPCallback *m_default_handler;
223  unsigned int m_port;
224  std::string m_data_dir;
225 
226  int ServeStaticContent(static_file_info *file_info,
227  HTTPResponse *response);
228 
229  ola::io::UnmanagedFileDescriptor *NewSocket(fd_set *r_set,
230  fd_set *w_set,
231  int fd);
232 
234 };
235 } // namespace http
236 } // namespace ola
237 #endif // INCLUDE_OLA_HTTP_HTTPSERVER_H_