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流中去追加请求体数据。
相关推荐
逊嘘9 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
van叶~12 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
Half-up12 分钟前
C语言心型代码解析
c语言·开发语言
knighthood200122 分钟前
解决:ros进行gazebo仿真,rviz没有显示传感器数据
c++·ubuntu·ros
‍。。。31 分钟前
使用Rust实现http/https正向代理
http·https·rust
Source.Liu34 分钟前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng34 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马37 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng40 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
Jacob程序员42 分钟前
java导出word文件(手绘)
java·开发语言·word