Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/crow/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,14 @@ namespace crow
}
}

/// Non-blocking version of \ref run()
std::future<void> run_async()
{
return std::async(std::launch::async, [&] {
this->run();
});
}

/// Stop the server
void stop()
{
Expand Down
112 changes: 54 additions & 58 deletions tests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,10 +463,7 @@ TEST_CASE("server_handling_error_request")
});
// Server<SimpleApp> server(&app, LOCALHOST_ADDRESS, 45451);
// auto _ = async(launch::async, [&]{server.run();});
auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
std::string sendmsg = "POX";
asio::io_service is;
Expand Down Expand Up @@ -498,10 +495,7 @@ TEST_CASE("server_handling_error_request_http_version")
([] {
return "A";
});
auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
std::string sendmsg = "POST /\r\nContent-Length:3\r\nX-HeaderTest: 123\r\n\r\nA=B\r\n";
asio::io_service is;
Expand Down Expand Up @@ -538,14 +532,8 @@ TEST_CASE("multi_server")
return "B";
});

auto _ = async(launch::async,
[&] {
app1.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _2 = async(launch::async,
[&] {
app2.bindaddr(LOCALHOST_ADDRESS).port(45452).run();
});
auto _ = app1.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
auto _2 = app2.bindaddr(LOCALHOST_ADDRESS).port(45452).run_async();
app1.wait_for_server_start();
app2.wait_for_server_start();

Expand Down Expand Up @@ -1354,10 +1342,7 @@ TEST_CASE("middleware_context")
return "";
});

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
std::string sendmsg = "GET /\r\n\r\n";
asio::io_service is;
Expand Down Expand Up @@ -1438,10 +1423,7 @@ TEST_CASE("local_middleware")

app.validate();

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
asio::io_service is;

Expand Down Expand Up @@ -1494,10 +1476,7 @@ TEST_CASE("middleware_cookieparser")
return "";
});

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
std::string sendmsg =
"GET /\r\nCookie: key1=value1; key2=\"val=ue2\"; key3=\"val\"ue3\"; "
Expand Down Expand Up @@ -1614,10 +1593,7 @@ TEST_CASE("bug_quick_repeated_request")
return "hello";
});

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
std::string sendmsg = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";
asio::io_service is;
Expand Down Expand Up @@ -1660,10 +1636,7 @@ TEST_CASE("simple_url_params")

/// params?h=1&foo=bar&lol&count[]=1&count[]=4&pew=5.2

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
asio::io_service is;
std::string sendmsg;
Expand Down Expand Up @@ -1886,14 +1859,31 @@ TEST_CASE("route_dynamic")

TEST_CASE("multipart")
{
//
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"hello\"
//
//world
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"world\"
//
//hello
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"multiline\"
//
//text
//text
//text
//--CROW-BOUNDARY--
//

std::string test_string = "--CROW-BOUNDARY\r\nContent-Disposition: form-data; name=\"hello\"\r\n\r\nworld\r\n--CROW-BOUNDARY\r\nContent-Disposition: form-data; name=\"world\"\r\n\r\nhello\r\n--CROW-BOUNDARY\r\nContent-Disposition: form-data; name=\"multiline\"\r\n\r\ntext\ntext\ntext\r\n--CROW-BOUNDARY--\r\n";

SimpleApp app;

CROW_ROUTE(app, "/multipart")
([](const crow::request& req, crow::response& res) {
multipart::message msg(req);
res.add_header("Content-Type", "multipart/form-data; boundary=CROW-BOUNDARY");
res.body = msg.dump();
res.end();
});
Expand All @@ -1911,6 +1901,25 @@ TEST_CASE("multipart")
app.handle(req, res);

CHECK(test_string == res.body);


multipart::message msg(req);
CHECK("hello" == msg.get_part_by_name("world").body);
CHECK("form-data" == msg.get_part_by_name("hello").get_header_object("Content-Disposition").value);
}

// Check with `"` encapsulating the boundary (.NET clients do this)
{
request req;
response res;

req.url = "/multipart";
req.add_header("Content-Type", "multipart/form-data; boundary=\"CROW-BOUNDARY\"");
req.body = test_string;

app.handle(req, res);

CHECK(test_string == res.body);
}
} // multipart

Expand Down Expand Up @@ -1988,12 +1997,9 @@ TEST_CASE("stream_response")

app.validate();

//running the test on a separate thread to allow the client to sleep
// running the test on a separate thread to allow the client to sleep
std::thread runTest([&app, &key_response, key_response_size]() {
auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
asio::io_service is;
std::string sendmsg;
Expand Down Expand Up @@ -2069,10 +2075,7 @@ TEST_CASE("websocket")

app.validate();

auto _ = async(launch::async,
[&] {
app.bindaddr(LOCALHOST_ADDRESS).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
app.wait_for_server_start();
asio::io_service is;

Expand Down Expand Up @@ -2244,12 +2247,8 @@ TEST_CASE("zlib_compression")
res.end();
});

auto t1 = async(launch::async, [&] {
app_deflate.bindaddr(LOCALHOST_ADDRESS).port(45451).use_compression(compression::algorithm::DEFLATE).run();
});
auto t2 = async(launch::async, [&] {
app_gzip.bindaddr(LOCALHOST_ADDRESS).port(45452).use_compression(compression::algorithm::GZIP).run();
});
auto t1 = app_deflate.bindaddr(LOCALHOST_ADDRESS).port(45451).use_compression(compression::algorithm::DEFLATE).run_async();
auto t2 = app_gzip.bindaddr(LOCALHOST_ADDRESS).port(45452).use_compression(compression::algorithm::GZIP).run_async();

app_deflate.wait_for_server_start();
app_gzip.wait_for_server_start();
Expand Down Expand Up @@ -2668,9 +2667,7 @@ TEST_CASE("get_port")

const std::uint16_t port = 12345;

auto _ = async(launch::async, [&] {
app.port(port).run();
});
auto _ = app.port(port).run_async();

app.wait_for_server_start();
CHECK(app.port() == port);
Expand All @@ -2690,9 +2687,8 @@ TEST_CASE("timeout")
return "hello";
});

auto _ = async(launch::async, [&] {
app.bindaddr(LOCALHOST_ADDRESS).timeout(timeout).port(45451).run();
});
auto _ = app.bindaddr(LOCALHOST_ADDRESS).timeout(timeout).port(45451).run_async();

app.wait_for_server_start();
asio::io_service is;
std::string sendmsg = "GET /\r\n\r\n";
Expand Down