From b88dc0fca1d4d3d2d387241152da2a9089096626 Mon Sep 17 00:00:00 2001 From: lanniesang Date: Tue, 16 Sep 2025 17:22:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=87=E5=AE=9Aip=E8=B7=B3=E8=BF=87DNS?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencentcloud/core/http/HttpClient.h | 3 + .../tencentcloud/core/profile/HttpProfile.h | 6 +- core/src/AbstractClient.cpp | 3 +- core/src/http/HttpClient.cpp | 22 +++- core/src/profile/HttpProfile.cpp | 13 +- test/function_test/core/CMakeLists.txt | 5 +- .../core/Core_Http_TargetIp_Ft.cpp | 119 ++++++++++++++++++ 7 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 test/function_test/core/Core_Http_TargetIp_Ft.cpp diff --git a/core/include/tencentcloud/core/http/HttpClient.h b/core/include/tencentcloud/core/http/HttpClient.h index e820cb684e..37595c4050 100644 --- a/core/include/tencentcloud/core/http/HttpClient.h +++ b/core/include/tencentcloud/core/http/HttpClient.h @@ -40,6 +40,8 @@ namespace TencentCloud void SetCaInfo(std::string caInfo); void SetCaPath(std::string caPath); + void SetTargetIp(std::string targetIp); + HttpResponseOutcome SendRequest(const HttpRequest &request); void SetProxy(const NetworkProxy &proxy); @@ -54,6 +56,7 @@ namespace TencentCloud NetworkProxy m_proxy; std::string m_caInfo; std::string m_caPath; + std::string m_targetIp; #ifdef ENABLE_COMPRESS_MODULE int GzipDecompress(const char *src, int srcLen, const char *dst, int* dstLen); bool TryDecompress(const char *src, int srcLen, std::string &decompressData); diff --git a/core/include/tencentcloud/core/profile/HttpProfile.h b/core/include/tencentcloud/core/profile/HttpProfile.h index c2bc305390..d6a76c7120 100644 --- a/core/include/tencentcloud/core/profile/HttpProfile.h +++ b/core/include/tencentcloud/core/profile/HttpProfile.h @@ -51,6 +51,8 @@ namespace TencentCloud void SetCaInfo(std::string caInfo); std::string GetCaInfo() const; + void SetTargetIp(std::string targetIp); + std::string GetTargetIp() const; void SetCaPath(std::string caPath); std::string GetCaPath() const; @@ -62,7 +64,8 @@ namespace TencentCloud m_connectTimeout(o.m_connectTimeout), m_keepAlive(o.m_keepAlive), m_caInfo(o.m_caInfo), - m_caPath(o.m_caPath) + m_caPath(o.m_caPath), + m_targetIp(o.m_targetIp) { } @@ -91,6 +94,7 @@ namespace TencentCloud bool m_keepAlive; std::string m_caInfo; std::string m_caPath; + std::string m_targetIp; }; } diff --git a/core/src/AbstractClient.cpp b/core/src/AbstractClient.cpp index 2ddfbbdae7..b4123e9095 100644 --- a/core/src/AbstractClient.cpp +++ b/core/src/AbstractClient.cpp @@ -169,6 +169,8 @@ HttpClient::HttpResponseOutcome AbstractClient::DoRequest(const std::string &act m_httpClient->SetCaInfo(httpProfile.GetCaInfo()); m_httpClient->SetCaPath(httpProfile.GetCaPath()); + m_httpClient->SetTargetIp(httpProfile.GetTargetIp()); + return m_httpClient->SendRequest(httpRequest); } @@ -212,4 +214,3 @@ void AbstractClient::GenerateSignature(HttpRequest &request) + ", SignedHeaders=content-type;host" + ", Signature=" + signature; request.AddHeader("Authorization", authorization); } - diff --git a/core/src/http/HttpClient.cpp b/core/src/http/HttpClient.cpp index 0fb8d1b091..ff2f6f169c 100644 --- a/core/src/http/HttpClient.cpp +++ b/core/src/http/HttpClient.cpp @@ -126,6 +126,11 @@ void HttpClient::SetCaInfo(std::string caInfo) m_caInfo = caInfo; } +void HttpClient::SetTargetIp(std::string targetIp) +{ + m_targetIp = targetIp; +} + void HttpClient::SetCaPath(std::string caPath) { m_caPath = caPath; @@ -174,6 +179,16 @@ HttpClient::HttpResponseOutcome HttpClient::SendRequest(const HttpRequest &reque curl_easy_setopt(m_curlHandle, CURLOPT_CONNECTTIMEOUT_MS, m_connectTimeout); curl_easy_setopt(m_curlHandle, CURLOPT_URL, url.c_str()); + std::string domain = request.GetUrl().GetHost(); + + // 创建解析规则链表(用于CURLOPT_RESOLVE) + struct curl_slist *resolveList = nullptr; + + if (!m_targetIp.empty() && !domain.empty()) { + std::string resolveEntry = domain + ":443:" + m_targetIp; + resolveList = curl_slist_append(resolveList, resolveEntry.c_str()); + curl_easy_setopt(m_curlHandle, CURLOPT_RESOLVE, resolveList); + } curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYHOST, 2L); @@ -205,6 +220,11 @@ HttpClient::HttpResponseOutcome HttpClient::SendRequest(const HttpRequest &reque curl_easy_setopt(m_curlHandle, CURLOPT_ERRORBUFFER, errbuf); CURLcode res = curl_easy_perform(m_curlHandle); + if (resolveList) + { + curl_slist_free_all(resolveList); + } + if (header_list) { curl_slist_free_all(header_list); @@ -279,4 +299,4 @@ int HttpClient::GzipDecompress(const char *src, int srcLen, const char *dst, int inflateEnd(&stream); return err; } -#endif // ENABLE_COMPRESS_MODULE \ No newline at end of file +#endif // ENABLE_COMPRESS_MODULE diff --git a/core/src/profile/HttpProfile.cpp b/core/src/profile/HttpProfile.cpp index 5adc04fd04..f11c0bba9e 100644 --- a/core/src/profile/HttpProfile.cpp +++ b/core/src/profile/HttpProfile.cpp @@ -27,7 +27,8 @@ HttpProfile::HttpProfile() : m_connectTimeout(TM_MINUTE_SECOND), m_keepAlive(false), m_caInfo(""), - m_caPath("") + m_caPath(""), + m_targetIp("") { } @@ -95,6 +96,16 @@ std::string HttpProfile::GetCaInfo() const return m_caInfo; } +void HttpProfile::SetTargetIp(std::string targetIp) +{ + m_targetIp = targetIp; +} + +std::string HttpProfile::GetTargetIp() const +{ + return m_targetIp; +} + void HttpProfile::SetCaPath(std::string caPath) { m_caPath = caPath; diff --git a/test/function_test/core/CMakeLists.txt b/test/function_test/core/CMakeLists.txt index 1cd551ebe5..00990ec108 100644 --- a/test/function_test/core/CMakeLists.txt +++ b/test/function_test/core/CMakeLists.txt @@ -32,8 +32,9 @@ add_executable(core_ft Core_Http_HttpResponse_Ft.cpp Core_Profile_HttpProfile_Ft.cpp Core_Profile_ClientProfile_Ft.cpp + Core_Http_TargetIp_Ft.cpp Main.cpp) -target_link_libraries(core_ft tencentcloud-sdk-cpp-cbs tencentcloud-sdk-cpp-core) +target_link_libraries(core_ft tencentcloud-sdk-cpp-cbs tencentcloud-sdk-cpp-cvm tencentcloud-sdk-cpp-core) target_link_libraries(core_ft gtest gmock_main -lpthread -lm) set_target_properties(core_ft @@ -41,4 +42,4 @@ set_target_properties(core_ft OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}core_ft RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -add_test(NAME core_ft COMMAND core_ft) \ No newline at end of file +add_test(NAME core_ft COMMAND core_ft) diff --git a/test/function_test/core/Core_Http_TargetIp_Ft.cpp b/test/function_test/core/Core_Http_TargetIp_Ft.cpp new file mode 100644 index 0000000000..265ecd536c --- /dev/null +++ b/test/function_test/core/Core_Http_TargetIp_Ft.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../utils.h" +#include "gtest/gtest.h" + +using namespace TencentCloud; +using namespace TencentCloud::Cvm::V20170312; +using namespace TencentCloud::Cvm::V20170312::Model; +using namespace std; + +namespace +{ + TEST(cvm, DescribeInstances_UseValidTargetIp) + { + TencentCloud::InitAPI(); + + string secretId = CUtils::GetEnv("TENCENTCLOUD_SECRET_ID"); + string secretKey = CUtils::GetEnv("TENCENTCLOUD_SECRET_KEY"); + Credential cred = Credential(secretId, secretKey); + + HttpProfile httpProfile = HttpProfile(); + httpProfile.SetEndpoint("cvm.ap-guangzhou.tencentcloudapi.com"); + httpProfile.SetReqTimeout(10); + httpProfile.SetTargetIp("106.55.122.199"); + + ClientProfile clientProfile = ClientProfile(httpProfile); + + DescribeInstancesRequest req = DescribeInstancesRequest(); + req.SetOffset(0); + req.SetLimit(5); + + CvmClient cvm_client = CvmClient(cred, "ap-guangzhou", clientProfile); + + auto outcome = cvm_client.DescribeInstances(req); + EXPECT_TRUE(outcome.IsSuccess()); + EXPECT_TRUE(outcome.GetError().GetErrorCode().empty()); + EXPECT_FALSE(outcome.GetResult().GetRequestId().empty()); + + TencentCloud::ShutdownAPI(); + } + + TEST(cvm, DescribeInstances_UseInvalidTargetIp) + { + TencentCloud::InitAPI(); + + string secretId = CUtils::GetEnv("TENCENTCLOUD_SECRET_ID"); + string secretKey = CUtils::GetEnv("TENCENTCLOUD_SECRET_KEY"); + Credential cred = Credential(secretId, secretKey); + + HttpProfile httpProfile = HttpProfile(); + httpProfile.SetEndpoint("cvm.ap-guangzhou.tencentcloudapi.com"); + httpProfile.SetReqTimeout(5); + httpProfile.SetTargetIp("192.168.1.1"); + + ClientProfile clientProfile = ClientProfile(httpProfile); + + DescribeInstancesRequest req = DescribeInstancesRequest(); + req.SetOffset(0); + req.SetLimit(5); + + CvmClient cvm_client = CvmClient(cred, "ap-guangzhou", clientProfile); + + auto outcome = cvm_client.DescribeInstances(req); + EXPECT_FALSE(outcome.IsSuccess()); + EXPECT_FALSE(outcome.GetError().GetErrorCode().empty()); + + TencentCloud::ShutdownAPI(); + } + + TEST(cvm, DescribeInstances_WithoutTargetIp) + { + TencentCloud::InitAPI(); + + string secretId = CUtils::GetEnv("TENCENTCLOUD_SECRET_ID"); + string secretKey = CUtils::GetEnv("TENCENTCLOUD_SECRET_KEY"); + Credential cred = Credential(secretId, secretKey); + + HttpProfile httpProfile = HttpProfile(); + httpProfile.SetEndpoint("cvm.ap-guangzhou.tencentcloudapi.com"); + httpProfile.SetReqTimeout(5); + + ClientProfile clientProfile = ClientProfile(httpProfile); + + DescribeInstancesRequest req = DescribeInstancesRequest(); + req.SetOffset(0); + req.SetLimit(5); + + CvmClient cvm_client = CvmClient(cred, "ap-guangzhou", clientProfile); + + auto outcome = cvm_client.DescribeInstances(req); + EXPECT_TRUE(outcome.IsSuccess()); + EXPECT_TRUE(outcome.GetError().GetErrorCode().empty()); + EXPECT_FALSE(outcome.GetResult().GetRequestId().empty()); + + TencentCloud::ShutdownAPI(); + } + + TEST(cvm, TargetIp_ParameterPassing) + { + HttpProfile httpProfile; + string testIp = "106.55.122.199"; + httpProfile.SetTargetIp(testIp); + + EXPECT_EQ(httpProfile.GetTargetIp(), testIp); + + ClientProfile clientProfile(httpProfile); + EXPECT_EQ(clientProfile.GetHttpProfile().GetTargetIp(), testIp); + + httpProfile.SetTargetIp(""); + EXPECT_TRUE(httpProfile.GetTargetIp().empty()); + } +}