做项目的时候用到了http通信,同事用libevent库写的,特此记录后端从前端拿到消息后的处理方式
void CHTTPTest::request(const std::any & data)
{
// data 是从前端拿到的数据
void *obj = std::any_cast<void *>(data); // std::any是C++17新标准的
struct evhttp_request *req = (evhttp_request*)(obj);
enum evhttp_cmd_type method = evhttp_request_get_command(req); // 获取请求方法
if (method == EVHTTP_REQ_GET)
{
// GET 请求
this->getProcess(req);
}
else if (method == EVHTTP_REQ_POST)
{
// POST 请求
this->postProcess(req);
}
else
{
// 错误
this->return_msg(req, "Unsupported request method.", ErrorCode::fail);
}
}
GET的请求处理,包括前端请求的参数
void CHTTPTest::getProcess(evhttp_request * req)
{
//获取请求uri
const char* uri = evhttp_request_get_uri(req);
//解码uri
struct evhttp_uri* decoded_uri = evhttp_uri_parse(uri);
if (!decoded_uri)
{
return_msg(req, "Failed to parse URI\n", ErrorCode::fail);
return;
}
// 找到路径
QString path = evhttp_uri_get_path(decoded_uri);
if (path.isEmpty())
{
path = "/";
}
//解析查询字符串
struct evkeyvalq params;
evhttp_parse_query(uri, ¶ms);
struct evkeyval* kv;
// 创建 QVariantHash 用于存储参数
//QVariantHash paramList;
// 创建 JSON 对象用于存储查询参数
QJsonObject jsonObj;
// 遍历查询参数,将其添加到 JSON 对象中
for (kv = params.tqh_first; kv; kv = kv->next.tqe_next)
{
jsonObj[kv->key] = kv->value;
}
// 清理查询参数的内存
evhttp_clear_headers(¶ms);
// 创建 JSON 文档
QJsonDocument JsonDoc = QJsonDocument(jsonObj);
// 检查 JSON 对象是否为空,返回相应的消息
QString Info = JsonDoc.toJson(QJsonDocument::Compact);
// 将 JSON 文档转换为字符串并使用紧凑格式
if (jsonObj.isEmpty())
{
return_msg(req, "Param Is Empty\n", ErrorCode::fail);
return;
}
else
{
// 逻辑处理接口
this->logicProcess(req, path, jsonObj);
}
}
POST的请求处理,包括前端发送的参数处理
void CHTTPTest::postProcess(evhttp_request * req)
{
const char* uri = evhttp_request_get_uri(req);
struct evhttp_uri* decoded_uri = evhttp_uri_parse(uri);
if (!decoded_uri)
{
printf("Failed to parse URI\n");
return;
}
QString path = evhttp_uri_get_path(decoded_uri);
if (path.isEmpty())
{
path = "/";
}
struct evbuffer* input_buf = evhttp_request_get_input_buffer(req);
size_t data_len = evbuffer_get_length(input_buf);
char* data = (char*)malloc(data_len + 1);
if (data)
{
evbuffer_copyout(input_buf, data, data_len);
data[data_len] = '\0';
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
if (parseError.error != QJsonParseError::NoError)
{
this->return_msg(req, parseError.errorString(), ErrorCode::fail);
return;
}
QJsonObject jsonObj = doc.object();
// 逻辑处理接口
this->logicProcess(req, path, jsonObj);
}
}
内部消息返回前端的处理
void CDigitalModelManage::return_msg(evhttp_request * req, QString msg, int errCode)
{
struct evbuffer* buf = evbuffer_new();
if (!buf)
{
return;
}
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(msg.toUtf8(), &parseError);
QJsonObject jsonObject;
QJsonDocument backJsonDoc;
if (parseError.error == QJsonParseError::NoError)
{
jsonObject = jsonDoc.object();
jsonObject["code"] = errCode;
}
else
{
jsonObject["code"] = errCode;
jsonObject["message"] = msg;
}
backJsonDoc = QJsonDocument(jsonObject);
QString backInfo = backJsonDoc.toJson(QJsonDocument::Compact);
evbuffer_add_printf(buf, backInfo.toUtf8().constData());
evhttp_add_header(req->output_headers, "Content-Type", "application/json; charset=utf-8");
evhttp_send_reply(req, HTTP_OK, "OK", buf);
evbuffer_free(buf);
}
在接口logicProcess
中处理就是各个消息的内部逻辑处理了,传的第一个参数是http请求的内存块(我是这么理解的),第二个参数是和前端约定的URL,第三个参数就是前端发送的JSON体。只需要在接口logicProcess
中解这个JSON体就可以拿到值了。
这里只是一部分代码,比如怎么调用request
接口还需要研究研究,只是作为记录,方便后续学习参考。