C++使用Poco库封装一个HTTP客户端类

0x00 前言

我们在使用HTTP协议获取接口数据时,通常需要在Header和Query中添加参数,还有一种就是在Body中追加XML或者JSON格式的数据。本文主要讲述使用Poco库提交HTTP Post请求的Body中附加XML格式的数据,JSON格式的数据类似。

0x01 HttpClient类

cpp 复制代码
#ifndef HTTPCLIENT_H
#define HTTPCLIENT_H

#include <string>
#include <map>
#include <Poco/URI.h>
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/HTTPCredentials.h>
#include <Poco/StreamCopier.h>
#include <Poco/NullStream.h>
#include <Poco/Exception.h>

class HttpClient
{
public:
    HttpClient(const std::string &host, const std::string &port = "80");

    std::string Get(const std::string &path,
                    const std::map<std::string, std::string> &header = std::map<std::string, std::string>());

    std::string Post(const std::string &path,
                     const std::string &body,
                     const std::map<std::string, std::string> &header = std::map<std::string, std::string>());

    bool DoRequest(Poco::Net::HTTPClientSession &session,
                   Poco::Net::HTTPRequest &request,
                   Poco::Net::HTTPResponse &response,
                   std::string &responseMsg);

    bool DoRequest(Poco::Net::HTTPClientSession &session,
                   Poco::Net::HTTPRequest &request,
                   Poco::Net::HTTPResponse &response,
                   const std::string &requestBody,
                   std::string &responseMsg);

private:
    std::string m_host;
    std::string m_port;
};

#endif // HTTPCLIENT_H

cpp 复制代码
#include "httpclient.h"
#include <sstream>

HttpClient::HttpClient(const std::string &host, const std::string &port)
    : m_host(host), m_port(port)
{
}

std::string HttpClient::Get(const std::string &path,
                            const std::map<std::string, std::string> &header)
{
    try
    {
        Poco::Net::HTTPClientSession session(m_host, std::stoi(m_port));

        Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1);
        // 设置请求头
        request.set("User-Agent", "PocoRuntime-PocoRuntime/1.1.0");
        for (auto item : header)
        {
            request.set(item.first, item.second);
        }

        Poco::Net::HTTPResponse response;

        std::string retMsg;
        if (DoRequest(session, request, response, retMsg))
        {
            printf("%s\n", retMsg.c_str());
        }
        return retMsg;
    }
    catch (const Poco::Exception &ex)
    {
        printf("%s\n", ex.displayText().c_str());
    }

    return "";
}

std::string HttpClient::Post(const std::string &path,
                             const std::string &body,
                             const std::map<std::string, std::string> &header)
{
    try
    {
        Poco::Net::HTTPClientSession session(m_host, std::stoi(m_port));

        Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, path, Poco::Net::HTTPMessage::HTTP_1_1);
        // 设置请求头
        request.set("User-Agent", "PocoRuntime-PocoRuntime/1.1.0");
        for (auto item : header)
        {
            request.set(item.first, item.second);
        }

        // XML类型的请求体
        // request.setContentType("application/xml");
        // request.setContentLength(body.length());

        Poco::Net::HTTPResponse response;

        std::string retMsg;
        if (DoRequest(session, request, response, body, retMsg))
        {
            printf("%s\n", retMsg.c_str());
        }
        return retMsg;
    }
    catch (const Poco::Exception &ex)
    {
        printf("[%s:%d] %s\n", __FILE__, __LINE__, ex.displayText().c_str());
    }

    return "";
}

bool HttpClient::DoRequest(Poco::Net::HTTPClientSession &session,
                           Poco::Net::HTTPRequest &request,
                           Poco::Net::HTTPResponse &response,
                           std::string &repMsg)
{

    session.sendRequest(request);                         // 发送请求
    std::istream &is = session.receiveResponse(response); // 接收响应
    std::ostringstream oss;
    printf("[%s:%d] %d %s\n", __FILE__, __LINE__, response.getStatus(), response.getReason().c_str());

    if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
    {
        // Poco::StreamCopier::copyStream(rs, std::cout);
        Poco::StreamCopier::copyStream(is, oss);
        if (!oss.str().empty())
        {
            // printf("[%s:%d] %s\n", __FILE__, __LINE__, oss.str().c_str());
            repMsg = oss.str();
        }

        return true;
    }
    else
    {
        printf("[%s:%d] -----HTTPResponse error-----\n", __FILE__, __LINE__);
        Poco::NullOutputStream null;
        Poco::StreamCopier::copyStream(is, null);
        return false;
    }
}

bool HttpClient::DoRequest(Poco::Net::HTTPClientSession &session,
                           Poco::Net::HTTPRequest &request,
                           Poco::Net::HTTPResponse &response,
                           const std::string &requestBody,
                           std::string &responseMsg)
{
    std::ostream &os = session.sendRequest(request); // 发送请求
    // 添加请求体
    os << requestBody;

    std::istream &is = session.receiveResponse(response); // 接收响应
    std::ostringstream oss;
    printf("[%s:%d] %d %s\n", __FILE__, __LINE__, response.getStatus(), response.getReason().c_str());

    if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
    {
        // Poco::StreamCopier::copyStream(rs, std::cout);
        Poco::StreamCopier::copyStream(is, oss);
        if (!oss.str().empty())
        {
            // printf("[%s:%d] %s\n", __FILE__, __LINE__, oss.str().c_str());
            responseMsg = oss.str();
        }

        return true;
    }
    else
    {
        printf("[%s:%d] -----HTTPResponse error-----\n", __FILE__, __LINE__);
        Poco::NullOutputStream null;
        Poco::StreamCopier::copyStream(is, null);
        return false;
    }
}

0x02 使用方法

0x04 代码说明

  1. HttpClient类中Post函数可以将请求头中"content-type"设置成application/xml,表示请求体的数据格式为XML,如果设置成application/json,,则发送的请求体的数据格式为JSON,在发送请求后追加上请求体数据。
  2. Poco库中的Poco::Net::HTTPClientSession类在使用sendRequest后获取的std::ostream流中去追加请求体数据。
相关推荐
arong_xu6 分钟前
现代C++锁介绍
c++·多线程·mutex
汤姆和杰瑞在瑞士吃糯米粑粑11 分钟前
【C++学习篇】AVL树
开发语言·c++·学习
Biomamba生信基地18 分钟前
R语言基础| 功效分析
开发语言·python·r语言·医药
DARLING Zero two♡19 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
手可摘星河20 分钟前
php中 cli和cgi的区别
开发语言·php
CodeClimb33 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
CT随44 分钟前
Redis内存碎片详解
java·开发语言
anlog1 小时前
C#在自定义事件里传递数据
开发语言·c#·自定义事件
奶香臭豆腐1 小时前
C++ —— 模板类具体化
开发语言·c++·学习
不想当程序猿_1 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先