2020-06-24 16:46:05 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
namespace acl {
|
|
|
|
|
|
|
|
class HttpServletRequest;
|
|
|
|
class HttpServletResponse;
|
|
|
|
|
2020-06-26 15:21:13 +08:00
|
|
|
typedef HttpServletRequest HttpRequest;
|
|
|
|
typedef HttpServletResponse HttpResponse;
|
|
|
|
|
|
|
|
typedef std::function<bool(HttpRequest&, HttpResponse&)> http_handler_t;
|
|
|
|
typedef std::map<acl::string, http_handler_t> 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,
|
|
|
|
};
|
2020-06-24 16:46:05 +08:00
|
|
|
|
|
|
|
class http_servlet_impl : public HttpServlet {
|
|
|
|
public:
|
2020-06-26 15:21:13 +08:00
|
|
|
http_servlet_impl(http_handlers_t* handlers,
|
2020-06-24 16:46:05 +08:00
|
|
|
socket_stream* stream, session* session)
|
|
|
|
: HttpServlet(stream, session), handlers_(handlers) {}
|
|
|
|
|
|
|
|
virtual ~http_servlet_impl(void) {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// override
|
2020-06-26 15:21:13 +08:00
|
|
|
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);
|
2020-06-24 16:46:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// override
|
2020-06-26 15:21:13 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-24 16:46:05 +08:00
|
|
|
res.setKeepAlive(req.isKeepAlive());
|
|
|
|
bool keep = req.isKeepAlive();
|
|
|
|
|
|
|
|
const char* path = req.getPathInfo();
|
|
|
|
if (path == NULL || *path == 0) {
|
|
|
|
res.setStatus(400);
|
2020-06-24 17:35:37 +08:00
|
|
|
acl::string buf("404 bad request\r\n");
|
|
|
|
res.setContentLength(buf.size());
|
2020-06-24 16:46:05 +08:00
|
|
|
return res.write(buf.c_str(), buf.size()) && keep;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t len = strlen(path);
|
2020-06-24 17:35:37 +08:00
|
|
|
acl::string buf(path);
|
|
|
|
if (path[len - 1] != '/') {
|
2020-06-24 16:46:05 +08:00
|
|
|
buf += '/';
|
|
|
|
}
|
2020-06-24 17:35:37 +08:00
|
|
|
buf.lower();
|
|
|
|
|
2020-06-26 15:21:13 +08:00
|
|
|
std::map<acl::string, http_handler_t>::iterator it
|
|
|
|
= handlers_[type].find(buf);
|
2020-06-24 17:35:37 +08:00
|
|
|
|
2020-06-26 15:21:13 +08:00
|
|
|
if (it != handlers_[type].end()) {
|
2020-06-24 16:46:05 +08:00
|
|
|
return it->second(req, res) && keep;
|
|
|
|
}
|
|
|
|
|
|
|
|
res.setStatus(404);
|
2020-06-24 17:35:37 +08:00
|
|
|
buf = "404 ";
|
|
|
|
buf += path;
|
|
|
|
buf += " not found\r\n";
|
|
|
|
res.setContentLength(buf.size());
|
2020-06-24 16:46:05 +08:00
|
|
|
return res.write(buf.c_str(), buf.size()) && keep;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-06-26 15:21:13 +08:00
|
|
|
http_handlers_t* handlers_;
|
2020-06-24 16:46:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace acl
|