1

对于 HTTP 调用,您可以执行以下操作:

http::async_read(m_stream, m_buffer, m_res, beast::bind_front_handler(&RestSession::on_read, shared_from_this())); 

// ... then
void on_read(beast::error_code ec, std::size_t /*bytes_transferred*/)
{
    if (ec)
        return ; // handle error_code

    if (m_res.result() == http::status::not_found)
        return ; // handle target not found
}

但我看不到如何为 websocket 流做同样的事情。如果流目标不存在,则永远不会调用 on_read()。

我尝试从 websocket 流 (m_websocketStream) 中获取下一个流,但从未调用过 lambda,大概是因为 websocket 层已经吞噬了 HTTP 响应:

void on_handshake(beast::error_code ec)
{
    if(ec)
        return fail(ec, "handshake", m_callback);
    
    http::async_read(m_websockStream.next_layer(), m_buffer, m_httpRes, [this, self = shared_from_this()](beast::error_code ec, std::size_t)
    {
        if (m_httpResponse.result() == http::status::not_found)
            return fail("path not found", m_callback);
        else
            m_ws.async_read(m_buffer, beast::bind_front_handler(&WsSession::on_read, self->shared_from_this()));
    });
}

这可能吗?

4

1 回答 1

0

但我看不到如何为 websocket 流做同样的事情。如果流目标不存在,则永远不会调用 on_read()。

这很有意义,因为读取永远不会开始。相反,握手失败,而ecinfail(ec, "handshake", m_callback);将反映这一点。


获取 HTTP 响应详细信息

这也受支持:文档

当客户端从服务器接收到表明升级成功的 HTTP 升级响应时,调用者可能希望对收到的 HTTP 响应消息执行额外的验证。

您可以传递一个额外的响应对象来接收详细信息:

beast::error_code ec;
http::response<http::string_body> res;
s.handshake(res, host + ":" + port, path, ec);

std::cout << "handshake: " << ec.message() << " (" << ec.category().name()
          << ":" << ec.value() << ")" << std::endl;

std::cout << "Declined: " << std::boolalpha
          << (ec == websocket::error::upgrade_declined) << '\n';

std::cout << "Full response:" << res;

这是一个非常简单的测试:

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <istream>
#include "zlib.h"
#include <iostream>

namespace net       = boost::asio;
namespace beast     = boost::beast;
namespace http      = beast::http;
namespace websocket = beast::websocket;
using tcp           = net::ip::tcp;
using socket_t      = websocket::stream<tcp::socket>;

int main() {
    std::string host = "www.example.com";
    auto const port  = "80";
    auto const path  = "/this/path/will/not/exist";

    net::io_context ioc;
    tcp::resolver   resolver{ioc};

    socket_t s{ioc};
    net::connect(beast::get_lowest_layer(s), resolver.resolve(host, port));

    beast::error_code ec;
    http::response<http::string_body> res;
    s.handshake(res, host + ":" + port, path, ec);

    std::cout << "handshake: " << ec.message() << " (" << ec.category().name()
              << ":" << ec.value() << ")" << std::endl;

    std::cout << "Declined: " << std::boolalpha
              << (ec == websocket::error::upgrade_declined) << '\n';

    std::cout << "Full response:" << res;
}

印刷

handshake: The WebSocket handshake was declined by the remote peer (boost.beast.websocket:20)
Declined: true
Full response:HTTP/1.1 200 OK

我想大多数服务器只会拒绝,而不是发送 HTTP Not Found。

于 2021-08-30T21:02:06.047 回答