134 lines
6.2 KiB
C++
134 lines
6.2 KiB
C++
/*
|
||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||
*
|
||
* openGauss is licensed under Mulan PSL v2.
|
||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||
* You may obtain a copy of Mulan PSL v2 at:
|
||
*
|
||
* http://license.coscl.org.cn/MulanPSL2
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||
* See the Mulan PSL v2 for more details.
|
||
* -------------------------------------------------------------------------
|
||
*
|
||
* curl_utils.cpp
|
||
* routines for curl connection with remote server
|
||
*
|
||
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
||
* Portions Copyright (c) 1994, Regents of the University of California
|
||
*
|
||
*
|
||
* IDENTIFICATION
|
||
* src/gausskernel/security/gs_policy/curl_utils.cpp
|
||
|
||
* -------------------------------------------------------------------------
|
||
*/
|
||
/*与网络通信和HTTP请求相关的功能。
|
||
它封装了libcurl库,提供了一组方便的函数来发送HTTP请求、处理响应并处理与网络通信相关的任务。
|
||
创建和释放CURL句柄、设置请求选项(如URL、请求方法、超时时间等)、
|
||
添加请求头信息、发送请求、接收响应、获取响应状态码和响应头信息、以及处理错误等。
|
||
*/
|
||
#include <fstream> //用于文件输入输出操作。
|
||
#include <streambuf> //用于流缓冲区操作
|
||
#include <thread> //用于线程操作
|
||
#include <mutex> //用于互斥锁操作
|
||
#include <vector> //用于向量容器操作
|
||
#include <string> //用于字符串操作
|
||
#include "curl/curl.h" //用于使用CURL库进行网络通信。
|
||
#include "gs_policy/curl_utils.h" //gs_policy模块中与curl通信相关的工具函数定义。
|
||
#include "utils/elog.h" //用于错误日志记录。
|
||
|
||
|
||
static std::mutex g_i_mutex; //静态互斥锁对象
|
||
|
||
CurlUtils::CurlUtils() : m_withSSL(false), //用于指示是否启用SSL连接,默认为 false。
|
||
m_certificate(""), //存储SSL证书的文件路径
|
||
m_user(""), //存储用户名称
|
||
m_password(""), //存储用户密码
|
||
m_curlForPost(NULL)//用于执行POST请求的CURL句柄
|
||
{
|
||
}
|
||
|
||
CurlUtils::~CurlUtils()
|
||
{
|
||
curl_easy_cleanup(m_curlForPost);
|
||
}
|
||
|
||
//初始化 CurlUtils 类的实例
|
||
void CurlUtils::initialize(bool withSSL, const std::string certificate, const std::string user,
|
||
const std::string password)
|
||
{
|
||
m_withSSL = withSSL;
|
||
m_certificate = certificate;
|
||
m_user = user;
|
||
m_password = password;
|
||
m_curlForPost = curl_easy_init();
|
||
}
|
||
|
||
/*
|
||
* Send file to remote web server as rest interface
|
||
*/
|
||
bool CurlUtils::http_post_file_request(const std::string url, const std::string fileName, bool connection_testing)
|
||
{
|
||
// 输出调试信息,包括URL和文件名
|
||
ereport(INFO, (errmsg("Url = %s, fileName = %s", url.c_str(), fileName.c_str())));
|
||
// 从文件中读取内容并存储为字符串
|
||
std::ifstream t(fileName);
|
||
std::string str((std::istreambuf_iterator<char>(t)),
|
||
std::istreambuf_iterator<char>());
|
||
|
||
if (m_curlForPost != NULL) {
|
||
// 设置请求头
|
||
struct curl_slist *slist1 = NULL;
|
||
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
|
||
|
||
// 设置CURL选项,包括URL、进度通知设置、请求体等
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_URL, url.c_str());
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_NOPROGRESS, 1L);
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_POSTFIELDS, str.c_str());
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_POSTFIELDSIZE_LARGE, str.length());
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_USERAGENT, "curl/7.29.0");
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_HTTPHEADER, slist1);
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_MAXREDIRS, 50L);
|
||
|
||
/*
|
||
* as cert from server maybe certificated by self we ignore the verification
|
||
*/
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_SSL_VERIFYPEER, 0L);
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_SSL_VERIFYHOST, 0L);
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_CUSTOMREQUEST, "POST");
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_TCP_KEEPALIVE, 1L);
|
||
|
||
/* a simply connection test to server, just verify the connection without any data transfer */
|
||
// 进行连接测试,仅验证连接而不进行数据传输
|
||
if (connection_testing) {
|
||
(void)curl_easy_setopt(m_curlForPost, CURLOPT_CONNECT_ONLY, 1L);
|
||
}
|
||
|
||
/* perform a file transfer */
|
||
CURLcode res = curl_easy_perform(m_curlForPost);//使用curl_easy_perform()函数来执行网络请求。该函数将阻塞当前线程,直到请求完成或发生错误。
|
||
if (res != CURLE_OK) {// 处理请求失败的情况
|
||
/*
|
||
* we will not generate error which will make the audit thread restarted
|
||
* but make an error and free related resource to make user deal with the connection issue
|
||
*/
|
||
if (connection_testing) {//判断是否正在进行连接测试
|
||
ereport(PANIC, //错误的严重级别,表示遇到了无法继续执行的致命错误,需要立即终止程序
|
||
(errmsg("make sure connection to elastic_search_ip_addr, error info: %s\n", //错误消息的格式化部分
|
||
curl_easy_strerror(res))));/*将错误码转换为对应的错误描述字符串。*/
|
||
}
|
||
|
||
curl_slist_free_all(slist1);//释放整个链表及其节点所占用的内存
|
||
curl_easy_reset(m_curlForPost);//重置,将其恢复为初始状态以进行新的请求。
|
||
ereport(WARNING, (errmsg("Connection issue happended, post file error: %s\n", curl_easy_strerror(res))));
|
||
return false;
|
||
}
|
||
curl_slist_free_all(slist1);
|
||
curl_easy_reset(m_curlForPost);
|
||
}
|
||
|
||
return true;
|
||
}
|