dmphttputils.cpp 5.3 KB
/**************************************************************************
* file:              dmphttputils.cpp

* Author:            lijiahuan
* Date:              2021-12-09 17:41:00
* Email:             jiahuanl@chinadci.com
* copyright:         广州城市信息研究所有限公司
***************************************************************************/
#include "dmphttputils.h"
#include <boost/bind.hpp>

DmpHttp::DmpHttpUtils::DmpHttpUtils(boost::asio::io_service& io_service)
: resolver_(io_service), socket_(io_service) {}
DmpHttp::DmpHttpUtils::~DmpHttpUtils() {}

int DmpHttp::DmpHttpUtils::post(const std::string& url) 
{
	handleRequestResolve(url, DmpHttpBase::buildPostRequest);
	return HTTP_SUCCESS;
}
int DmpHttp::DmpHttpUtils::get(const std::string& url) 
{
	handleRequestResolve(url, DmpHttpBase::buildGetRequest);
	return HTTP_SUCCESS;
}
void DmpHttp::DmpHttpUtils::handleRequestResolve(const std::string& url, pBuildRequest func) {
	try {
		responseData_.clear();
		// 解析URL
		std::string server, port, path;
		parseUrl(url, server, port, path);
 
		std::ostream request_stream(&request_); 
		// 合成请求
		func(server, path, request_stream);
 
		// 解析服务地址\端口
		boost::asio::ip::tcp::resolver::query query(server, port);
		resolver_.async_resolve(query,
			boost::bind(&DmpHttpUtils::handleResolve, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::iterator));
	}
	catch (std::exception& e) {
		socket_.close();
		std::cout << "Exception: " << e.what() << "\n";
	}	
	return;
}
void DmpHttp::DmpHttpUtils::handleResolve(const boost::system::error_code& err,
	boost::asio::ip::tcp::resolver::iterator endpoint_iterator) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	} 
	// 尝试连接
	boost::asio::async_connect(socket_, endpoint_iterator,
		boost::bind(&DmpHttpUtils::handleConnect, this,
		boost::asio::placeholders::error));
}
void DmpHttp::DmpHttpUtils::handleConnect(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}
	// 发送request请求
	boost::asio::async_write(socket_, request_,
		boost::bind(&DmpHttpUtils::handleWriteRequest, this,
		boost::asio::placeholders::error));
}
void DmpHttp::DmpHttpUtils::handleWriteRequest(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}
	// 异步持续读数据到response_,直到接收协议符号 \r\n 为止
	boost::asio::async_read_until(socket_, response_, "\r\n",
		boost::bind(&DmpHttpUtils::handleReadStatusLine, this,
		boost::asio::placeholders::error));
}
void DmpHttp::DmpHttpUtils::handleReadStatusLine(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}
	// 解析buff
	std::istream response_stream(&response_);
	unsigned int status_code;
	std::string http_version, status_message;
	response_stream >> http_version;
	response_stream >> status_code;
	std::getline(response_stream, status_message);
 
	// 核对是否是正确返回
	if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
		std::cout << "错误的响应数据\n";
		return;
	}
	if (status_code != 200) {
		std::cout << "服务器响应的状态码: " << status_code << "\n";
		return;
	}
	// 读取响应头,直到接收协议符号 \r\n\r\n 为止
	boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
		boost::bind(&DmpHttpUtils::handleReadHeaders, this,
		boost::asio::placeholders::error));
}

void DmpHttp::DmpHttpUtils::handleReadHeaders(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}
	// 输出响应头
	std::istream response_stream(&response_);
	std::string header;
	while (std::getline(response_stream, header) && header != "\r") {
#ifdef _DEBUG
		std::cout << header << "\n";
#endif 
	}
#ifdef _DEBUG
	std::cout << "\n";
#endif 
 
	// 写完所有剩余的内容
	if (response_.size() > 0) {
		boost::asio::streambuf::const_buffers_type cbt = response_.data();
		responseData_ += std::string(boost::asio::buffers_begin(cbt), boost::asio::buffers_end(cbt));
#ifdef _DEBUG
		std::cout << &response_;
#endif 
	}
 
	// 开始读取剩余所有内容
	boost::asio::async_read(socket_, response_,
		boost::asio::transfer_at_least(1),
		boost::bind(&DmpHttpUtils::handleReadContent, this,
		boost::asio::placeholders::error));
}
void DmpHttp::DmpHttpUtils::handleReadContent(const boost::system::error_code& err) {
	if (!err) {
	
		// 输出读到的数据
		boost::asio::streambuf::const_buffers_type cbt = response_.data();
		
		responseData_ = std::string(boost::asio::buffers_begin(cbt), boost::asio::buffers_end(cbt));
#ifdef _DEBUG
		std::cout << &response_;
#endif 
 
		// 继续读取剩余内容,直到读到EOF
	boost::asio::async_read(socket_, response_,
			boost::asio::transfer_at_least(1),
			boost::bind(&DmpHttpUtils::handleReadContent, this,
			boost::asio::placeholders::error));
			
	}
	else if (err != boost::asio::error::eof) {
		std::cout << "Error: " << err << "\n";
	}
	else {
		socket_.close();
		resolver_.cancel();
	}
}
 
 
std::string DmpHttp::post(const std::string &url) {
	boost::asio::io_service io;
	DmpHttp::DmpHttpUtils c(io);
	c.post(url);
	io.run();
	return c.getResponse();
}

std::string DmpHttp::get(const std::string &url) {
	boost::asio::io_service io;
	DmpHttp::DmpHttpUtils c(io);
	c.get(url);
	io.run();
	return c.getResponse();
}