Permalink
Browse files

Add a simple request dispatcher and tests for it

  • Loading branch information...
1 parent 730956d commit 251d933bd1b591b6447b21e0d37014ee4421c1a4 @tadzik committed Apr 9, 2012
Showing with 178 additions and 1 deletion.
  1. +12 −1 Makefile
  2. +50 −0 dispatcher.cpp
  3. +20 −0 dispatcher.hpp
  4. +96 −0 dispatcher_test.cpp
View
@@ -3,11 +3,22 @@ CC=clang++
CFLAGS=-Wall -Wextra -pedantic
COMPILE= $(CC) $(CFLAGS)
+all: app
+
+test: dispatcher_test
+
app: csgi.o app.cpp
$(COMPILE) app.cpp csgi.o -o app
+dispatcher_test: csgi.o dispatcher.o dispatcher_test.cpp
+ $(COMPILE) dispatcher_test.cpp csgi.o dispatcher.o -o dispatcher_test
+ ./dispatcher_test
+
csgi.o: csgi.hpp csgi.cpp
$(COMPILE) -c csgi.cpp
+dispatcher.o: dispatcher.hpp dispatcher.cpp
+ $(COMPILE) -c dispatcher.cpp
+
clean:
- rm -f app csgi.o
+ rm -f *.o app dispatcher_test
View
@@ -0,0 +1,50 @@
+#include "dispatcher.hpp"
+#include <sstream>
+
+// removes leading and trailing slashes from a string
+std::string stripslashes(std::string s)
+{
+ if (s.at(0) == '/') s.erase(0, 1);
+ if (s.at(s.length() - 1) == '/') s.erase(s.length() - 1, 1);
+ return s;
+}
+
+CSGI::Response not_found_handler(CSGI::Env& env)
+{
+ CSGI::Response ret;
+
+ std::string body = "Not found";
+ std::stringstream len;
+ len << body.length();
+
+ ret.status = 404;
+ ret.headers["Content-Type"] = "text/plain";
+ ret.headers["Content-Length"] = len.str();
+ ret.content = body;
+
+ return ret;
+ (void)env;
+}
+
+Dispatcher::Dispatcher(CSGI::Application default_app)
+{
+ if (default_app != NULL) {
+ default_handler_ = default_app;
+ } else {
+ default_handler_ = not_found_handler;
+ }
+}
+
+void Dispatcher::add_handler(std::string s, CSGI::Application a)
+{
+ handlers_[stripslashes(s)] = a;
+}
+
+CSGI::Response Dispatcher::dispatch(CSGI::Env& env)
+{
+ CSGI::Application y = handlers_[stripslashes(env["REQUEST_URI"])];
+ if (y != NULL) {
+ return y(env);
+ }
+ return default_handler_(env);
+}
View
@@ -0,0 +1,20 @@
+#ifndef DISPATCHER_H
+#define DISPATCHER_H
+
+#include "csgi.hpp"
+
+#include <map>
+#include <string>
+
+class Dispatcher {
+public:
+ Dispatcher(CSGI::Application a);
+ // dispatch() is a CSGI application itself. Cool, eh?
+ CSGI::Response dispatch(CSGI::Env&);
+ void add_handler(std::string, CSGI::Application);
+private:
+ std::map<std::string, CSGI::Application> handlers_;
+ CSGI::Application default_handler_;
+};
+
+#endif
View
@@ -0,0 +1,96 @@
+#include "dispatcher.hpp"
+#include <cassert>
+#include <sstream>
+#include <iostream>
+
+std::string itoa(int i)
+{
+ std::stringstream out;
+ out << i;
+ return out.str();
+}
+
+CSGI::Response make_response(std::string body)
+{
+ CSGI::Response ret;
+
+ ret.status = 200;
+ ret.headers["Content-Type"] = "text/plain";
+ ret.headers["Content-Length"] = itoa(body.length());
+ ret.content = body;
+
+ return ret;
+}
+
+CSGI::Response hello_handler(CSGI::Env& e)
+{
+ return make_response("Hello, world!");
+ (void)e;
+}
+
+CSGI::Response aboot_handler(CSGI::Env& e)
+{
+ return make_response("Could you tell us again what your argument "
+ "is all ABOUT?");
+ (void)e;
+}
+
+CSGI::Response placki_handler(CSGI::Env& e)
+{
+ return make_response("Lubię placki!");
+ (void)e;
+}
+
+CSGI::Response another_handler(CSGI::Env& e)
+{
+ return make_response("Another prick in the wall");
+ (void)e;
+}
+
+void assert_status(Dispatcher& d, const char * uri, int status)
+{
+ CSGI::Env env;
+ env["REQUEST_URI"] = std::string(uri);
+ assert(d.dispatch(env).status == status);
+}
+
+void assert_found(Dispatcher& d, const char * uri)
+{
+ assert_status(d, uri, 200);
+}
+
+int main()
+{
+ Dispatcher dispatcher(NULL);
+
+ dispatcher.add_handler("/hello", hello_handler);
+ dispatcher.add_handler("aboot/", aboot_handler);
+ dispatcher.add_handler("/placki/", placki_handler);
+ dispatcher.add_handler("another", another_handler);
+
+ assert_found(dispatcher, "/hello");
+ assert_found(dispatcher, "/hello/");
+ assert_found(dispatcher, "hello/");
+ assert_found(dispatcher, "hello");
+
+ assert_found(dispatcher, "/aboot");
+ assert_found(dispatcher, "/aboot/");
+ assert_found(dispatcher, "aboot/");
+ assert_found(dispatcher, "aboot");
+
+ assert_found(dispatcher, "/placki");
+ assert_found(dispatcher, "/placki/");
+ assert_found(dispatcher, "placki/");
+ assert_found(dispatcher, "placki");
+
+ assert_found(dispatcher, "/another");
+ assert_found(dispatcher, "/another/");
+ assert_found(dispatcher, "another/");
+ assert_found(dispatcher, "another");
+
+ assert_status(dispatcher, "dupa", 404);
+
+ std::cerr << "All tests OK" << std::endl;
+
+ return 0;
+}

0 comments on commit 251d933

Please sign in to comment.