Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crow does not return "404 Not Found\r\n" when calling an invalid route because the socket is closed before the response can be asynchronously written to it #1019

Open
GitGud711 opened this issue Apr 11, 2025 · 0 comments

Comments

@GitGud711
Copy link

This issue affects crow v1.2.0 and higher.

In #499 the HTTP parser code was changed so that a route is searched for as soon as the HTTP method and URL are parsed from the request. If no route is found, the parsing is terminated with error CHPE_INVALID_EOF_STATE, causing the crow::Connection<>::do_read() function to terminate the socket early because of the error state. Before the socket was terminated though, crow::Connection<>::handle_url() called crow::Connection<>::complete_request(), which prepared the response buffers and was supposed to write them to the socket asynchronously (do_write_general() -> do_write()), but it never did.

The 2 problems I see are:

  • Not finding a route is treated as a parsing error, when it in fact shouldn't be. It shouldn't end parsing with CHPE_INVALID_EOF_STATE.
  • crow::Connection<>'s close_connection_ is not set in crow::Connection<>::handle_url() before calling crow::Connection<>::complete_request() when parsing terminates early because the route was not found. This means that the socket is not closed after the response buffers are written to it.

Overall, finding a route should be treated as a success case, but not as CHPE_OK. My suggestion would be to add another error, something like CHPE_OK_ROUTE_NOT_FOUND or something similar, and handle this case where required.

I tested this on Ubuntu 20.04.6 LTS on a x64 VirtualBox VM, using boost 1.76 and crow v1.2.0. I initiated a crow::SimpleApp and set multithreaded() on it.
For the REST request and socket logic I used:

  • boost::beast::http::request<boost::beast::http::string_body> and boost::beast::http::response<boost::beast::http::string_body>
  • boost::asio::io_context and boost::asio::ip::tcp::socket to create the socket
  • boost::beast::http::write and boost::beast::http::read to write to and read from the socket.

If required I can provide a code sample.

I tested a hacky fix on my setup where I added a new error to the list (CROW_XX(OK_ROUTE_NOT_FOUND, "route not found for request")), and set parser_.http_errno to the error number and close_connection_ to true inside handle_url(), but this is not a proper way to do it. I don't know where and how to set this error using its name, not its index.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant