【问题标题】:convert boost beast http request to a string and write to ostringstream将 boost beast http 请求转换为字符串并写入 ostringstream
【发布时间】:2020-08-17 18:07:33
【问题描述】:

我正在尝试使用 boost beast 进行 http 调用,并希望在写入套接字之前先编写它;我尝试使用 ostringstream 来获取 request 的值以在打印的日志中获取它并得到以下错误消息:

string verb = "POST";
using http::field;
http::request<http::string_body> request;
request.method_string(verb);
request.target(server_endpoint);
request.version(11);
request.set(field::host, hostname);
request.set(field::accept, "*/*");
request.set(field::authorization, authorization_token);
request.set(field::user_agent, client_name);
request.set(field::content_length, req_str.length());
request.set(field::content_type, "application/x-www-form-urlencoded");
request.set(field::connection, field::close);
request.body() = req_str;
request.prepare_payload();
fast_ostringstream oss;
oss <<"Request message" << request;
PBLOG_INFO(oss.str());
oss.clear();



HttpTracRequestHandler.cpp:78:26: error: invalid operands to binary expression ('framework::string_::fast_ostringstream' and
      'http::request<http::string_body>' (aka 'boost::beast::http::message<true, boost::beast::http::basic_string_body<char,
      std::char_traits<char>, std::allocator<char> >, boost::beast::http::basic_fields<std::allocator<char> > >'))
        oss <<"Request message" << request;
        ~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~
/BARXPBViewstore/GIT_Workspace/barx_rel/mq8_barx/barx-server/appl/include/FoxException/GenericException.h:133:19: note: candidate function
      [with TData = boost::beast::http::message<true, boost::beast::http::basic_string_body<char, std::char_traits<char>,
      std::allocator<char> >, boost::beast::http::basic_fields<std::allocator<char> > >] not viable: no known conversion from
      'framework::string_::fast_ostringstream' to 'GenericException &' for 1st argument
GenericException& operator<<(GenericException &e, const TData& data)
                  ^
/BARXPBViewstore/GIT_Workspace/boost/boost_1_70_0/boost/beast/http/impl/write.hpp:921:1: note: candidate function [with isRequest = true,
      Body = boost::beast::http::basic_string_body<char, std::char_traits<char>, std::allocator<char> >, Fields =
      boost::beast::http::basic_fields<std::allocator<char> >] not viable: no known conversion from 'framework::string_::fast_ostringstream'
      to 'std::ostream &' (aka 'basic_ostream<char> &') for 1st argument
operator<<(std::ostream& os,
^
/BARXPBViewstore/GIT_Workspace/boost/boost_1_70_0/boost/beast/http/write.hpp:721:1: note: candidate function [with isRequest = true, Fields
      = boost::beast::http::basic_fields<std::allocator<char> >] not viable: no known conversion from
      'framework::string_::fast_ostringstream' to 'std::ostream &' (aka 'basic_ostream<char> &') for 1st argument
operator<<(std::ostream& os,
^
/BARXPBViewstore/GIT_Workspace/boost/boost_1_70_0/boost/beast/http/impl/write.hpp:901:1: note: candidate function [with Fields =
      boost::beast::http::basic_fields<std::allocator<char> >] not viable: no known conversion from 'framework::string_::fast_ostringstream'
      to 'std::ostream &' (aka 'basic_ostream<char> &') for 1st argument

【问题讨论】:

    标签: boost boost-beast ostringstream


    【解决方案1】:

    您的代码看起来很正常。事实上,它适用于标准字符串流:

    Live On Coliru

    #include <boost/beast/http.hpp>
    #include <iostream>
    #include <sstream>
    
    namespace http = boost::beast::http;
    
    #define PBLOG_INFO(a) do { std::clog << (a) << std::endl; } while(0);
    
    int main() {
        std::string verb = "POST", req_str = "payload";
        using http::field;
        http::request<http::string_body> request;
        request.method_string(verb);
        request.target("server_endpoint");
        request.version(11);
        request.set(field::host, "hostname");
        request.set(field::accept, "*/*");
        request.set(field::authorization, "authorization_token");
        request.set(field::user_agent, "client_name");
        request.set(field::content_length, req_str.length());
        request.set(field::content_type, "application/x-www-form-urlencoded");
        request.set(field::connection, field::close);
        request.body() = req_str;
        request.prepare_payload();
    
        {
            std::ostringstream oss;
            oss <<"Request message " << request;
            PBLOG_INFO(oss.str());
            oss.clear();
        }
    }
    

    打印

    Request message POST server_endpoint HTTP/1.1
    Host: hostname
    Accept: */*
    Authorization: authorization_token
    User-Agent: client_name
    Content-Type: application/x-www-form-urlencoded
    Connection: Close
    Content-Length: 7
    payload
    

    有什么问题?

    问题似乎是 Beast 的流式操作符重载不适用于 fast_ostringstream 的任何类型。这是设计使然:

      no known conversion from 'framework::string_::fast_ostringstream'
      to 'std::ostream &' (aka 'basic_ostream<char> &')
    

    作者fast_ostringstream 显然是在作弊,因为它可能很快,但绝对不是ostream&amp; :)。

    我试图通过创建自己的作弊流来得到类似的错误:

    struct my_cheat_stream {
        using Device = boost::iostreams::back_insert_device<std::string>;
        using Stream = boost::iostreams::stream<Device>;
    
        std::string buf;
        Stream _impl { buf };
    
        template <typename T> my_cheat_stream& operator<<(T&& rhs) {
            _impl << std::forward<T>(rhs);
            return *this;
        }
    
        std::string&&    str()&& { _impl.flush(); return std::move(buf); }
        std::string_view str()&  { _impl.flush(); return buf; }
    
        void clear() {
            buf.clear();
            _impl.clear(std::ios::failbit|std::ios::badbit);
        }
    };
    

    但是,it simply compiles,因为很明显,operator&lt;&lt; &lt;T&gt;() 只适用。也许你可以相应地修复你的fast_ostringstream,或者使用其他东西。

    肮脏的解决方法:

    你可以使用上面的反例作为杠杆:

    template <typename Stream> struct wrap_non_std_stream {
        Stream& _wrapped;
        explicit wrap_non_std_stream(Stream& ref) : _wrapped(ref) {}
    
        template <typename T> auto& operator<<(T const& rhs) {
            _wrapped << rhs;
            return *this;
        }
    
        auto& operator<<(std::ostream&(*manip)(std::ostream&)) {
            _wrapped << manip;
            return *this;
        }
    };
    

    现在应该可以了

        fast_ostringstream oss;
        wrap_non_std_stream woss{oss};
        woss << "Request message " << request;
    

    如果底层流支持,它也将支持操纵器:

        woss << std::endl << std::fixed << std::boolalpha << std::flush;
    

    【讨论】:

    • 非常感谢。我用过ostringstream oss;在日志中打印,我们能够点击destiantion url并能够使用boost beast解析响应。
    猜你喜欢
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    相关资源
    最近更新 更多