Как прочитать заголовок неверного запроса в beast :: websocket? - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть сервер веб-сокетов (прослушивание интерфейса обратной связи), который должен отвечать на запрос GET.Вот как я это делаю

ws_.async_accept_ex(
    [self = shared_from_this()](websocket::response_type& res) //
    {
        if (res.result_int() == 400) { // bad request, assume HTTP GET
            osstream response;
            /* invoke request handlers */
            for (auto& do_handle : self->handlers) {
                do_handle({ "GET" }, response);
                /* if responded, assing response to the body*/
                if (response.tellp()) {
                    res.content_length(response.str().size());
                    res.body() = std::move(response.str());
                    break;
                }
            }
        }
    },
    net::bind_executor(strand_,
        [self = shared_from_this()](beast::error_code ec) {
            self->on_accept(ec);
}));

Но мне также нужно уметь обрабатывать местоположения (например, localhost:2019/some_location).

Есть ли способ?

Решение: прочитайте заголовок вручную, проверьте, является ли это обновление

beast::flat_buffer buffer_;
websocket::request_type req_;

/*
  ...
  ...
*/
        http::async_read(ws_.next_layer(), buffer_, req_,
        [self=shared_from_this()](beast::error_code ec, size_t)
        {
            if(ec){
                fail(ec, "[http] read");
                return;
            }
            if(websocket::is_upgrade(self->req_)){
                self->ws_.accept(self->req_,ec);
                self->on_accept(ec);
            }
            else{
                osstream response;
                websocket::response_type res;
                vector<string_view> req_args
                    { "GET", self->req_.base().target().begin() };
                /* invoke request handlers */ 
                for(auto &do_handle : self->handlers){
                    do_handle(req_args, response);
                    /* if responded, assing response to the body*/
                    if(response.tellp()){
                        res.content_length(response.str().size());
                        res.body() = std::move(response.str());
                        break;
                }}
                http::write(self->ws_.next_layer(), res);
            }
        });

1 Ответ

0 голосов
/ 09 февраля 2019

Цель запроса для запроса на обновление WebSocket должна быть в исходной форме."localhost: 2019 / some_location" в абсолютной форме и поэтому недопустим.Мне кажется, что вам нужно иметь возможность специально обрабатывать HTTP-запросы, которые не являются обновлениями WebSocket, а для реальных обновлений WebSocket пусть поток веб-сокетов обрабатывает его, выполняя рукопожатие.

Это рассматривается вдокументация: https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/using_websocket/handshaking_servers.html#beast.using_websocket.handshaking_servers.passing_http_requests

А также в примерах: https://github.com/boostorg/beast/blob/06efddd8b851610b5b3a5832ac87f1c52b838d9b/example/advanced/server/advanced_server.cpp#L665

tl; dr: Прочтите запрос самостоятельно, используя beast::http::async_read, посмотрите, является ли это обновление через веб-сокет, используя beast::websocket::is_upgrade.Если это обновление, создайте beast::websocket::stream и вызовите на нем async_accept вместе с запросом, в противном случае обработайте HTTP-запрос так, как вы хотите, и отправьте ответ самостоятельно, используя beast::http::async_write.

...