gpt4 book ai didi

c++ - 短读错误-Boost asio同步https调用

转载 作者:行者123 更新时间:2023-12-02 10:11:28 27 4
gpt4 key购买 nike

我正在使用 Boost Asio https synchronous call- Error code 400 bad request 中所述的 boost asio 进行 https 同步调用现在我们得到了响应代码,但是在从套接字读取它时,我收到了短读错误:

   boost::asio::write(socket, request_);
boost::asio::read_until(socket, response_, "\r\n");
string res=make_string(response_);

// Check that response is OK.
std::istream response_stream(&response_);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);

if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
PBLOG_WARN("Invalid response\n");
}
if (status_code != 200)
{
fast_ostringstream oss;
oss << "Response returned with status code: " << status_code << "\n";
PBLOG_WARN(oss.str());
}

boost::asio::read(socket, response_, boost::asio::transfer_all(), error);
if (error != boost::asio::error::eof)
{
fast_ostringstream oss;
oss << "Error : " << error.message();
PBLOG_WARN(oss.str());
return false;
}
else
{
//parse the original resposne
}
在上述逻辑中,它进入 if 循环并将错误作为 Error : short read。请帮我解决这个问题。
谢谢

最佳答案

正如我在 the other answer 中解释的那样,当服务器通过简单地关闭连接来实现关闭时,可以预期短读(“stream_truncaed”)。在这种情况下,缺少常规 SSL 关闭,提示“短读”。
我链接回那里的问题描述了如何在 HTTP 响应解析的上下文中处理错误 - 并得出结论,当响应已被完全解析时,忽略它是安全的。
在您的情况下,您没有明确解析响应,因此您无法真正做出明智的决定。这使您容易受到潜在的滥用,您可能会被攻击者接受格式错误的请求。
1.累了(解决方法)
我们天真的解决方法是:
Live On Coliru

std::istream response_stream(&response_);

if (std::getline(response_stream >> http_version >> status_code, status_message)
&& http_version.substr(0, 5) == "HTTP/")
{
if (status_code != 200) {
std::clog << "Response returned with status code: " << status_code << "\n";
}

boost::system::error_code error;
boost::asio::read(socket, response_, boost::asio::transfer_all(), error);

if (error != boost::asio::error::eof &&
error != boost::asio::ssl::error::stream_truncated)
{
std::clog << "Error : " << error.message() << std::endl;
return 1;
}
else
{
//parse the original resposne

}
} else {
std::clog << "Invalid response\n" << std::endl;
}
打印
Payload:
----
<!DOCTYPE html>
<html>
<title>Coliru Viewer</title>
<head>
....
....
</body>
</html>

----
2.连线:正确执行
但是,我建议您启动游戏并使用 Beast 来解析响应。这样做的好处是您可以信任响应。它解析预期的协议(protocol),而不是盲目地等待 EOF (这可能永远不会出现?)并摸不着头脑,为什么会导致短读。
由于我们现在在响应完成后停止读取,因此我们不会遇到 EOF 或 Short Read。

Note: this method also makes a lot of other things less error-prone and way less insecure. Things like encoding header values (which you don't), proper use of CRLF (which was an error in your previous question), correct calculation of content length etc.

On the response parsing you - randomly - check that HTTP version starts with "HTTP/". However, using Beast you will actually check input sanity and change behaviour accordingly. This means that if your server does something you didn't expect (like, you know, actually using HTTP/1.1 features like chunked encoding) you will still read the response, as if you totally knew about that.

Conversely, if someone attacks your server by sending invalid responses, you have a better chance of not crashing or worse.


Live On Coliru
#include <boost/asio.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
#include <iomanip>

namespace http = boost::beast::http;
using boost::asio::ip::tcp;

// https://postman-echo.com/post see https://docs.postman-echo.com/?version=latest
static std::string
verb = "POST",
server_endpoint = "/post",
hostname = "postman-echo.com",
port_no = "443",
authorization_token = "c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb"
"25fdG9rZW4gPSAiQXV0aDogIj"
"sK",
client_name = "demo program 0.01",
req_str = R"(name=blabla&password=bloblo)";

int main() {
boost::asio::io_service io_service;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);

ctx.set_verify_mode(boost::asio::ssl::verify_peer);
//ctx.load_verify_file("ca.pem");
ctx.add_verify_path("/etc/ssl/certs");

ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
socket(io_service, ctx);

{
#ifdef COLIRU
verb = "GET";
server_endpoint = "/a/cf2748285fa3343a";
hostname = "coliru.stacked-crooked.com";

socket.set_verify_mode(boost::asio::ssl::verify_none);
socket.lowest_layer().connect({ boost::asio::ip::address::from_string("173.203.57.63"), 443 });
#else
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);

tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;

boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
#endif
}

{
socket.handshake(boost::asio::ssl::stream_base::client);

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_type, "application/x-www-form-urlencoded");
request.set(field::connection, field::close);
request.body() = req_str;
request.prepare_payload();

write(socket, request);
// std::clog << request << "\n"; return 1;
}

{
boost::system::error_code ec;
using http::field;
http::response<http::string_body> response_;
boost::beast::flat_buffer buf;
read(socket, buf, response_, ec);

{
//std::clog << "Response: " << response_ << std::endl;
}

// Check that response is OK.
if (!ec && response_.version() == 11) {
if (response_.result() != http::status::ok) {
std::clog << "Response returned with status code: " << response_.result_int() << "\n";
}

std::clog << "Payload:\n----\n" << response_.body() << "\n----" << std::endl;
} else {
std::clog << "Error: " << ec.message() << "\n";
}
}
}
概括
得到教训:
  • 不要低估 HTTP 或 SSL 的复杂性
  • 不要重新发明轮子 - 使用库对您有利!

  • 快乐学习!

    关于c++ - 短读错误-Boost asio同步https调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63376765/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com