使用 boost::asio 发送 http GET 请求,类似于 cURL
Sending http GET request using boost::asio, similar to cURL
我正在尝试使用某个域的 REST API 发送 http GET 请求。
基本上我要做的是替换以下 curl 请求:
curl -k -H "Content-Type: application/json" -X GET
--data '{"username":"user@name.co", "password":"test"}' https:/domain.name/api/login/
一些 C++ 代码使用 boost::asio
。
我不想在这里找到所有的 c++ 代码,但是一些检查点会很棒。
boost::asio
不是应用程序级库。所以你可以用它打开一个连接,做一个 SSL 握手等等。但是您不能通过 boost::asio
构造 HTTP 请求,因为它仅设计用于 send/receive 数据。
但是,您可以尝试使用 this asio HTTP client example 进行试验。这可能是一件好事。
有一个 Urdl 库,由 Boost.Asio 的作者 Christopher M. Kohlhoff 创建:
Urdl is a cross-platform C++ library for downloading web content using
a URL. It provides an easy-to-use extension to standard C++ iostreams
and an asynchronous interface for use with Boost.Asio.
您的请求示例如下:
#include <urdl/http.hpp>
urdl::istream is;
// Set request options: method, content type, content
is.set_option(urdl::http::request_method("GET"));
is.set_option(urdl::http::request_content_type("application/json"));
is.set_option(urdl::http::request_content("{\"username\":\"user@name.co\", \"password\":\"test\"}"));
// open HTTP stream at URL
is.open("https:/domain.name/api/login/");
我发现自己也在使用 boost
来发送一些 "customized" HTTP GET 请求 - 我 运行 我的 Ubuntu 机器上的本地服务器 (16.04) .
在我的例子中,请求是一些专有的 API 我的服务器实现的(与它保存在数据库中的词相关),但是你可以修改 queryStr
变量来保存任何查询字符串你想要的。
此外,在 运行 程序中更改 argv[1]
和 argv[2]
以保存所需的值(IP 地址、查询和端口,如果需要 - 默认值为 80)。
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
int main(int argc, char* argv[])
{
cout << "main -start" << endl;
try
{
boost::asio::io_service io_service;
string ipAddress = argv[1]; //"localhost" for loop back or ip address otherwise, i.e.- www.boost.org;
string portNum = argv[2]; //"8000" for instance;
string hostAddress;
if (portNum.compare("80") != 0) // add the ":" only if the port number is not 80 (proprietary port number).
{
hostAddress = ipAddress + ":" + portNum;
}
else
{
hostAddress = ipAddress;
}
string wordToQuery = "aha";
string queryStr = argv[3]; //"/api/v1/similar?word=" + wordToQuery;
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(ipAddress, portNum);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << queryStr << " HTTP/1.1\r\n"; // note that you can change it if you wish to HTTP/1.0
request_stream << "Host: " << hostAddress << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return 1;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code << "\n";
return 1;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r")
{
std::cout << header << "\n";
}
std::cout << "\n";
// Write whatever content we already have to output.
if (response.size() > 0)
{
std::cout << &response;
}
// Read until EOF, writing data to output as we go.
boost::system::error_code error;
while (boost::asio::read(socket, response,boost::asio::transfer_at_least(1), error))
{
std::cout << &response;
}
if (error != boost::asio::error::eof)
{
throw boost::system::system_error(error);
}
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}
我遵循的原始示例在这里:Boost-simple-http-get-request-sync-client
我正在尝试使用某个域的 REST API 发送 http GET 请求。 基本上我要做的是替换以下 curl 请求:
curl -k -H "Content-Type: application/json" -X GET
--data '{"username":"user@name.co", "password":"test"}' https:/domain.name/api/login/
一些 C++ 代码使用 boost::asio
。
我不想在这里找到所有的 c++ 代码,但是一些检查点会很棒。
boost::asio
不是应用程序级库。所以你可以用它打开一个连接,做一个 SSL 握手等等。但是您不能通过 boost::asio
构造 HTTP 请求,因为它仅设计用于 send/receive 数据。
但是,您可以尝试使用 this asio HTTP client example 进行试验。这可能是一件好事。
有一个 Urdl 库,由 Boost.Asio 的作者 Christopher M. Kohlhoff 创建:
Urdl is a cross-platform C++ library for downloading web content using a URL. It provides an easy-to-use extension to standard C++ iostreams and an asynchronous interface for use with Boost.Asio.
您的请求示例如下:
#include <urdl/http.hpp>
urdl::istream is;
// Set request options: method, content type, content
is.set_option(urdl::http::request_method("GET"));
is.set_option(urdl::http::request_content_type("application/json"));
is.set_option(urdl::http::request_content("{\"username\":\"user@name.co\", \"password\":\"test\"}"));
// open HTTP stream at URL
is.open("https:/domain.name/api/login/");
我发现自己也在使用 boost
来发送一些 "customized" HTTP GET 请求 - 我 运行 我的 Ubuntu 机器上的本地服务器 (16.04) .
在我的例子中,请求是一些专有的 API 我的服务器实现的(与它保存在数据库中的词相关),但是你可以修改 queryStr
变量来保存任何查询字符串你想要的。
此外,在 运行 程序中更改 argv[1]
和 argv[2]
以保存所需的值(IP 地址、查询和端口,如果需要 - 默认值为 80)。
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
int main(int argc, char* argv[])
{
cout << "main -start" << endl;
try
{
boost::asio::io_service io_service;
string ipAddress = argv[1]; //"localhost" for loop back or ip address otherwise, i.e.- www.boost.org;
string portNum = argv[2]; //"8000" for instance;
string hostAddress;
if (portNum.compare("80") != 0) // add the ":" only if the port number is not 80 (proprietary port number).
{
hostAddress = ipAddress + ":" + portNum;
}
else
{
hostAddress = ipAddress;
}
string wordToQuery = "aha";
string queryStr = argv[3]; //"/api/v1/similar?word=" + wordToQuery;
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(ipAddress, portNum);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << queryStr << " HTTP/1.1\r\n"; // note that you can change it if you wish to HTTP/1.0
request_stream << "Host: " << hostAddress << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return 1;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code << "\n";
return 1;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r")
{
std::cout << header << "\n";
}
std::cout << "\n";
// Write whatever content we already have to output.
if (response.size() > 0)
{
std::cout << &response;
}
// Read until EOF, writing data to output as we go.
boost::system::error_code error;
while (boost::asio::read(socket, response,boost::asio::transfer_at_least(1), error))
{
std::cout << &response;
}
if (error != boost::asio::error::eof)
{
throw boost::system::system_error(error);
}
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}
我遵循的原始示例在这里:Boost-simple-http-get-request-sync-client