Open Lighting Architecture
 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  * This is a simple HTTP Server built around libmicrohttpd. It runs in a
21  * separate thread.
22  *
23  * Example:
24  * HTTPServer::HTTPServerOptions options;
25  * options.port = ...;
26  * HTTPServer server(options);
27  * server.Init();
28  * server.Run();
29  * // get on with life and later...
30  * server.Stop();
31  */
32 
33 
34 #ifndef INCLUDE_OLA_HTTP_HTTPSERVER_H_
35 #define INCLUDE_OLA_HTTP_HTTPSERVER_H_
36 
37 #include <ola/Callback.h>
38 #include <ola/io/Descriptor.h>
39 #include <ola/io/SelectServer.h>
40 #include <ola/thread/Thread.h>
41 #include <ola/web/Json.h>
42 // 0.4.6 of microhttp doesn't include stdarg so we do it here.
43 #include <stdarg.h>
44 #include <stdint.h>
45 #include <stdlib.h>
46 #include <sys/select.h>
47 #include <sys/socket.h>
48 #include <microhttpd.h>
49 #include <map>
50 #include <set>
51 #include <string>
52 #include <vector>
53 
54 namespace ola {
55 namespace http {
56 
57 using std::map;
58 using std::multimap;
59 using std::string;
60 using std::vector;
61 
62 /*
63  * Represents the HTTP request
64  */
65 class HTTPRequest {
66  public:
67  HTTPRequest(const string &url,
68  const string &method,
69  const string &version,
70  struct MHD_Connection *connection);
71  ~HTTPRequest();
72  bool Init();
73 
74  // accessors
75  const string Url() const { return m_url; }
76  const string Method() const { return m_method; }
77  const string Version() const { return m_version; }
78 
79  void AddHeader(const string &key, const string &value);
80  void AddPostParameter(const string &key, const string &value);
81  void ProcessPostData(const char *data, size_t *data_size);
82  const string GetHeader(const string &key) const;
83  bool CheckParameterExists(const string &key) const;
84  const string GetParameter(const string &key) const;
85  const string GetPostParameter(const string &key) const;
86 
87  bool InFlight() const { return m_in_flight; }
88  void SetInFlight() { m_in_flight = true; }
89 
90  private:
91  string m_url;
92  string m_method;
93  string m_version;
94  struct MHD_Connection *m_connection;
95  map<string, string> m_headers;
96  map<string, 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 };
102 
103 
104 /*
105  * Represents the HTTP Response
106  */
108  public:
109  explicit HTTPResponse(struct MHD_Connection *connection):
110  m_connection(connection),
111  m_status_code(MHD_HTTP_OK) {}
112 
113  void Append(const string &data) { m_data.append(data); }
114  void SetContentType(const string &type);
115  void SetHeader(const string &key, const string &value);
116  void SetStatus(unsigned int status) { m_status_code = status; }
117  void SetNoCache();
118  int SendJson(const ola::web::JsonValue &json);
119  int Send();
120  struct MHD_Connection *Connection() const { return m_connection; }
121  private:
122  string m_data;
123  struct MHD_Connection *m_connection;
124  multimap<string, string> m_headers;
125  unsigned int m_status_code;
126 };
127 
128 
129 /*
130  * The base HTTP Server
131  */
133  public:
136 
138  public:
139  // The port to listen on
140  uint16_t port;
141  // The root for content served with ServeStaticContent();
142  string data_dir;
143 
145  : port(0),
146  data_dir("") {
147  }
148  };
149 
150  explicit HTTPServer(const HTTPServerOptions &options);
151  virtual ~HTTPServer();
152  bool Init();
153  void *Run();
154  void Stop();
155  void UpdateSockets();
156 
161  void HandleHTTPIO() {}
162 
163  int DispatchRequest(const HTTPRequest *request, HTTPResponse *response);
164 
165  // Register a callback handler.
166  bool RegisterHandler(const string &path, BaseHTTPCallback *handler);
167 
168  // Register a file handler.
169  bool RegisterFile(const string &path,
170  const string &content_type);
171  bool RegisterFile(const string &path,
172  const string &file,
173  const string &content_type);
174  // Set the default handler.
175  void RegisterDefaultHandler(BaseHTTPCallback *handler);
176 
177  void Handlers(vector<string> *handlers) const;
178  const string DataDir() const { return m_data_dir; }
179 
180  // Return an error
181  int ServeError(HTTPResponse *response, const string &details="");
182  int ServeNotFound(HTTPResponse *response);
183  static int ServeRedirect(HTTPResponse *response, const string &location);
184 
185  // Return the contents of a file.
186  int ServeStaticContent(const string &path,
187  const string &content_type,
188  HTTPResponse *response);
189 
190  static const char CONTENT_TYPE_PLAIN[];
191  static const char CONTENT_TYPE_HTML[];
192  static const char CONTENT_TYPE_GIF[];
193  static const char CONTENT_TYPE_PNG[];
194  static const char CONTENT_TYPE_CSS[];
195  static const char CONTENT_TYPE_JS[];
196 
197  // Expose the SelectServer
198  ola::io::SelectServer *SelectServer() { return &m_select_server; }
199 
200  private :
201  typedef struct {
202  string file_path;
203  string content_type;
204  } static_file_info;
205 
206  typedef std::set<ola::io::UnmanagedFileDescriptor*,
208 
209  struct MHD_Daemon *m_httpd;
210  ola::io::SelectServer m_select_server;
211  SocketSet m_sockets;
212 
213  map<string, BaseHTTPCallback*> m_handlers;
214  map<string, static_file_info> m_static_content;
215  BaseHTTPCallback *m_default_handler;
216  unsigned int m_port;
217  string m_data_dir;
218 
219 
220  HTTPServer(const HTTPServer&);
221  HTTPServer& operator=(const HTTPServer&);
222 
223  int ServeStaticContent(static_file_info *file_info,
224  HTTPResponse *response);
225 
226  ola::io::UnmanagedFileDescriptor *NewSocket(fd_set *r_set,
227  fd_set *w_set,
228  int fd);
229 };
230 } // namespace http
231 } // namespace ola
232 #endif // INCLUDE_OLA_HTTP_HTTPSERVER_H_