game2006/server/gameserver/httpproxy.cc
aozhiwei db0d36269e 1
2024-07-31 09:43:42 +08:00

242 lines
9.0 KiB
C++

#include "precompile.h"
#include <a8/sysutils.h>
#include <a8/mutable_xobject.h>
#include <a8/openssl.h>
#include <f8/udplog.h>
#include <f8/jsonhttprequest.h>
#include "httpproxy.h"
#include "app.h"
#include "jsondatamgr.h"
#include "handlermgr.h"
#include "f8/httpclientpool.h"
struct HttpProxyRequest
{
std::string req_id;
f8::HttpProxyCb cb;
std::string url;
std::shared_ptr<a8::MutableXObject> url_params;
long long add_tick = 0;
};
static void _ProxyCallback(std::shared_ptr<f8::JsonHttpRequest> request)
{
#ifdef MYDEBUG
f8::UdpLog::Instance()->Debug("ProxyCallbBack request:%s",
{
request->GetParams()->ToJsonStr()
});
#endif
std::string seq_id = request->GetParams()->Get("seq_id");
std::shared_ptr<HttpProxyRequest> req = HttpProxy::Instance()->GetRequest(seq_id);
if (req) {
a8::XObject data;
data.ReadFromJsonString(request->GetParams()->Get("data").GetString());
if (data.GetType() == a8::XOT_SIMPLE) {
data.ReadFromJsonString("{}");
}
f8::HttpContext ctx;
if (request->GetParams()->HasKey("errcode") &&
request->GetParams()->Get("errcode").GetInt() == 0) {
req->cb(true, &data, &ctx);
} else {
req->cb(false, request->GetParams().get(), &ctx);
}
HttpProxy::Instance()->DestoryRequest(req);
}
}
void HttpProxy::Init()
{
request_prefix_ = "game2006_" + a8::XValue(a8::GetMilliSecond()).GetString() + "_";
HandlerMgr::Instance()->RegisterGMMsgHandler("Proxy@callback", _ProxyCallback);
}
void HttpProxy::UnInit()
{
request_hash_.clear();
}
std::string HttpProxy::HttpGet(
f8::HttpProxyCb cb,
const std::string& url,
std::shared_ptr<a8::MutableXObject> url_params
)
{
if (f8::App::Instance()->Terminated()) {
return "";
}
AddSignParams(url, url_params, "");
std::shared_ptr<HttpProxyRequest> request = std::make_shared<HttpProxyRequest>();
request->req_id = CreateRequestId();
request->cb = cb;
request->url = url;
request->url_params = url_params;
request->add_tick = a8::XGetTickCount();
if (request_hash_.find(request->req_id) != request_hash_.end()) {
abort();
}
request_hash_[request->req_id] = request;
auto proxy_url_params = a8::MutableXObject::CreateObject();
proxy_url_params->SetVal("seq_id", request->req_id);
proxy_url_params->SetVal("target_url", std::string(url));
proxy_url_params->SetVal("params", url_params->ToJsonStr());
proxy_url_params->SetVal("cb_url", a8::Format("http://%s:%d/webapp/index.php?c=Proxy&a=callback",
{
JsonDataMgr::Instance()->ip,
JsonDataMgr::Instance()->listen_port
}));
std::string proxy_url;
JsonDataMgr::Instance()->GetHttpGetProxyUrl(proxy_url);
f8::HttpClientPool::Instance()->HttpGet
(
[request] (bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
long long cost_time = a8::XGetTickCount() - request->add_tick;
if (ok) {
#ifdef MYDEBUG
f8::UdpLog::Instance()->Debug("ProxyHttpGet ok cost_time:%d url:%s params:%s",
{
cost_time,
request->url,
request->url_params->ToJsonStr(),
});
#endif
} else {
f8::UdpLog::Instance()->Warning("ProxyHttpGet error cost_time:%d url:%s params:%s response:%s",
{
cost_time,
request->url,
request->url_params->ToJsonStr(),
ctx->response
});
request->cb(false, rsp_obj, ctx);
HttpProxy::Instance()->DestoryRequest(request);
}
},
proxy_url.c_str(),
*proxy_url_params,
rand() % MAX_SYS_HTTP_NUM
);
return request->req_id;
}
std::string HttpProxy::HttpPost(
f8::HttpProxyCb cb,
const std::string& url,
std::shared_ptr<a8::MutableXObject> url_params,
const std::string& content
)
{
if (f8::App::Instance()->Terminated()) {
return "";
}
AddSignParams(url, url_params, content);
std::shared_ptr<HttpProxyRequest> request = std::make_shared<HttpProxyRequest>();
request->req_id = CreateRequestId();
request->cb = cb;
request->url = url;
request->url_params = url_params;
request->add_tick = a8::XGetTickCount();
if (request_hash_.find(request->req_id) != request_hash_.end()) {
abort();
}
request_hash_[request->req_id] = request;
auto proxy_url_params = a8::MutableXObject::CreateObject();
proxy_url_params->SetVal("seq_id", request->req_id);
proxy_url_params->SetVal("target_url", std::string(url));
proxy_url_params->SetVal("params", url_params->ToJsonStr());
proxy_url_params->SetVal("cb_url", a8::Format("http://%s:%d/webapp/index.php?c=Proxy&a=callback",
{
JsonDataMgr::Instance()->ip,
JsonDataMgr::Instance()->listen_port
}));
auto http_headers = a8::MutableXObject::CreateArray();
http_headers->Push("Content-Type: application/json");
std::string proxy_url;
JsonDataMgr::Instance()->GetHttpPostProxyUrl(proxy_url);
f8::HttpClientPool::Instance()->HttpPost
(
[request] (bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
long long cost_time = a8::XGetTickCount() - request->add_tick;
if (ok) {
#ifdef MYDEBUG
f8::UdpLog::Instance()->Debug("ProxyHttpPost ok cost_time:%d url:%s params:%s",
{
cost_time,
request->url,
request->url_params->ToJsonStr(),
});
#endif
} else {
f8::UdpLog::Instance()->Warning("ProxyHttpPost error cost_time:%d url:%s params:%s response:%s",
{
cost_time,
request->url,
request->url_params->ToJsonStr(),
ctx->response
});
request->cb(false, rsp_obj, ctx);
HttpProxy::Instance()->DestoryRequest(request);
}
},
proxy_url.c_str(),
*proxy_url_params,
content,
rand() % MAX_SYS_HTTP_NUM,
http_headers.get()
);
return request->req_id;
}
std::string HttpProxy::CreateRequestId()
{
return request_prefix_ + f8::App::Instance()->NewGlobalUuid();
}
std::shared_ptr<HttpProxyRequest> HttpProxy::GetRequest(const std::string& req_id)
{
auto itr = request_hash_.find(req_id);
return itr != request_hash_.end() ? itr->second : nullptr;
}
void HttpProxy::DestoryRequest(std::shared_ptr<HttpProxyRequest> request)
{
request_hash_.erase(request->req_id);
}
void HttpProxy::AddSignParams(const std::string& url,
std::shared_ptr<a8::MutableXObject> url_params, const std::string& post_data)
{
if (url.find('?') != std::string::npos) {
A8_ABORT();
}
std::string sign_data;
sign_data.reserve(1024 * 64);
int nowtime = f8::App::Instance()->GetNowTime();
{
std::vector<std::string> keys;
url_params->GetKeys(keys);
for (auto& key : keys) {
std::string val = url_params->Get(key, "").GetString();
sign_data += key + "=" + val + "&";
}
sign_data += post_data;
}
{
sign_data += a8::XValue(nowtime).GetString() + JsonDataMgr::Instance()->GetApiSecretKey();
}
std::string sign = a8::openssl::md5(sign_data);
url_params->SetVal("_timestamp", a8::XValue(nowtime).GetString());
url_params->SetVal("_sign", sign);
}