开放的API接口:
#ifndef _HTTP_CLIENT_H_
#define _HTTP_CLIENT_H_
#include <string>
#include "curl/curl.h" /* 引入http 服务接口 */
typedef size_t (*WriteDataCBFunc)(void* buffer, size_t size, size_t nmemb, void* lpVoid);
class HttpClientBase // http client 基类
{
public:
HttpClientBase(int format = 0);
HttpClientBase(std::string username, std::string password);
~HttpClientBase(void);
/**
* @brief HTTP POST请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strPost 输入参数,使用如下格式para1=val1?2=val2&…
* @param strResponse 输出参数,返回的内容
* @return 返回是否Post成功
*/
virtual int Post(const std::string & strUrl, long & httpCode, const std::string & strPost, std::string & strResponse);
/**
* @brief HTTP GET请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strResponse 输出参数,返回的内容
* @return 返回是否Post成功
*/
virtual int Get(const std::string & strUrl, long & httpCode, const std::string & strGet, std::string & strResponse);
/**
* @brief HTTP Put请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strPut 输入参数,使用如下格式para1=val1?2=val2&…
* @param strResponse 输出参数,返回的内容
* @return 返回是否Put成功
*/
virtual int Put(const std::string & strUrl, long & httpCode, const std::string & strPut, std::string & strResponse);
/**
* @brief HTTP Get Download 数据
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param writeDataFunc 数据回调函数
* @return 返回是否Get成功
*/
virtual int Download(const std::string & strUrl, long & httpCode, const std::string & strGet, WriteDataCBFunc cbWriteDataFunc, void *lpVoid);
/**
* @brief HTTPS POST请求,无证书版本
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
* @param strPost 输入参数,使用如下格式para1=val1?2=val2&…
* @param strResponse 输出参数,返回的内容
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
* @return 返回是否Post成功
*/
virtual int Posts(const std::string & strUrl, long & httpCode, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
/**
* @brief HTTPS GET请求,无证书版本
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
* @param strResponse 输出参数,返回的内容
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
* @return 返回是否Post成功
*/
virtual int Gets(const std::string & strUrl, long & httpCode, std::string & strResponse, const char * pCaPath = NULL);
/**
* @brief HTTPS DELETE请求,无证书版本
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strPut 输入参数,使用如下格式para1=val1?2=val2&…
* @param strResponse 输出参数,返回的内容
* @return 返回是否Delete成功
*/
virtual int Delete(const std::string & strUrl, long & httpCode, const std::string & strDelete, std::string & strResponse);
void SetDebug(bool bDebug);
void SetTimeout(int timeout);
void SetVerbose(int verbose){m_verbose = verbose;};
void AddHeader(std::string & headText);
void setAuthMode(unsigned long authMap);
int checkAuthMode(unsigned long authMap);
private:
bool m_bDebug;
unsigned long m_httpAuthMod; // 要使用的http鉴权方式 为curl库提供
std::string m_username;
std::string m_password;
int m_timeout;
int m_verbose;
struct curl_slist* m_headers;
};
#endif
实现部分使用的功能做个小demo
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "HttpClient.hpp"
/* HTTP命令传输层控制 */
#define HTTPBASE_CMD_TIMEOUT (5)
#define HTTPBASE_CMD_VERBOSE (0)
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
if(itype == CURLINFO_TEXT)
{
//printf("[TEXT]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_IN)
{
printf("[HEADER_IN]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_OUT)
{
printf("[HEADER_OUT]%s\n", pData);
}
else if(itype == CURLINFO_DATA_IN)
{
printf("[DATA_IN]%s\n", pData);
}
else if(itype == CURLINFO_DATA_OUT)
{
printf("[DATA_OUT]%s\n", pData);
}
return 0;
}
static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
if( NULL == str || NULL == buffer )
{
return -1;
}
char* pData = (char*)buffer;
str->append(pData, size * nmemb);
return size * nmemb;
}
static size_t OnReadData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
if( NULL == str || NULL == buffer )
{
return -1;
}
char* pData = (char*)buffer;
memcpy(buffer, str->c_str(), str->length());
return str->length();
}
HttpClientBase::HttpClientBase(int format):
m_bDebug(false)
,m_timeout(HTTPBASE_CMD_TIMEOUT)
,m_verbose(HTTPBASE_CMD_VERBOSE)
,m_headers(NULL)
{
std::string head1 = "Accept:*/*";
std::string head2 = "Connection:Keep-Alive";
std::string head3 = "Content-Type: application/xml";
AddHeader(head1);
AddHeader(head2);
AddHeader(head3);
}
HttpClientBase::~HttpClientBase(void)
{
if(m_headers)
{
curl_slist_free_all(m_headers);
m_headers = NULL;
}
}
int HttpClientBase::Get(const std::string & strUrl, long & httpCode, const std::string & strGet, std::string & strResponse)
{
CURLcode res;
CURL* curl = curl_easy_init();
if(NULL == curl)
{
return CURLE_FAILED_INIT;
}
if(m_bDebug)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
/**
* 添加basic 和 digest鉴权方式
*/
curl_easy_setopt(curl, CURLOPT_USERNAME, m_username.c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, m_httpAuthMod);
curl_easy_setopt(curl, CURLOPT_HEADER, 0); //将响应头信息和相应体一起传给write_data
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); //url地址
curl_easy_setopt(curl, CURLOPT_POST, 0); //设置问非0表示本次操作为post
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ""); //post参数
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //对返回的数据进行操作的函数地址
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); //这是write_data的第四个参数值
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
/**
* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
*/
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_VERBOSE, m_verbose); //打印调试信息
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //设置为非0,响应头信息location
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
curl_easy_cleanup(curl);
return res;
}
Linux下编译运行:
//g++ HttpClient.cpp -o httpcli -lcurl
huqin@ubuntu:/mnt/hgfs/share/code/2021/mon10/week3/httpclient$ ./httpcli
recv: {"key":"value"}
huqin@ubuntu:/mnt/hgfs/share/code/2021/mon9/week5/httpSer/httpSvr$ ./httpSvr
sh: 1: cannot create /tmp/nvrLogs/httpSvr.version: Permission denied
httpSvr start, compile: Sep 27 2021 02:55:42
[httpSerInit] use inner map !!!!
start step:
start done.
[httpSerStart] Starting RESTful server on port 8020, serving '.', thdNum: 10
http server start on: 8020
cliReqIn,handle:1,method:GET,url:/test/url,token:Basic Og==,ip:Unknown,port:0
[httpSerDoResponseEx][1469][24734] 2021-10-21 01:23:11 handle: 1, status: 200
cliReqOut,handle:1,method:GET,url:/test/url,res:200