blob: 99eb29572f2fe8614dbc86dfc11bd94edec2e33a [file] [log] [blame]
#include "event2/buffer.h"
#include "event2/http.h"
#include <string>
namespace aos {
namespace http {
// An HTTP server that serves files from a directory using libevent.
// Also allows configuring certain URLs to be dynamically generated.
class HTTPServer {
public:
HTTPServer(const char *directory, uint16_t port);
// Starts serving pages.
// Might not clean up everything before returning.
void Run();
protected:
template<class T> class MemberHandler {
public:
typedef void (T::*Handler)(evhttp_request *);
struct Holder {
T *self;
Handler handler;
};
static void Call(evhttp_request *request, void *handler_in) {
const Holder *const holder = static_cast<Holder *>(handler_in);
AddStandardHeaders(request);
((holder->self)->*(holder->handler))(request);
}
};
void AddPage(const std::string &path, void (*handler)(evhttp_request *, void *),
void *data);
template<class T> void AddPage(const std::string &path,
typename MemberHandler<T>::Handler handler,
T *self) {
// have to put "typename" in, so the typedef makes it clearer
typedef typename MemberHandler<T>::Holder HolderType;
AddPage(path, MemberHandler<T>::Call, new HolderType{self, handler});
}
// This gets set up as the generic handler.
// It can also be called separately to serve the file that the request is
// requesting from the filesystem.
void ServeFile(evhttp_request *request);
private:
// The directory where files to be served come from.
const char *directory_;
// The main libevent structure.
event_base *const base_;
// The libevent HTTP server handle.
evhttp *const http_;
static void AddStandardHeaders(evhttp_request *request);
static void StaticServeFile(evhttp_request *request, void *self) {
static_cast<HTTPServer *>(self)->ServeFile(request);
}
};
} // namespace http
} // namespace aos