Как прочитать заголовок неверного запроса в beast::websocket?
У меня есть сервер веб-сокетов (прослушивание интерфейса обратной связи), который должен отвечать на запрос 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 ответ
Цель запроса для запроса на обновление WebSocket должна быть в исходной форме. "localhost:2019/some_location" в абсолютной форме и поэтому недопустим. Мне кажется, что вам нужно иметь возможность специально обрабатывать HTTP-запросы, которые не являются обновлениями WebSocket, а для реальных обновлений WebSocket пусть поток websocket обрабатывает его, выполняя рукопожатие.
Это описано в документации: https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/using_websocket/handshaking_servers.html
А также в примерах: 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
,