Add extra log when status code is not defined.

Just to document behaviour when returning status that is
not well-known.
This commit is contained in:
konrad 2022-05-08 13:44:45 +02:00 committed by Farook Al-Sammarraie
parent 45ced144a7
commit 7e4f57486c
3 changed files with 76 additions and 7 deletions

View File

@ -11,7 +11,7 @@ Using `/hello` means the client will need to access `http://example.com/hello` i
A path can have parameters, for example `/hello/<int>` will allow a client to input an int into the url which will be in the handler (something like `http://example.com/hello/42`).<br>
Parameters can be `<int>`, `<uint>`, `<double>`, `<string>`, or `<path>`.<br>
It's worth noting that the parameters also need to be defined in the handler, an example of using parameters would be to add 2 numbers based on input:
```cpp
```cpp
CROW_ROUTE(app, "/add/<int>/<int>")
([](int a, int b)
{
@ -45,7 +45,10 @@ Please note that in order to return a response defined as a parameter you'll nee
Alternatively, you can define the response in the body and return it (`#!cpp ([](){return crow::response()})`).<br>
For more information on `crow::response` go [here](../../reference/structcrow_1_1response.html).<br><br>
!!! note
When your status code is not well-known e.g. crow::response(123) it will get converted into 500.
### Return statement
A `crow::response` is very strictly tied to a route. If you can have something in a response constructor, you can return it in a handler.<br><br>
The main return type is `std::string`, although you could also return a `crow::json::wvalue` or `crow::multipart::message` directly.<br><br>
@ -60,14 +63,14 @@ to use the returnable class, you only need your class to publicly extend `crow::
Your class should look like the following:
```cpp
class a : public crow::returnable
class a : public crow::returnable
{
a() : returnable("text/plain"){};
...
...
...
std::string dump() override
{
return this.as_string();

View File

@ -317,12 +317,16 @@ namespace crow
buffers_.reserve(4 * (res.headers.size() + 5) + 3);
if (!statusCodes.count(res.code))
res.code = 500;
{
auto& status = statusCodes.find(res.code)->second;
buffers_.emplace_back(status.data(), status.size());
CROW_LOG_WARNING << this << " status code "
<< "(" << res.code << ")"
<< " not defined, returning 500 instead";
res.code = 500;
}
auto& status = statusCodes.find(res.code)->second;
buffers_.emplace_back(status.data(), status.size());
if (res.code >= 400 && res.body.empty())
res.body = statusCodes[res.code].substr(9);

View File

@ -571,6 +571,61 @@ TEST_CASE("multi_server")
app2.stop();
} // multi_server
TEST_CASE("undefined_status_code")
{
SimpleApp app;
CROW_ROUTE(app, "/get123")
([] {
//this status does not exists statusCodes map defined in include/crow/http_connection.h
const int undefinedStatusCode = 123;
return response(undefinedStatusCode, "this should return 500");
});
CROW_ROUTE(app, "/get200")
([] {
return response(200, "ok");
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(0).run_async();
app.wait_for_server_start();
asio::io_service is;
auto sendRequestAndGetStatusCode = [&](const std::string& route) -> unsigned {
asio::ip::tcp::socket socket(is);
socket.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string(LOCALHOST_ADDRESS), app.port()));
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << route << " HTTP/1.0\r\n";
request_stream << "Host: " << LOCALHOST_ADDRESS << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned status_code = 0;
response_stream >> status_code;
return status_code;
};
unsigned statusCode = sendRequestAndGetStatusCode("/get200");
CHECK(statusCode == 200);
statusCode = sendRequestAndGetStatusCode("/get123");
CHECK(statusCode == 500);
app.stop();
} // undefined_status_code
TEST_CASE("json_read")
{
{
@ -2025,7 +2080,11 @@ TEST_CASE("send_file")
app.handle(req, res);
CHECK(200 == res.code);
REQUIRE(res.headers.count("Content-Type"));
CHECK("image/jpeg" == res.headers.find("Content-Type")->second);
REQUIRE(res.headers.count("Content-Length"));
CHECK(to_string(statbuf_cat.st_size) == res.headers.find("Content-Length")->second);
}
@ -2039,7 +2098,10 @@ TEST_CASE("send_file")
CHECK_NOTHROW(app.handle(req, res));
CHECK(200 == res.code);
REQUIRE(res.headers.count("Content-Type"));
CHECK("text/plain" == res.headers.find("Content-Type")->second);
REQUIRE(res.headers.count("Content-Length"));
CHECK(to_string(statbuf_badext.st_size) == res.headers.find("Content-Length")->second);
}
} // send_file