openGauss-server/src/gausskernel/security/gs_policy/curl_utils.cpp

134 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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;
}