解决使用 libcurl 与 Charles 抓包的问题
在使用 C++ 发送网络请求时,利用 libcurl 是个不错的选择。然而,有时候我们需要使用 Charles 抓包工具来检查这些请求,但可能会遇到无法抓取请求包的情况,或者 libcurl 提示代理名称无法解析等问题。
设置 libcurl 使用代理
要抓取 libcurl 的请求,需要设置代理。下面的代码演示了如何通过 libcurl 设置代理:
curl_easy_setopt( m_CURL, CURLOPT_PROXY, "127.0.0.1:8888" );
//8888端口就是在Charles 代理设置里面的http代理的端口
获取系统代理配置
为了正确设置 libcurl 的代理,通常在 Windows 系统上,可以使用 WinHTTP 库来获取系统的代理配置信息。以下是网上找到的(注意:使用了wxWidgets库 里面的类)
:
struct PROXY_CONFIG
{
wxString host;
wxString username;
wxString password;
};
bool GetSystemProxyConfig(const wxString& aURL, PROXY_CONFIG& aCfg)
{
// 原始来源:来自微软示例(公共领域)
// https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/WinhttpProxy/cpp/GetProxy.cpp#L844
bool autoProxyDetect = false; // 标志:是否需要自动代理检测
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig = { 0 }; // 存储当前用户的 IE 代理配置
WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = { 0 }; // 自动代理选项
WINHTTP_PROXY_INFO autoProxyInfo = { 0 }; // 自动代理信息
HINTERNET proxyResolveSession = NULL; // 代理解析会话
bool success = false; // 是否成功获取代理配置
// 获取当前用户的 IE 代理配置信息
if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig))
{
// 如果存在自动代理检测或自动代理配置 URL,设置相应的标志和选项
if (ieProxyConfig.fAutoDetect)
{
autoProxyDetect = true;
}
if (ieProxyConfig.lpszAutoConfigUrl != NULL)
{
autoProxyDetect = true;
autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl;
}
}
else if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
// 如果出现特定的错误代码,继续尝试寻找代理
autoProxyDetect = true;
}
// 如果需要自动代理检测
if (autoProxyDetect)
{
proxyResolveSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
if (proxyResolveSession)
{
// 根据自动代理配置 URL 或自动检测模式设置相应标志和选项
if (autoProxyOptions.lpszAutoConfigUrl != NULL)
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
}
else
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
autoProxyOptions.dwAutoDetectFlags =
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
}
// 最初不进行自动登录,让 Windows 使用缓存
autoProxyOptions.fAutoLogonIfChallenged = FALSE;
// 获取给定 URL 的代理信息
autoProxyDetect = WinHttpGetProxyForUrl(proxyResolveSession, aURL.c_str(),
&autoProxyOptions, &autoProxyInfo);
// 如果未成功并出现登录失败,尝试使用自动登录
if (!autoProxyDetect && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE)
{
autoProxyOptions.fAutoLogonIfChallenged = TRUE;
// 现在尝试自动登录
autoProxyDetect = WinHttpGetProxyForUrl(proxyResolveSession, aURL.c_str(),
&autoProxyOptions, &autoProxyInfo);
}
WinHttpCloseHandle(proxyResolveSession);
}
}
// 如果成功获取了代理信息
if (autoProxyDetect)
{
if (autoProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
{
// autoProxyInfo 将返回一个以分号分隔的代理列表
// todo...可能需要更好的选择逻辑
wxString proxyList = autoProxyInfo.lpszProxy;
wxStringTokenizer tokenizer(proxyList, wxT(";"));
if (tokenizer.HasMoreTokens())
{
aCfg.host = tokenizer.GetNextToken();
}
success = true;
}
}
else
{
// 如果没有使用自动代理,则直接从 IE 配置中获取代理信息
if (ieProxyConfig.lpszProxy != NULL)
{
// IE 代理配置可能返回 : 或 :: 作为空代理
aCfg.host = ieProxyConfig.lpszProxy;
if (aCfg.host != ":" && aCfg.host != "::")
{
success = true;
}
}
}
// 清理 Win32 API 返回的字符串内存
if (autoProxyInfo.lpszProxy)
{
GlobalFree(autoProxyInfo.lpszProxy);
autoProxyInfo.lpszProxy = NULL;
}
if (autoProxyInfo.lpszProxyBypass)
{
GlobalFree(autoProxyInfo.lpszProxyBypass);
autoProxyInfo.lpszProxyBypass = NULL;
}
if (ieProxyConfig.lpszAutoConfigUrl != NULL)
{
GlobalFree(ieProxyConfig.lpszAutoConfigUrl);
ieProxyConfig.lpszAutoConfigUrl = NULL;
}
if (ieProxyConfig.lpszProxy != NULL)
{
GlobalFree(ieProxyConfig.lpszProxy);
ieProxyConfig.lpszProxy = NULL;
}
if (ieProxyConfig.lpszProxyBypass != NULL)
{
GlobalFree(ieProxyConfig.lpszProxyBypass);
ieProxyConfig.lpszProxyBypass = NULL;
}
return success; // 返回是否成功获取代理配置
}
为了成功获取网络请求的代理配置并设置libcurl以实现正确的代理,我们需要解析获取到的代理信息。有时,代理配置可能以形如"http=127.0.0.1:8888;https=127.0.0.1:8888"的格式出现,这种情况下直接传入libcurl可能会导致问题。为了确保正确设置HTTP和HTTPS代理,我需要按照代理信息中的不同键值对进行解析,并分配给相应的变量。
以下是我用于解析代理配置并设置HTTP和HTTPS代理的代码段:
const char* proxyConfig = cfg.host; // 代理配置示例 http=127.0.0.1:8888;https=127.0.0.1:8888
const char* httpProxy = NULL;
const char* httpsProxy = NULL;
// 检查代理配置是否包含 "http=" 或 "https="
if(strstr(proxyConfig, "http=") != NULL || strstr(proxyConfig, "https=") != NULL) {
// 解析代理配置,按分号分割
char* token;
char* context = NULL;
token = strtok_s((char*)proxyConfig, ";", &context);
while(token != NULL) {
// 根据 "http=" 或 "https=" 设置对应的代理变量
if(strstr(token, "http=") != NULL) {
httpProxy = token + strlen("http=");
} else if(strstr(token, "https=") != NULL) {
httpsProxy = token + strlen("https=");
}
token = strtok_s(NULL, ";", &context);
}
} else {
// 代理配置为单一 IP + 端口形式,直接设置为 HTTP 和 HTTPS 代理
httpProxy = proxyConfig;
httpsProxy = proxyConfig;
}
这段代码会检查代理配置是否包含了 "http=" 或 "https=" 的信息,若包含则进行分割和解析,将对应的代理地址分配给 httpProxy
和 httpsProxy
变量;如果代理配置只是一个单一的 IP + 端口形式,则将其同时设置为 HTTP 和 HTTPS 代理。文章来源:https://www.toymoban.com/news/detail-749858.html
Charles 代理设置
文章来源地址https://www.toymoban.com/news/detail-749858.html
到了这里,关于解决使用 libcurl 与 Charles 抓包的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!