Http客户端

 开放的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值