From 0f0db0ee56b69d580fe66528a379fb08d714bf4d Mon Sep 17 00:00:00 2001 From: Pixel Date: Fri, 18 Nov 2011 22:52:12 -0800 Subject: Starting to re-organize the HTTP code a bit. Sharing code between the server and a potential client makes sense. Also packing requests and responses into structures / classes is probably a good idea. --- includes/Http.h | 18 ++++++++++++++++++ includes/HttpServer.h | 12 +++++------- src/HttpServer.cc | 32 ++++++++++++++++++++------------ tests/test-Http.cc | 4 ++-- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/includes/Http.h b/includes/Http.h index cbb118f..cd7973f 100644 --- a/includes/Http.h +++ b/includes/Http.h @@ -1,9 +1,27 @@ #pragma once +#include +#include +#include + namespace Balau { namespace Http { +typedef std::map StringMap; +typedef std::map > FileList; + +class Request { + public: + int method; + String host; + String uri; + StringMap variables; + StringMap headers; + FileList files; + bool persistent; +}; + enum { GET, POST, diff --git a/includes/HttpServer.h b/includes/HttpServer.h index c2e8992..f78a816 100644 --- a/includes/HttpServer.h +++ b/includes/HttpServer.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Balau { @@ -17,19 +18,16 @@ class HttpWorker; class HttpServer { public: - typedef std::map StringMap; - typedef std::map > FileList; - class Action { public: Action(Regex & regex, Regex & host = Regexes::any) : m_regex(regex), m_host(host), m_refCount(0) { } ~Action() { Assert(m_refCount == 0); } - typedef std::pair ActionMatches; - ActionMatches matches(const char * uri, const char * host); + typedef std::pair ActionMatch; + ActionMatch matches(const char * uri, const char * host); void unref() { if (Atomic::Decrement(&m_refCount) == 0) delete this; } void ref() { Atomic::Increment(&m_refCount); } void registerMe(HttpServer * server) { server->registerAction(this); } - virtual bool Do(HttpServer * server, ActionMatches & m, IO out, StringMap & vars, StringMap & headers, FileList & files) = 0; + virtual bool Do(HttpServer * server, Http::Request & req, ActionMatch & match, IO out) = 0; private: Regex m_regex, m_host; volatile int m_refCount; @@ -43,7 +41,7 @@ class HttpServer { void setLocal(const char * local) { Assert(!m_started); m_local = local; } void registerAction(Action * action); void flushAllActions(); - typedef std::pair ActionFound; + typedef std::pair ActionFound; ActionFound findAction(const char * uri, const char * host); private: bool m_started; diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 6afb074..d99e1ea 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -20,7 +20,7 @@ class HttpWorker : public Task { void send400(); void send404(); String httpUnescape(const char * in); - void readVariables(HttpServer::StringMap & variables, char * str); + void readVariables(Http::StringMap & variables, char * str); IO m_socket; IO m_strm; @@ -70,7 +70,7 @@ Balau::String Balau::HttpWorker::httpUnescape(const char * in) { return r; } -void Balau::HttpWorker::readVariables(HttpServer::StringMap & variables, char * str) { +void Balau::HttpWorker::readVariables(Http::StringMap & variables, char * str) { char * ampPos; do { ampPos = strchr(str, '&'); @@ -146,9 +146,9 @@ bool Balau::HttpWorker::handleClient() { String host; String uri; String httpVersion; - HttpServer::StringMap httpHeaders; - HttpServer::StringMap variables; - HttpServer::FileList files; + Http::StringMap httpHeaders; + Http::StringMap variables; + Http::FileList files; bool persistent = false; // read client's request @@ -251,7 +251,7 @@ bool Balau::HttpWorker::handleClient() { } if (httpVersion == "1.1") { - HttpServer::StringMap::iterator i = httpHeaders.find("Connection"); + Http::StringMap::iterator i = httpHeaders.find("Connection"); if (i != httpHeaders.end()) { if (i->second == "close") { @@ -270,7 +270,7 @@ bool Balau::HttpWorker::handleClient() { if (method == Http::POST) { int length = 0; - HttpServer::StringMap::iterator i; + Http::StringMap::iterator i; bool multipart = false; String boundary; @@ -289,7 +289,7 @@ bool Balau::HttpWorker::handleClient() { send400(); return false; } - HttpServer::StringMap t; + Http::StringMap t; char * b = i->second.extract(sizeof(multipartStr) + 1).do_trim().strdup(); readVariables(t, b); free(b); @@ -351,7 +351,7 @@ bool Balau::HttpWorker::handleClient() { } } - HttpServer::StringMap::iterator hostIter = httpHeaders.find("host"); + Http::StringMap::iterator hostIter = httpHeaders.find("host"); if (hostIter != httpHeaders.end()) { if (host != "") { @@ -367,7 +367,15 @@ bool Balau::HttpWorker::handleClient() { HttpServer::ActionFound f = m_server->findAction(uri.to_charp(), host.to_charp()); if (f.first) { - if (!f.first->Do(m_server, f.second, m_socket, variables, httpHeaders, files)) { + Http::Request req; + req.method = method; + req.host = host; + req.uri = uri; + req.variables = variables; + req.headers = httpHeaders; + req.files = files; + req.persistent = persistent; + if (!f.first->Do(m_server, req, f.second, m_socket)) { persistent = false; } } else { @@ -421,8 +429,8 @@ void Balau::HttpServer::flushAllActions() { m_actionsLock.leave(); } -Balau::HttpServer::Action::ActionMatches Balau::HttpServer::Action::matches(const char * uri, const char * host) { - ActionMatches r; +Balau::HttpServer::Action::ActionMatch Balau::HttpServer::Action::matches(const char * uri, const char * host) { + ActionMatch r; r.second = m_host.match(host); if (r.second.empty()) diff --git a/tests/test-Http.cc b/tests/test-Http.cc index 496d7e6..de3c6f3 100644 --- a/tests/test-Http.cc +++ b/tests/test-Http.cc @@ -10,10 +10,10 @@ using namespace Balau; class TestAction : public HttpServer::Action { public: TestAction() : Action(Regexes::any) { } - virtual bool Do(HttpServer * server, HttpServer::Action::ActionMatches & m, IO out, HttpServer::StringMap & vars, HttpServer::StringMap & headers, HttpServer::FileList & files); + virtual bool Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out); }; -bool TestAction::Do(HttpServer * server, HttpServer::Action::ActionMatches & m, IO out, HttpServer::StringMap & vars, HttpServer::StringMap & headers, HttpServer::FileList & files) { +bool TestAction::Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) { static const char str[] = "HTTP/1.1 200 Found\r\n" "Content-Type: text/html; charset=UTF-8\r\n" -- cgit v1.2.3