如何读取 beast::websocket 中错误请求的 header?
How to read the header of a bad request in beast::websocket?
我有一个应该响应 GET 请求的 websocket 服务器(侦听环回接口)。这是我的做法
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
)。
有办法吗?
解决方法:手动读取header,检查是否升级
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);
}
});
WebSocket 升级请求的请求目标必须为原始格式。 "localhost:2019/some_location" 是绝对形式,因此是非法的。在我看来,您想要的是能够专门处理不是 WebSocket 升级的 HTTP 请求,对于实际的 WebSocket 升级,让 websocket 流通过执行握手来处理它。
tl;dr:使用beast::http::async_read
自己阅读请求,看是否是使用beast::websocket::is_upgrade
的websocket升级。如果是升级,构造 beast::websocket::stream
并在其上调用 async_accept
请求,否则以您想要的方式处理 HTTP 请求并使用 beast::http::async_write
.[= 自己发回响应17=]
我有一个应该响应 GET 请求的 websocket 服务器(侦听环回接口)。这是我的做法
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
)。
有办法吗?
解决方法:手动读取header,检查是否升级
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);
}
});
WebSocket 升级请求的请求目标必须为原始格式。 "localhost:2019/some_location" 是绝对形式,因此是非法的。在我看来,您想要的是能够专门处理不是 WebSocket 升级的 HTTP 请求,对于实际的 WebSocket 升级,让 websocket 流通过执行握手来处理它。
tl;dr:使用beast::http::async_read
自己阅读请求,看是否是使用beast::websocket::is_upgrade
的websocket升级。如果是升级,构造 beast::websocket::stream
并在其上调用 async_accept
请求,否则以您想要的方式处理 HTTP 请求并使用 beast::http::async_write
.[= 自己发回响应17=]