#pragma once #include #include #include #include namespace acl { class HttpServletRequest; class HttpServletResponse; typedef HttpServletRequest HttpRequest; typedef HttpServletResponse HttpResponse; typedef std::function http_handler_t; typedef std::map http_handlers_t; enum { http_handler_get = 0, http_handler_post, http_handler_head, http_handler_put, http_handler_patch, http_handler_connect, http_handler_purge, http_handler_delete, http_handler_options, http_handler_profind, http_handler_websocket, http_handler_error, http_handler_unknown, http_handler_max, }; class http_servlet_impl : public HttpServlet { public: http_servlet_impl(http_handlers_t* handlers, socket_stream* stream, session* session) : HttpServlet(stream, session), handlers_(handlers) {} virtual ~http_servlet_impl(void) {} protected: // override bool doGet(HttpRequest& req, HttpResponse& res) { return doService(http_handler_get, req, res); } // override bool doPost(HttpRequest& req, HttpResponse& res) { return doService(http_handler_post, req, res); } // override bool doHead(HttpRequest& req, HttpResponse& res) { return doService(http_handler_head, req, res); } // override bool doPut(HttpRequest& req, HttpResponse& res) { return doService(http_handler_put, req, res); } // override bool doPatch(HttpRequest& req, HttpResponse& res) { return doService(http_handler_patch, req, res); } // override bool doConnect(HttpRequest& req, HttpResponse& res) { return doService(http_handler_connect, req, res); } // override bool doPurge(HttpRequest& req, HttpResponse& res) { return doService(http_handler_purge, req, res); } // override bool doDelete(HttpRequest& req, HttpResponse& res) { return doService(http_handler_delete, req, res); } // override bool doOptions(HttpRequest& req, HttpResponse& res) { return doService(http_handler_options, req, res); } // override bool doProfind(HttpRequest& req, HttpResponse& res) { return doService(http_handler_profind, req, res); } // override bool doWebsocket(HttpRequest& req, HttpResponse& res) { return doService(http_handler_websocket, req, res); } // override bool doUnknown(HttpRequest& req, HttpResponse& res) { return doService(http_handler_unknown, req, res); } // override bool doError(HttpRequest& req, HttpResponse& res) { return doService(http_handler_error, req, res); } private: bool doService(int type, HttpRequest& req, HttpResponse& res) { if (type < http_handler_get || type >= http_handler_max) { return false; } res.setKeepAlive(req.isKeepAlive()); bool keep = req.isKeepAlive(); const char* path = req.getPathInfo(); if (path == NULL || *path == 0) { res.setStatus(400); acl::string buf("404 bad request\r\n"); res.setContentLength(buf.size()); return res.write(buf.c_str(), buf.size()) && keep; } size_t len = strlen(path); acl::string buf(path); if (path[len - 1] != '/') { buf += '/'; } buf.lower(); std::map::iterator it = handlers_[type].find(buf); if (it != handlers_[type].end()) { return it->second(req, res) && keep; } res.setStatus(404); buf = "404 "; buf += path; buf += " not found\r\n"; res.setContentLength(buf.size()); return res.write(buf.c_str(), buf.size()) && keep; } private: http_handlers_t* handlers_; }; } // namespace acl