Comments (13)
@ashtum we should document this, where the Table of Contents entry for the paragraph says "stream_truncated error" so people can find it easily
from beast.
This is a known issue with some of the web servers in the wild; they don't perform a proper SSL shutdown procedure and close the TCP socket unexpectedly. For example, if you try connecting to google.com, you would get that error, but not when connecting to github.com.
By the way, because this error happens exactly when you want to close the SSL stream, you can safely ignore this error (as all internet browsers do):
beast::error_code ec;
stream.shutdown(ec);
if (ec == net::error::eof || ec == net::ssl::error::stream_truncated)
ec = {};
from beast.
Thanks for the help!
I'm still struggling to figure out how to modify the example code to get it to print the "Hello" response from the server:
In the client I tried replacing:
http::read(stream, buffer, res);
with:
boost::beast::error_code myec;
http::read(stream, buffer, res, myec);
if(myec && myec != ssl::error::stream_truncated)
throw beast::system_error{myec};
but this doesn't seem to do the trick. I still only get to see the HTTP/1.1 200 OK
part, not the Hello
ee@vp:~/sand/beasttest % g++ main.cpp -lssl -lcrypto && ./a.out localhost 51733 /
HTTP/1.1 200 OK
Error: stream truncated
ee@vp:~/sand/beasttest % wget --no-check-certificate -q -O - https://localhost:51733
Hello
from beast.
@EelisVP In client mode, http::read(stream, buffer, res, myec)
should complete successfully. The net::ssl::error::stream_truncated
error only occurs during the call to stream.shutdown(ec)
.
What type of response body are you using? Could you please provide a minimal reproducible example of your issue?
I recommend first trying the http_client_sync_ssl.cpp
example without any modifications to see what it prints.
from beast.
@ashtum As described in the opening post, the issue can be reproduced by taking http_client_sync_ssl.cpp
and only changing ssl::verify_peer
to ssl::verify_none
(because the server's certificate was self-signed). With only this modification, I get this result:
ee@vp:~/sand/beasttest % g++ -I /home/eelis/apps/sources/boost_1_85_0 main.cpp -lssl -lcrypto && ./a.out localhost 51733 /
Error: stream truncated [asio.ssl.stream:1]
from beast.
It seems you successfully get a response from the server, but it is just empty. Note that the target in the wget --no-check-certificate -q -O - https://localhost:51733
command is empty, while in ./a.out localhost 51733 /
, the target is "/".
What happens if you try ./a.out localhost 51733 ""
?
from beast.
Note that the target in the
wget --no-check-certificate -q -O - https://localhost:51733
command is empty, while in./a.out localhost 51733 /
, the target is "/".
Nah, wget
asks for /
automatically if you don't provide a target. So wgetting https://localhost:51733
is the same as wgetting https://localhost:51733/
.
What happens if you try
./a.out localhost 51733 ""
?
Same result (because the server doesn't look at the target at all).
from beast.
Does http::read(stream, buffer, res, myec)
complete without any errors, or are you getting net::ssl::error::stream_truncated
on that line? Could you try setting req.keep_alive(true);
?
from beast.
Does
http::read(stream, buffer, res, myec)
complete without any errors, or are you gettingnet::ssl::error::stream_truncated
on that line?
If I use:
boost::beast::error_code myec;
http::read(stream, buffer, res, myec);
if(myec) std::cout << "oh there was an error: " << myec << std::endl;
then I do see oh there was an error: asio.ssl.stream:1
at runtime, so it's really the read
that's reporting the error.
Could you try setting
req.keep_alive(true);
?
Sure. No effect.
from beast.
It seems we need to manually set the end of stream when parser completes with ssl::error::stream_truncated
error, this should work:
http::response_parser<http::dynamic_body> p;
beast::error_code ec;
http::read(stream, buffer, p, ec);
if(ec == net::ssl::error::stream_truncated && p.need_eof())
p.put_eof(ec);
std::cout << p.get() << std::endl;
from beast.
OK, the reason the Beast parser needs a manual EOF is that your Python server doesn't set the Content-Length
header nor does it perform a proper SSL shutdown procedure to indicate the EOF.
If you change the Python code for the server to the following, it should work fine:
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
message = b'hello'
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header('Content-Length', str(len(message)))
self.end_headers()
self.wfile.write(message)
from beast.
@ashtum Ah fantastic, with that change in the client, I do indeed get the hello
! Thanks!
from beast.
Yes, the only way to get it to work in Beast is to manually set the EOF on the parser.
The reason this is not the default behavior is that it poses a security risk. Without a Content-Length
header, the body length is determined by EOF, which allows an attacker to close the connection and truncate the body contents. Therefore, an HTTPS server should either perform a proper TLS shutdown or avoid relying on EOF by setting the Content-Length
header.
If you try using curl on your server, you will see it also completes with an error.
from beast.
Related Issues (20)
- Question about field used hash function HOT 6
- Web link is broken HOT 1
- Websocket Async Client as a DLL HOT 1
- CI should build documentation on Windows platform
- Beast Server Exits for reasons that Client is disconnecting? HOT 2
- Any benefit to multiple sockets between a server and a single client instance using Boost Beast? HOT 4
- Using a minimal executor causes compile errors with beast::websocket HOT 3
- How to check whether there is any available data on the stream HOT 4
- [HELP] Server heartbeat and response HOT 2
- Limitation of `websocket::stream::accept(...)` and `websocket::stream::async_accept(...)`. HOT 3
- Session communication without Mutex? HOT 4
- The beast Server Exits frequently HOT 3
- Is it possible to serialize the body directly to file from a request_parser<empty_body> HOT 7
- Beast shouldn't have a root Jamfile
- Timeout for async_write, which must not happen at all HOT 7
- stream.async_connect() ambiguous overload with asio::as_tuple(asio::use_awaitable) HOT 3
- boost::beast::http::async_read core dumped when reading chunked response HOT 4
- The problem of async_write_header or async_write HOT 3
- coredump about http BIO_write HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from beast.