Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

109 lines
3.1 KiB
C++

// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#define CAF_SUITE net.http.server
#include "caf/net/http/server.hpp"
#include "net-test.hpp"
using namespace caf;
using namespace caf::literals;
using namespace std::literals::string_literals;
namespace {
struct app_t {
net::http::header hdr;
caf::byte_buffer payload;
template <class LowerLayerPtr>
error init(net::socket_manager*, LowerLayerPtr, const settings&) {
return none;
}
template <class LowerLayerPtr>
bool prepare_send(LowerLayerPtr) {
return true;
}
template <class LowerLayerPtr>
bool done_sending(LowerLayerPtr) {
return true;
}
template <class LowerLayerPtr>
void abort(LowerLayerPtr, const error& reason) {
CAF_FAIL("app::abort called: " << reason);
}
template <class LowerLayerPtr>
bool consume(LowerLayerPtr down, net::http::context ctx,
const net::http::header& request_hdr,
caf::const_byte_span body) {
hdr = request_hdr;
down->send_response(ctx, net::http::status::ok, "text/plain",
"Hello world!");
payload.assign(body.begin(), body.end());
return true;
}
string_view field(string_view key) {
if (auto i = hdr.fields().find(key); i != hdr.fields().end())
return i->second;
else
return {};
}
string_view param(string_view key) {
auto& qm = hdr.query();
if (auto i = qm.find(key); i != qm.end())
return i->second;
else
return {};
}
};
using mock_server_type = mock_stream_transport<net::http::server<app_t>>;
} // namespace
BEGIN_FIXTURE_SCOPE(host_fixture)
SCENARIO("the server parses HTTP GET requests into header fields") {
GIVEN("valid HTTP GET request") {
string_view req = "GET /foo/bar?user=foo&pw=bar HTTP/1.1\r\n"
"Host: localhost:8090\r\n"
"User-Agent: AwesomeLib/1.0\r\n"
"Accept-Encoding: gzip\r\n\r\n";
string_view res = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 12\r\n"
"\r\n"
"Hello world!";
WHEN("sending it to an HTTP server") {
mock_server_type serv;
CHECK_EQ(serv.init(), error{});
serv.push(req);
THEN("the HTTP layer parses the data and calls the application layer") {
CHECK_EQ(serv.handle_input(), static_cast<ptrdiff_t>(req.size()));
auto& app = serv.upper_layer.upper_layer();
auto& hdr = app.hdr;
CHECK_EQ(hdr.method(), net::http::method::get);
CHECK_EQ(hdr.version(), "HTTP/1.1");
CHECK_EQ(hdr.path(), "foo/bar");
CHECK_EQ(app.field("Host"), "localhost:8090");
CHECK_EQ(app.field("User-Agent"), "AwesomeLib/1.0");
CHECK_EQ(app.field("Accept-Encoding"), "gzip");
}
AND("the server properly formats a response from the application layer") {
CHECK_EQ(serv.output_as_str(), res);
}
}
}
}
END_FIXTURE_SCOPE()