]> git.tdb.fi Git - libs/net.git/blob - examples/minihttpd.cpp
Some largely cosmetic touch-up
[libs/net.git] / examples / minihttpd.cpp
1 #include <msp/core/application.h>
2 #include <msp/debug/demangle.h>
3 #include <msp/fs/dir.h>
4 #include <msp/fs/path.h>
5 #include <msp/fs/utils.h>
6 #include <msp/http/request.h>
7 #include <msp/http/response.h>
8 #include <msp/http/server.h>
9 #include <msp/io/eventdispatcher.h>
10 #include <msp/io/file.h>
11 #include <msp/io/print.h>
12 #include <msp/strings/utils.h>
13
14 using namespace std;
15 using namespace Msp;
16
17 class MiniHttpd: public RegisteredApplication<MiniHttpd>
18 {
19 private:
20         FS::Path root;
21         Http::Server server;
22         IO::EventDispatcher event_disp;
23
24 public:
25         MiniHttpd(int, char **);
26
27 private:
28         virtual void tick();
29
30         void request(const Http::Request &, Http::Response &);
31 };
32
33 MiniHttpd::MiniHttpd(int argc, char **argv):
34         root(FS::getcwd()),
35         server(8080)
36 {
37         if(argc>1)
38                 root /= argv[1];
39         server.signal_request.connect(sigc::mem_fun(this, &MiniHttpd::request));
40         server.use_event_dispatcher(&event_disp);
41 }
42
43 void MiniHttpd::tick()
44 {
45         event_disp.tick();
46 }
47
48 void MiniHttpd::request(const Http::Request &req, Http::Response &resp)
49 {
50         IO::print("%s requests \"%s\"\n", req.get_header("-Client-Host"), c_escape(req.get_path()));
51
52         FS::Path path = root/req.get_path().substr(1);
53         if(FS::descendant_depth(path, root)<0)
54         {
55                 resp = Http::Response(Http::FORBIDDEN);
56                 resp.add_content("You do not have permission to access the requested resource\n");
57                 return;
58         }
59
60         try
61         {
62                 IO::BufferedFile file(path.str());
63                 resp = Http::Response(Http::OK);
64                 if(FS::extpart(path.str())==".html")
65                         resp.set_header("Content-Type", "text/html");
66                 char buf[1024];
67                 while(1)
68                 {
69                         unsigned len = file.read(buf, sizeof(buf));
70                         if(!len)
71                                 break;
72                         resp.add_content(string(buf, len));
73                 }
74         }
75         catch(const IO::file_not_found &)
76         {
77                 resp = Http::Response(Http::NOT_FOUND);
78                 resp.add_content("The requested resource was not found\n");
79         }
80         catch(const exception &e)
81         {
82                 resp = Http::Response(Http::INTERNAL_ERROR);
83                 resp.add_content(format("An exception occurred while trying to retrieve %s:\n", req.get_path()));
84                 resp.add_content(format("  type:   %s\n", Debug::demangle(typeid(e).name())));
85                 resp.add_content(format("  what(): %s\n", e.what()));
86         }
87         catch(...)
88         {
89                 resp = Http::Response(Http::INTERNAL_ERROR);
90                 resp.add_content("Something horrible happened and I can't even tell what it was!\n");
91         }
92 }