diff options
Diffstat (limited to 'src/uscxml/server')
-rw-r--r-- | src/uscxml/server/HTTPServer.cpp | 56 | ||||
-rw-r--r-- | src/uscxml/server/HTTPServer.h | 15 | ||||
-rw-r--r-- | src/uscxml/server/InterpreterServlet.cpp | 3 | ||||
-rw-r--r-- | src/uscxml/server/InterpreterServlet.h | 2 |
4 files changed, 45 insertions, 31 deletions
diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index bd24326..f4b1a57 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -72,7 +72,10 @@ std::map<std::string, std::string> HTTPServer::mimeTypes; HTTPServer* HTTPServer::getInstance(int port) { // tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); if (_instance == NULL) { - +#ifdef _WIN32 + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif // this is but a tiny list, supply a content-type <header> yourself mimeTypes["txt"] = "text/plain"; mimeTypes["c"] = "text/plain"; @@ -109,19 +112,16 @@ std::string HTTPServer::mimeTypeForExtension(const std::string& ext) { return ""; } +/** + * This callback is registered for all HTTP requests + */ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackData) { -// std::cout << (uintptr_t)req << ": Replying" << std::endl; -// evhttp_send_error(req, 404, NULL); -// return; - std::stringstream raw; evhttp_request_own(req); Request request; request.curlReq = req; - - switch (evhttp_request_get_command(req)) { case EVHTTP_REQ_GET: request.data.compound["type"] = Data("get", Data::VERBATIM); @@ -167,7 +167,7 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD const char* query = evhttp_uri_get_query(evhttp_request_get_evhttp_uri(req)); if (query) raw << "?" << std::string(query); - + raw << " HTTP/" << request.data.compound["httpMajor"].atom << "." << request.data.compound["httpMinor"].atom; raw << std::endl; @@ -237,40 +237,45 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD request.raw = raw.str(); - if (callbackData == NULL) { + // try with the handler registered for path first + bool answered = false; + if (callbackData != NULL) + answered = ((HTTPServlet*)callbackData)->httpRecvRequest(request); + + if (!answered) HTTPServer::getInstance()->processByMatchingServlet(request); - } else { - ((HTTPServlet*)callbackData)->httpRecvRequest(request); - } } + void HTTPServer::processByMatchingServlet(const Request& request) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); + servlet_iter_t servletIter = _servlets.begin(); std::string actualPath = request.data.compound.at("path").atom; - HTTPServlet* bestMatch = NULL; - std::string bestPath; + std::map<std::string, HTTPServlet*, comp_strsize_less> matches; while(servletIter != _servlets.end()) { // is the servlet path a prefix of the actual path? std::string servletPath = "/" + servletIter->first; if (boost::iequals(actualPath.substr(0, servletPath.length()), servletPath) && // actual path is a prefix - boost::iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/' - if (bestPath.length() < servletPath.length()) { - // this servlet is a better match - bestPath = servletPath; - bestMatch = servletIter->second; - } + boost::iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/' + matches.insert(std::make_pair(servletPath, servletIter->second)); } servletIter++; } - if (bestMatch != NULL) { - bestMatch->httpRecvRequest(request); - } else { - LOG(INFO) << "Got an HTTP request at " << actualPath << " but no servlet is registered there or at a prefix"; - evhttp_send_error(request.curlReq, 404, NULL); + // process by best matching servlet until someone feels responsible + std::map<std::string, HTTPServlet*, comp_strsize_less>::iterator matchesIter = matches.begin(); + while(matchesIter != matches.end()) { + if (matchesIter->second->httpRecvRequest(request)) { + return; + } + matchesIter++; } + + LOG(INFO) << "Got an HTTP request at " << actualPath << " but no servlet is registered there or at a prefix"; + evhttp_send_error(request.curlReq, 404, NULL); } void HTTPServer::reply(const Reply& reply) { @@ -281,7 +286,6 @@ void HTTPServer::reply(const Reply& reply) { } void HTTPServer::replyCallback(evutil_socket_t fd, short what, void *arg) { - Reply* reply = (Reply*)arg; if (reply->content.size() > 0 && reply->headers.find("Content-Type") == reply->headers.end()) { diff --git a/src/uscxml/server/HTTPServer.h b/src/uscxml/server/HTTPServer.h index bd54166..d216d5e 100644 --- a/src/uscxml/server/HTTPServer.h +++ b/src/uscxml/server/HTTPServer.h @@ -20,7 +20,7 @@ public: Request() : curlReq(NULL) {} std::string content; struct evhttp_request* curlReq; - + operator bool() { return curlReq != NULL; } @@ -50,6 +50,15 @@ public: static void unregisterServlet(HTTPServlet* servlet); private: + struct comp_strsize_less { + bool operator()(std::string const& l, std::string const& r) const { + if (l.size() < r.size()) + return false; + + return l < r; + }; + }; + HTTPServer(unsigned short port); ~HTTPServer(); @@ -86,11 +95,11 @@ private: class HTTPServlet { public: - virtual void httpRecvRequest(const HTTPServer::Request& request) = 0; + virtual bool httpRecvRequest(const HTTPServer::Request& request) = 0; + virtual void setURL(const std::string& url) = 0; /// Called by the server with the actual URL virtual bool canAdaptPath() { return true; } - virtual void setURL(const std::string& url) = 0; /// Called by the server with the actual URL }; } diff --git a/src/uscxml/server/InterpreterServlet.cpp b/src/uscxml/server/InterpreterServlet.cpp index 28b7c1b..b59cc05 100644 --- a/src/uscxml/server/InterpreterServlet.cpp +++ b/src/uscxml/server/InterpreterServlet.cpp @@ -24,7 +24,7 @@ boost::shared_ptr<IOProcessorImpl> InterpreterServlet::create(InterpreterImpl* i return io; } -void InterpreterServlet::httpRecvRequest(const HTTPServer::Request& req) { +bool InterpreterServlet::httpRecvRequest(const HTTPServer::Request& req) { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); // evhttp_request_own(req.curlReq); @@ -37,6 +37,7 @@ void InterpreterServlet::httpRecvRequest(const HTTPServer::Request& req) { event.origin = toStr((uintptr_t)req.curlReq); event.initContent(event.data.compound["content"].atom); _interpreter->receive(event); + return true; } Data InterpreterServlet::getDataModelVariables() { diff --git a/src/uscxml/server/InterpreterServlet.h b/src/uscxml/server/InterpreterServlet.h index 6c61e47..c00bd11 100644 --- a/src/uscxml/server/InterpreterServlet.h +++ b/src/uscxml/server/InterpreterServlet.h @@ -26,7 +26,7 @@ public: Data getDataModelVariables(); virtual void send(const SendRequest& req); - virtual void httpRecvRequest(const HTTPServer::Request& req); + virtual bool httpRecvRequest(const HTTPServer::Request& req); std::string getPath() { return _path; |