0x00 前言
我们在使用HTTP协议获取接口数据时,通常需要在Header和Query中添加参数,还有一种就是在Body中追加XML或者JSON格式的数据。本文主要讲述使用Poco库提交HTTP Post请求的Body中附加XML格式的数据,JSON格式的数据类似。
0x01 HttpClient类
#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
#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 代码说明
- HttpClient类中Post函数可以将请求头中"content-type"设置成application/xml,表示请求体的数据格式为XML,如果设置成application/json,,则发送的请求体的数据格式为JSON,在发送请求后追加上请求体数据。
- Poco库中的Poco::Net::HTTPClientSession类在使用sendRequest后获取的std::ostream流中去追加请求体数据。