171 lines
5.5 KiB
C++
171 lines
5.5 KiB
C++
#include "bf.request.h"
|
|
|
|
// Poco 头文件
|
|
#include <Poco/Net/HTTPClientSession.h>
|
|
#include <Poco/Net/HTTPRequest.h>
|
|
#include <Poco/Net/HTTPResponse.h>
|
|
#include <Poco/Net/HTTPSClientSession.h>
|
|
#include <Poco/StreamCopier.h>
|
|
#include <Poco/URI.h>
|
|
|
|
// SSL 相关头文件
|
|
#include <Poco/Net/AcceptCertificateHandler.h>
|
|
#include <Poco/Net/Context.h>
|
|
#include <Poco/Net/InvalidCertificateHandler.h>
|
|
#include <Poco/Net/SSLManager.h>
|
|
#include <Poco/SharedPtr.h>
|
|
#include <fmt/format.h>
|
|
#include <nlohmann/json.hpp>
|
|
#include <sstream>
|
|
|
|
#include "bf.util.h"
|
|
|
|
BF_Request::BF_Request()
|
|
{
|
|
}
|
|
|
|
BF_Request::~BF_Request()
|
|
{
|
|
}
|
|
|
|
std::string BF_Request::getResult(const std::string& url)
|
|
{
|
|
std::string response;
|
|
|
|
try {
|
|
Poco::URI uri(url);
|
|
|
|
// 禁用SSL验证(模拟curl的SSL_VERIFYHOST=0, SSL_VERIFYPEER=0)
|
|
Poco::Net::initializeSSL();
|
|
Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> pCertHandler = new Poco::Net::AcceptCertificateHandler(false);
|
|
Poco::Net::Context::Ptr pContext =
|
|
new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE, 9, true);
|
|
Poco::Net::SSLManager::instance().initializeClient(0, pCertHandler, pContext);
|
|
|
|
std::unique_ptr<Poco::Net::HTTPClientSession> pSession;
|
|
|
|
if (uri.getScheme() == "https") {
|
|
// HTTPS
|
|
pSession = std::make_unique<Poco::Net::HTTPSClientSession>(uri.getHost(), uri.getPort(), pContext);
|
|
} else {
|
|
// HTTP
|
|
pSession = std::make_unique<Poco::Net::HTTPClientSession>(uri.getHost(), uri.getPort());
|
|
}
|
|
|
|
std::string path(uri.getPathAndQuery());
|
|
if (path.empty())
|
|
path = "/";
|
|
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1);
|
|
|
|
// 添加必要的请求头
|
|
request.set("User-Agent", "Mozilla/5.0 (compatible; baidu_fanyi/1.0)");
|
|
request.set("Accept", "*/*");
|
|
request.set("Connection", "close");
|
|
|
|
pSession->setTimeout(Poco::Timespan(10, 0)); // 10秒超时
|
|
|
|
pSession->sendRequest(request);
|
|
|
|
Poco::Net::HTTPResponse httpResponse;
|
|
std::istream& rs = pSession->receiveResponse(httpResponse);
|
|
|
|
if (httpResponse.getStatus() != Poco::Net::HTTPResponse::HTTP_OK) {
|
|
gLogger->error("HTTP request failed. Status: {} - {}", static_cast<int>(httpResponse.getStatus()),
|
|
httpResponse.getReason());
|
|
return response;
|
|
}
|
|
|
|
std::stringstream ss;
|
|
Poco::StreamCopier::copyStream(rs, ss);
|
|
response = ss.str();
|
|
|
|
} catch (const Poco::Exception& e) {
|
|
gLogger->error("Poco request failed. Error: {}", e.displayText());
|
|
} catch (const std::exception& e) {
|
|
gLogger->error("Request failed. Error: {}", e.what());
|
|
}
|
|
|
|
Poco::Net::uninitializeSSL(); // 清理SSL
|
|
|
|
return response;
|
|
}
|
|
|
|
std::string BF_Request::doReady(const std::string& words, const std::string& from, const std::string& to)
|
|
{
|
|
char* buffer = new char[2048]{};
|
|
auto rs = BF_Util::RandomStrNum();
|
|
auto s = fmt::format("{}{}{}{}", config_->appId, words, rs, config_->appSecret);
|
|
auto md5 = BF_Util::MD5(s);
|
|
auto reqWords = BF_Util::urlEncode(words);
|
|
std::snprintf(buffer, 2048, "q=%s&from=%s&to=%s&appid=%s&salt=%s&sign=%s", reqWords.c_str(), from.c_str(), to.c_str(),
|
|
config_->appId.c_str(), rs.c_str(), md5.c_str());
|
|
std::string data(buffer);
|
|
delete[] buffer;
|
|
return data;
|
|
}
|
|
|
|
size_t BF_Request::writeData(void* buffer, size_t size, size_t nmemb, std::string* str)
|
|
{
|
|
auto totalSize = size * nmemb;
|
|
str->append(static_cast<char*>(buffer), totalSize);
|
|
return totalSize;
|
|
}
|
|
|
|
bool BF_Request::HandleStr(const std::string& jsonMsg, std::string& out)
|
|
{
|
|
out.clear();
|
|
|
|
if (jsonMsg.empty()) {
|
|
gLogger->error("JSON消息为空");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
nlohmann::json j = nlohmann::json::parse(jsonMsg);
|
|
|
|
if (j.contains("error_code")) {
|
|
std::string errorCode = j["error_code"];
|
|
std::string errorMsg = j.value("error_msg", "未知错误");
|
|
gLogger->error("翻译API返回错误: code={}, msg={}", errorCode, errorMsg);
|
|
return false;
|
|
}
|
|
|
|
if (!j.contains("trans_result")) {
|
|
gLogger->error("JSON中缺少trans_result字段");
|
|
return false;
|
|
}
|
|
|
|
const auto& transResult = j["trans_result"];
|
|
if (!transResult.is_array() || transResult.empty()) {
|
|
gLogger->error("trans_result不是有效数组或为空");
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> translations;
|
|
for (const auto& item : transResult) {
|
|
if (item.contains("dst")) {
|
|
translations.push_back(item["dst"].get<std::string>());
|
|
}
|
|
}
|
|
|
|
if (translations.empty()) {
|
|
gLogger->error("未找到有效的翻译结果");
|
|
return false;
|
|
}
|
|
for (size_t i = 0; i < translations.size(); ++i) {
|
|
out += translations[i];
|
|
if (i < translations.size() - 1) {
|
|
out += "\n";
|
|
}
|
|
}
|
|
return true;
|
|
|
|
} catch (const nlohmann::json::exception& e) {
|
|
gLogger->error("JSON解析失败: {}, 原始数据: {}", e.what(), jsonMsg);
|
|
return false;
|
|
} catch (const std::exception& e) {
|
|
gLogger->error("处理JSON时发生异常: {}, 原始数据: {}", e.what(), jsonMsg);
|
|
return false;
|
|
}
|
|
} |