2014-11-19 00:25:21 +08:00
|
|
|
|
// http_servlet.cpp : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̨Ӧ<CCA8>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㡣
|
|
|
|
|
//
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include "acl_cpp/lib_acl.hpp"
|
|
|
|
|
|
|
|
|
|
static void (*format)(const char*, ...) = acl::log::msg1;
|
|
|
|
|
|
|
|
|
|
using namespace acl;
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class master_service : public master_proc
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
master_service(const char* to_charset = "gb2312")
|
|
|
|
|
{
|
|
|
|
|
local_charset_ = to_charset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~master_service() {}
|
|
|
|
|
|
|
|
|
|
void set_charset(const char* to_charset)
|
|
|
|
|
{
|
|
|
|
|
local_charset_ = to_charset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
|
|
|
|
|
virtual void on_accept(socket_stream* stream)
|
|
|
|
|
{
|
|
|
|
|
http_response res(stream);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ͻ<EFBFBD><CDBB>˵<EFBFBD> HTTP <20><><EFBFBD><EFBFBD>ͷ
|
|
|
|
|
if (res.read_header() == false)
|
|
|
|
|
{
|
|
|
|
|
const char* ptr = "read request header error";
|
|
|
|
|
res.response_header().set_status(400).set_keep_alive(false);
|
|
|
|
|
res.response(ptr, strlen(ptr));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><> HTTP <20><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ȡ<EFBFBD><C8A1> Content-Type <20>ֶ<EFBFBD>ֵ
|
|
|
|
|
// Content-Type: text/xml; charset=utf-8
|
|
|
|
|
http_client* client = res.get_client();
|
|
|
|
|
assert(client);
|
|
|
|
|
const char* p = client->header_value("Content-Type");
|
|
|
|
|
if (p == NULL || *p == 0)
|
|
|
|
|
{
|
|
|
|
|
const char* ptr = "no Content-Type";
|
|
|
|
|
res.response_header().set_status(400).set_keep_alive(false);
|
|
|
|
|
res.response(ptr, strlen(ptr));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><> HTTP <20><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD>У<EFBFBD>Content-Type: text/xml; charset=utf-8
|
|
|
|
|
// <20><> get_stype ȡ<><C8A1> xml <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
http_ctype content_type;
|
|
|
|
|
content_type.parse(p);
|
|
|
|
|
const char* stype = content_type.get_stype();
|
|
|
|
|
const char* req_charset = content_type.get_charset();
|
|
|
|
|
|
|
|
|
|
bool ret;
|
|
|
|
|
string err;
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵IJ<CDB5>ͬ<EFBFBD><CDAC><EFBFBD>ò<EFBFBD>ͬ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
if (stype == NULL)
|
|
|
|
|
ret = do_plain(res, req_charset, err);
|
|
|
|
|
|
|
|
|
|
// text/xml <20><>ʽ
|
|
|
|
|
else if (strcasecmp(stype, "xml") == 0)
|
|
|
|
|
ret = do_xml(res, req_charset, err);
|
|
|
|
|
|
|
|
|
|
// text/json <20><>ʽ
|
|
|
|
|
else if (strcasecmp(stype, "json") == 0)
|
|
|
|
|
ret = do_json(res, req_charset, err);
|
|
|
|
|
else
|
|
|
|
|
ret = do_plain(res, req_charset, err);
|
|
|
|
|
if (ret == false)
|
|
|
|
|
res.response(err.c_str(), err.length());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> text/plain <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
bool do_plain(http_response& res, const char* req_charset, string& err)
|
|
|
|
|
{
|
|
|
|
|
string body;
|
|
|
|
|
if (res.get_body(body, local_charset_) == false)
|
|
|
|
|
{
|
|
|
|
|
err += "get_body error";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
printf("body:\r\n(%s)\r\n", body.c_str());
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧͷ<D3A6>ֶ<EFBFBD>
|
|
|
|
|
http_header& header = res.response_header();
|
|
|
|
|
string ctype("text/plain");
|
|
|
|
|
if (req_charset)
|
|
|
|
|
{
|
|
|
|
|
ctype << "; charset=" << req_charset;
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
|
|
|
|
|
printf(">>ctype: %s\r\n", ctype.c_str());
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
return response_body(res, body, req_charset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> text/xml <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
bool do_xml(http_response& res, const char* req_charset, string& err)
|
|
|
|
|
{
|
|
|
|
|
xml body;
|
|
|
|
|
if (res.get_body(body, local_charset_) == false)
|
|
|
|
|
{
|
|
|
|
|
err += "get_body error";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
xml_node* node = body.first_node();
|
|
|
|
|
while (node)
|
|
|
|
|
{
|
|
|
|
|
const char* tag = node->tag_name();
|
|
|
|
|
const char* name = node->attr_value("name");
|
|
|
|
|
const char* pass = node->attr_value("pass");
|
|
|
|
|
printf(">>tag: %s, name: %s, pass: %s\r\n",
|
|
|
|
|
tag ? tag : "null",
|
|
|
|
|
name ? name : "null",
|
|
|
|
|
pass ? pass : "null");
|
|
|
|
|
node = body.next_node();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧͷ<D3A6>ֶ<EFBFBD>
|
|
|
|
|
http_header& header = res.response_header();
|
|
|
|
|
string ctype("text/xml");
|
|
|
|
|
if (req_charset)
|
|
|
|
|
{
|
|
|
|
|
ctype << "; charset=" << req_charset;
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
|
|
|
|
|
printf(">>ctype: %s\r\n", ctype.c_str());
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
string buf;
|
|
|
|
|
body.build_xml(buf);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
return response_body(res, buf, req_charset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> text/json <20><><EFBFBD><EFBFBD>
|
|
|
|
|
bool do_json(http_response& res, const char* req_charset, string& err)
|
|
|
|
|
{
|
|
|
|
|
json body;
|
|
|
|
|
if (res.get_body(body, local_charset_) == false)
|
|
|
|
|
{
|
|
|
|
|
err += "get_body error";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json_node* node = body.first_node();
|
|
|
|
|
while (node)
|
|
|
|
|
{
|
|
|
|
|
if (node->tag_name())
|
|
|
|
|
{
|
|
|
|
|
printf("tag: %s", node->tag_name());
|
|
|
|
|
if (node->get_text())
|
|
|
|
|
printf(", value: %s\r\n", node->get_text());
|
|
|
|
|
else
|
|
|
|
|
printf("\r\n");
|
|
|
|
|
}
|
|
|
|
|
node = body.next_node();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧͷ<D3A6>ֶ<EFBFBD>
|
|
|
|
|
http_header& header = res.response_header();
|
|
|
|
|
string ctype("text/json");
|
|
|
|
|
if (req_charset)
|
|
|
|
|
{
|
|
|
|
|
ctype << "; charset=" << req_charset;
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
header.set_content_type(ctype);
|
|
|
|
|
|
|
|
|
|
printf(">>ctype: %s\r\n", ctype.c_str());
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
string buf;
|
|
|
|
|
body.build_json(buf);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
return response_body(res, buf, req_charset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool response_body(http_response& res, const string& body,
|
|
|
|
|
const char* req_charset)
|
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
|
|
|
|
|
if (local_charset_ == req_charset)
|
|
|
|
|
return res.response(body.c_str(), body.length());
|
|
|
|
|
|
|
|
|
|
// <20><>һ<EFBFBD><D2BB>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
|
|
|
|
|
string buf;
|
|
|
|
|
charset_conv conv;
|
|
|
|
|
if (conv.convert(local_charset_, req_charset,
|
|
|
|
|
body.c_str(), body.length(), &buf) == false)
|
|
|
|
|
{
|
|
|
|
|
logger_error("charset convert from %s to %s error",
|
|
|
|
|
local_charset_.c_str(), req_charset);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf(">>response\r\n(%s)\r\n", buf.c_str());
|
|
|
|
|
return res.response(buf.c_str(), buf.length());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
string local_charset_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
|
{
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
acl::acl_cpp_init();
|
|
|
|
|
#endif
|
|
|
|
|
master_service service; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
if (argc >= 2 && strcmp(argv[1], "alone") == 0)
|
|
|
|
|
{
|
|
|
|
|
if (argc >= 3)
|
|
|
|
|
service.set_charset(argv[2]);
|
|
|
|
|
|
|
|
|
|
format = (void (*)(const char*, ...)) printf;
|
|
|
|
|
printf("listen: 0.0.0.0:8888 ...\r\n");
|
|
|
|
|
service.run_alone("0.0.0.0:8888", NULL, 1); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD>ʽ
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
service.run_daemon(argc, argv); // acl_master <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|