【问题标题】:Sending http GET request using boost::asio, similar to cURL使用 boost::asio 发送 http GET 请求,类似于 cURL
【发布时间】:2015-04-27 23:56:18
【问题描述】:

我正在尝试使用某个域的 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++ 代码,但是一些检查点会很棒。

【问题讨论】:

  • 我读过关于 libcurl 的文章,但我的目标是用 boost 做同样的事情
  • 好吧,boost 中没有任何东西可以远程完成 curl one-liner 所做的事情。考虑 HTTP 重定向响应、分块编码、保持活动、压缩、身份验证、证书......

标签: c++ curl boost boost-asio


【解决方案1】:

我发现自己也在使用 boost 以发送一些“自定义”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

【讨论】:

    【解决方案2】:

    boost::asio 不是应用程序级库。因此,您可以打开与它的连接、进行 SSL 握手等。但是你不能通过 boost::asio 构造 HTTP 请求,因为它只是为了发送/接收数据而设计的。

    但是,您可以尝试使用this asio HTTP client example。可能这可能是一件好事。

    【讨论】:

      【解决方案3】:

      有一个 Urdl 库,由 Boost.Asio 的作者 Christopher M. Kohlhoff 创建:

      Urdl 是一个跨平台的 C++ 库,用于下载 Web 内容,使用 一个网址。它为标准 C++ iostreams 提供了一个易于使用的扩展 以及用于 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/");
      

      【讨论】:

      猜你喜欢
      • 2012-02-29
      • 1970-01-01
      • 2019-06-04
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 1970-01-01
      • 2015-03-15
      • 2016-05-12
      相关资源
      最近更新 更多