--- /dev/null
+#include <msp/core/application.h>
+#include <msp/debug/demangle.h>
+#include <msp/fs/dir.h>
+#include <msp/fs/path.h>
+#include <msp/fs/utils.h>
+#include <msp/http/request.h>
+#include <msp/http/response.h>
+#include <msp/http/server.h>
+#include <msp/io/eventdispatcher.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+
+using namespace std;
+using namespace Msp;
+
+class MiniHttpd: public RegisteredApplication<MiniHttpd>
+{
+private:
+ FS::Path root;
+ Http::Server server;
+ IO::EventDispatcher event_disp;
+
+public:
+ MiniHttpd(int, char **);
+
+private:
+ virtual void tick();
+
+ void request(const Http::Request &, Http::Response &);
+};
+
+MiniHttpd::MiniHttpd(int argc, char **argv):
+ root(FS::getcwd()),
+ server(8080)
+{
+ if(argc>1)
+ root /= argv[1];
+ server.signal_request.connect(sigc::mem_fun(this, &MiniHttpd::request));
+ server.use_event_dispatcher(&event_disp);
+}
+
+void MiniHttpd::tick()
+{
+ event_disp.tick();
+}
+
+void MiniHttpd::request(const Http::Request &req, Http::Response &resp)
+{
+ IO::print("%s requests \"%s\"\n", req.get_header("-Client-Host"), c_escape(req.get_path()));
+
+ FS::Path path = root/req.get_path().substr(1);
+ if(FS::descendant_depth(path, root)<0)
+ {
+ resp = Http::Response(Http::FORBIDDEN);
+ resp.add_content("You do not have permission to access the requested resource\n");
+ return;
+ }
+
+ try
+ {
+ IO::BufferedFile file(path.str());
+ resp = Http::Response(Http::OK);
+ if(FS::extpart(path.str())==".html")
+ resp.set_header("Content-Type", "text/html");
+ char buf[1024];
+ while(1)
+ {
+ unsigned len = file.read(buf, sizeof(buf));
+ if(!len)
+ break;
+ resp.add_content(string(buf, len));
+ }
+ }
+ catch(const IO::file_not_found &)
+ {
+ resp = Http::Response(Http::NOT_FOUND);
+ resp.add_content("The requested resource was not found\n");
+ }
+ catch(const exception &e)
+ {
+ resp = Http::Response(Http::INTERNAL_ERROR);
+ resp.add_content(format("An exception occurred while trying to retrieve %s:\n", req.get_path()));
+ resp.add_content(format(" type: %s\n", Debug::demangle(typeid(e).name())));
+ resp.add_content(format(" what(): %s\n", e.what()));
+ }
+ catch(...)
+ {
+ resp = Http::Response(Http::INTERNAL_ERROR);
+ resp.add_content("Something horrible happened and I can't even tell what it was!\n");
+ }
+}