mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-02 20:08:21 +08:00
http module can response json&xml data
This commit is contained in:
parent
ccce38b52d
commit
dee4ebeaea
@ -37,7 +37,7 @@ public:
|
||||
* @param memcache_addr {const char*}
|
||||
*/
|
||||
HttpServlet(socket_stream* stream,
|
||||
const char* memcache_addr = "127.0.0.1:11211");
|
||||
const char* memcache_addr = "127.0.0.1|11211");
|
||||
|
||||
HttpServlet(void);
|
||||
virtual ~HttpServlet(void) = 0;
|
||||
|
@ -8,6 +8,8 @@ namespace acl {
|
||||
|
||||
class dbuf_guard;
|
||||
class string;
|
||||
class xml;
|
||||
class json;
|
||||
class ostream;
|
||||
class socket_stream;
|
||||
class http_header;
|
||||
@ -191,6 +193,22 @@ public:
|
||||
*/
|
||||
bool write(const string& buf);
|
||||
|
||||
/**
|
||||
* 向客户端发送 HTTP Xml 响应数据体
|
||||
* @param buf {const xml&} 数据缓冲区
|
||||
* @param charset {const char*} 数据体字符集
|
||||
* @return {bool} 发送是否成功,如果返回 false 表示连接中断
|
||||
*/
|
||||
bool write(const xml& body, const char* charset = "utf-8");
|
||||
|
||||
/**
|
||||
* 向客户端发送 HTTP Json 响应数据体
|
||||
* @param buf {const json&} 数据缓冲区
|
||||
* @param charset {const char*} 数据体字符集
|
||||
* @return {bool} 发送是否成功,如果返回 false 表示连接中断
|
||||
*/
|
||||
bool write(const json& body, const char* charset = "utf-8");
|
||||
|
||||
/**
|
||||
* 带格式方式向 HTTP 客户端发送响应数据,内部自动调用
|
||||
* HttpServletResponse::write(const void*, size_t) 过程,在使用
|
||||
|
@ -434,7 +434,7 @@ public:
|
||||
* 判断当前 HTTP 传输是否采用 chunked 传输方式
|
||||
* @return {bool}
|
||||
*/
|
||||
bool chunked_transfer() const
|
||||
bool chunked_transfer(void) const
|
||||
{
|
||||
return chunked_transfer_;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ typedef enum
|
||||
HTTP_METHOD_HEAD, // HEAD 方法
|
||||
HTTP_METHOD_OPTION, // OPTION 方法
|
||||
HTTP_METHOD_PROPFIND, // PROPFIND 方法
|
||||
HTTP_METHOD_PATCH, // PATCH 方法
|
||||
HTTP_METHOD_PATCH, // PATCH 方法
|
||||
HTTP_METHOD_OTHER, // 其它的方法
|
||||
} http_method_t;
|
||||
|
||||
|
@ -24,7 +24,7 @@ HttpServlet::HttpServlet(socket_stream* stream, session* session)
|
||||
init();
|
||||
|
||||
if (session == NULL) {
|
||||
session_ = NEW memcache_session("127.0.0.1");
|
||||
session_ = NEW memcache_session("127.0.0.1|11211");
|
||||
session_ptr_ = session_;
|
||||
} else {
|
||||
session_ = session;
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "acl_cpp/stdlib/dbuf_pool.hpp"
|
||||
#include "acl_cpp/stdlib/snprintf.hpp"
|
||||
#include "acl_cpp/stdlib/string.hpp"
|
||||
#include "acl_cpp/stdlib/xml.hpp"
|
||||
#include "acl_cpp/stdlib/json.hpp"
|
||||
#include "acl_cpp/stream/ostream.hpp"
|
||||
#include "acl_cpp/stream/socket_stream.hpp"
|
||||
#include "acl_cpp/http/http_header.hpp"
|
||||
@ -223,6 +225,39 @@ int HttpServletResponse::format(const char* fmt, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HttpServletResponse::write(const xml& body, const char* charset /* utf-8 */)
|
||||
{
|
||||
if (charset && *charset) {
|
||||
setCharacterEncoding(charset);
|
||||
}
|
||||
setContentType("application/xml");
|
||||
|
||||
const string& buf = body.to_string();
|
||||
if (!header_->chunked_transfer()) {
|
||||
setContentLength(buf.size());
|
||||
return write(buf.c_str(), buf.size());
|
||||
}
|
||||
|
||||
return write(buf.c_str(), buf.size()) && write(NULL, 0);
|
||||
}
|
||||
|
||||
bool HttpServletResponse::write(const json& body, const char* charset /* utf-8 */)
|
||||
{
|
||||
if (charset && *charset) {
|
||||
setCharacterEncoding(charset);
|
||||
}
|
||||
setContentType("application/json");
|
||||
|
||||
const string& buf = body.to_string();
|
||||
|
||||
if (!header_->chunked_transfer()) {
|
||||
setContentLength(buf.size());
|
||||
return write(buf.c_str(), buf.size());
|
||||
}
|
||||
|
||||
return write(buf.c_str(), buf.size()) && write(NULL, 0);
|
||||
}
|
||||
|
||||
void HttpServletResponse::encodeUrl(string& out, const char* url)
|
||||
{
|
||||
out.clear();
|
||||
|
@ -15,47 +15,62 @@ typedef std::function<bool(acl::socket_stream&)> thread_accept_t;
|
||||
|
||||
class http_server_impl : public master_fiber {
|
||||
public:
|
||||
http_server_impl(void) {}
|
||||
http_server_impl(const char* addr, bool use_redis) {
|
||||
if (use_redis) {
|
||||
redis_ = new redis_client_cluster;
|
||||
redis_->init(NULL, addr, 0, 10, 10);
|
||||
redis_->bind_thread(true);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~http_server_impl(void) {}
|
||||
|
||||
public:
|
||||
http_server_impl& service(const std::string& path, handler_t fn) {
|
||||
return service(path.c_str(), fn);
|
||||
}
|
||||
void onService(int type, const char* path, http_handler_t fn) {
|
||||
if (type >= http_handler_get && type < http_handler_max
|
||||
&& path && *path) {
|
||||
|
||||
// The path should lookup like as "/xxx/" with
|
||||
// lower charactors.
|
||||
|
||||
http_server_impl& service(const char* path, handler_t fn) {
|
||||
if (path && *path) {
|
||||
acl::string buf(path);
|
||||
if (buf[buf.size() - 1] != '/') {
|
||||
buf += '/';
|
||||
}
|
||||
buf.lower();
|
||||
handlers_[buf] = std::move(fn);
|
||||
handlers_[type][buf] = std::move(fn);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::map<acl::string, handler_t> handlers_;
|
||||
redis_client_cluster* redis_ = nullptr;
|
||||
proc_jail_t proc_jail_ = nullptr;
|
||||
proc_init_t proc_init_ = nullptr;
|
||||
proc_exit_t proc_exit_ = nullptr;
|
||||
proc_sighup_t proc_sighup_ = nullptr;
|
||||
thread_init_t thread_init_ = nullptr;
|
||||
thread_accept_t thread_accept_ = nullptr;
|
||||
http_handlers_t handlers_[http_handler_max];
|
||||
|
||||
// @override
|
||||
void on_accept(socket_stream& conn) {
|
||||
if (thread_accept_) {
|
||||
if (!thread_accept_(conn)) {
|
||||
return;
|
||||
}
|
||||
if (thread_accept_ && !thread_accept_(conn)) {
|
||||
return;
|
||||
}
|
||||
memcache_session session("127.0.0.1:11211");
|
||||
http_servlet servlet(handlers_, &conn, &session);
|
||||
servlet.setLocalCharset("gb2312");
|
||||
|
||||
acl::session* session;
|
||||
if (redis_) {
|
||||
session = new redis_session(*redis_, 0);
|
||||
} else {
|
||||
session = new memcache_session("127.0.0.1|11211");
|
||||
}
|
||||
|
||||
http_servlet servlet(handlers_, &conn, session);
|
||||
servlet.setLocalCharset("utf-8");
|
||||
|
||||
while (servlet.doRun()) {}
|
||||
|
||||
delete session;
|
||||
}
|
||||
|
||||
// @override
|
||||
|
@ -10,14 +10,32 @@ namespace acl {
|
||||
class HttpServletRequest;
|
||||
class HttpServletResponse;
|
||||
|
||||
typedef HttpServletRequest request_t;
|
||||
typedef HttpServletResponse response_t;
|
||||
typedef HttpServletRequest HttpRequest;
|
||||
typedef HttpServletResponse HttpResponse;
|
||||
|
||||
typedef std::function<bool(request_t&, response_t&)> handler_t;
|
||||
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,
|
||||
};
|
||||
|
||||
class http_servlet_impl : public HttpServlet {
|
||||
public:
|
||||
http_servlet_impl(std::map<acl::string, handler_t>& handlers,
|
||||
http_servlet_impl(http_handlers_t* handlers,
|
||||
socket_stream* stream, session* session)
|
||||
: HttpServlet(stream, session), handlers_(handlers) {}
|
||||
|
||||
@ -25,12 +43,76 @@ public:
|
||||
|
||||
protected:
|
||||
// override
|
||||
bool doGet(request_t& req, response_t& res) {
|
||||
return doPost(req, res);
|
||||
bool doGet(HttpRequest& req, HttpResponse& res) {
|
||||
return doService(http_handler_get, req, res);
|
||||
}
|
||||
|
||||
// override
|
||||
bool doPost(request_t& req, response_t& res) {
|
||||
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();
|
||||
|
||||
@ -49,10 +131,10 @@ protected:
|
||||
}
|
||||
buf.lower();
|
||||
|
||||
std::map<acl::string, handler_t>::iterator it
|
||||
= handlers_.find(buf);
|
||||
std::map<acl::string, http_handler_t>::iterator it
|
||||
= handlers_[type].find(buf);
|
||||
|
||||
if (it != handlers_.end()) {
|
||||
if (it != handlers_[type].end()) {
|
||||
return it->second(req, res) && keep;
|
||||
}
|
||||
|
||||
@ -65,7 +147,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<acl::string, handler_t> handlers_;
|
||||
http_handlers_t* handlers_;
|
||||
};
|
||||
|
||||
} // namespace acl
|
||||
|
@ -7,17 +7,67 @@ namespace acl {
|
||||
|
||||
class http_server : public http_server_impl {
|
||||
public:
|
||||
http_server(void) {}
|
||||
http_server(const char* addr = "127.0.0.1|6379", bool use_redis = true) : http_server_impl(addr, use_redis) {}
|
||||
~http_server(void) {}
|
||||
|
||||
public:
|
||||
http_server& get(const std::string path, handler_t fn) {
|
||||
this->service(path, fn);
|
||||
http_server& onGet(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_get, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& post(const std::string& path, handler_t fn) {
|
||||
this->service(path, fn);
|
||||
http_server& onPost(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_post, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onHead(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_head, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onPut(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_put, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onPatch(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_patch, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onConnect(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_connect, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onPurge(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_purge, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onDelete(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_delete, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onOptions(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_options, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onPropfind(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_profind, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onError(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_error, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
http_server& onWebsocket(const char* path, http_handler_t fn) {
|
||||
this->onService(http_handler_websocket, path, fn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace acl {
|
||||
|
||||
class http_servlet : public http_servlet_impl {
|
||||
public:
|
||||
http_servlet(std::map<acl::string, handler_t>& handlers,
|
||||
http_servlet(http_handlers_t* handlers,
|
||||
socket_stream* stream, session* session)
|
||||
: http_servlet_impl(handlers, stream, session) {}
|
||||
|
||||
|
@ -67,19 +67,30 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// set http route
|
||||
|
||||
server.get("/", [](acl::request_t&, acl::response_t& res) {
|
||||
server.onGet("/", [](acl::HttpRequest&, acl::HttpResponse& res) {
|
||||
acl::string buf("hello world1!\r\n");
|
||||
res.setContentLength(buf.size());
|
||||
return res.write(buf.c_str(), buf.size());
|
||||
}).get("/hello", [](acl::request_t&, acl::response_t& res) {
|
||||
}).onGet("/hello", [](acl::HttpRequest&, acl::HttpResponse& res) {
|
||||
acl::string buf("hello world2!\r\n");
|
||||
res.setContentLength(buf.size());
|
||||
return res.write(buf.c_str(), buf.size());
|
||||
}).post("/ok", [](acl::request_t& req, acl::response_t& res) {
|
||||
}).onPost("/ok", [](acl::HttpRequest& req, acl::HttpResponse& res) {
|
||||
acl::string buf;
|
||||
req.getBody(buf);
|
||||
res.setContentLength(buf.size());
|
||||
return res.write(buf.c_str(), buf.size());
|
||||
}).onGet("/json", [](acl::HttpRequest&, acl::HttpResponse& res) {
|
||||
acl::json json;
|
||||
acl::json_node& root = json.get_root();
|
||||
root.add_number("code", 200)
|
||||
.add_text("status", "+ok")
|
||||
.add_child("data",
|
||||
json.create_node()
|
||||
.add_text("name", "value")
|
||||
.add_bool("success", true)
|
||||
.add_number("number", 100));
|
||||
return res.write(json);
|
||||
});
|
||||
|
||||
// start the server in alone or daemon mode
|
||||
|
Loading…
Reference in New Issue
Block a user