Add an example of Http::Server usage
authorMikko Rasa <tdb@tdb.fi>
Wed, 10 Aug 2011 19:31:42 +0000 (22:31 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 10 Aug 2011 19:31:42 +0000 (22:31 +0300)
.gitignore
Build
examples/minihttpd.cpp [new file with mode: 0644]

index d16c915753cb82b919e385791baadfc5de25db73..8c908ea71bc5589980b2f77b07df74473c130e74 100644 (file)
@@ -5,6 +5,7 @@
 /httpget
 /libmspnet.a
 /libmspnet.so
+/minihttpd
 /mspnet.pc
 /netcat
 /pc-32-windows
diff --git a/Build b/Build
index 47032c49d60cceabb380eb2fd5e8dd4d467a72c4..01d3a842699b8f7ac2c705c7c9440b9981eb6df6 100644 (file)
--- a/Build
+++ b/Build
@@ -45,4 +45,13 @@ package "mspnet"
                        library "mspnet";
                };
        };
+
+       program "minihttpd"
+       {
+               source "examples/minihttpd.cpp";
+               build_info
+               {
+                       library "mspnet";
+               };
+       };
 };
diff --git a/examples/minihttpd.cpp b/examples/minihttpd.cpp
new file mode 100644 (file)
index 0000000..b59b0f9
--- /dev/null
@@ -0,0 +1,92 @@
+#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");
+       }
+}