Support asynchronous requests with internal I/O context
This commit is contained in:
parent
571fe8b0ad
commit
49e2bb9261
2 changed files with 34 additions and 17 deletions
|
|
@ -216,6 +216,7 @@ namespace SimpleWeb {
|
||||||
/// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
|
/// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
|
||||||
/// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
|
/// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
|
||||||
std::shared_ptr<Response> request(const std::string &method, const std::string &path = {"/"}, string_view content = {}, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
|
std::shared_ptr<Response> request(const std::string &method, const std::string &path = {"/"}, string_view content = {}, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
|
||||||
|
start_internal_io_service_handler_thread();
|
||||||
std::promise<std::shared_ptr<Response>> response_promise;
|
std::promise<std::shared_ptr<Response>> response_promise;
|
||||||
std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
|
std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
|
||||||
std::shared_ptr<Response> response;
|
std::shared_ptr<Response> response;
|
||||||
|
|
@ -251,6 +252,7 @@ namespace SimpleWeb {
|
||||||
/// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
|
/// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
|
||||||
/// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
|
/// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
|
||||||
std::shared_ptr<Response> request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
|
std::shared_ptr<Response> request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
|
||||||
|
start_internal_io_service_handler_thread();
|
||||||
std::promise<std::shared_ptr<Response>> response_promise;
|
std::promise<std::shared_ptr<Response>> response_promise;
|
||||||
std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
|
std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
|
||||||
std::shared_ptr<Response> response;
|
std::shared_ptr<Response> response;
|
||||||
|
|
@ -465,8 +467,7 @@ namespace SimpleWeb {
|
||||||
port = parsed_host_port.second;
|
port = parsed_host_port.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Connection> get_connection() noexcept {
|
void start_internal_io_service_handler_thread() noexcept {
|
||||||
std::shared_ptr<Connection> connection;
|
|
||||||
LockGuard lock(connections_mutex);
|
LockGuard lock(connections_mutex);
|
||||||
|
|
||||||
if(!io_service) {
|
if(!io_service) {
|
||||||
|
|
@ -477,6 +478,15 @@ namespace SimpleWeb {
|
||||||
io_service->run();
|
io_service->run();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Connection> get_connection() noexcept {
|
||||||
|
std::shared_ptr<Connection> connection;
|
||||||
|
LockGuard lock(connections_mutex);
|
||||||
|
|
||||||
|
if(!io_service) {
|
||||||
|
io_service = std::make_shared<asio::io_service>();
|
||||||
|
}
|
||||||
|
|
||||||
for(auto it = connections.begin(); it != connections.end(); ++it) {
|
for(auto it = connections.begin(); it != connections.end(); ++it) {
|
||||||
if(!(*it)->in_use) {
|
if(!(*it)->in_use) {
|
||||||
|
|
|
||||||
|
|
@ -389,12 +389,16 @@ int main() {
|
||||||
|
|
||||||
// Test large responses
|
// Test large responses
|
||||||
{
|
{
|
||||||
HttpClient client("localhost:8080");
|
// Don't mix synchronous and asynchronous on the same client
|
||||||
client.config.max_response_streambuf_size = 400;
|
HttpClient sync_request_client("localhost:8080");
|
||||||
|
HttpClient async_request_client("localhost:8080");
|
||||||
|
sync_request_client.config.max_response_streambuf_size = 400;
|
||||||
|
async_request_client.config.max_response_streambuf_size = 400;
|
||||||
|
async_request_client.io_service = std::make_shared<SimpleWeb::io_context>();
|
||||||
{
|
{
|
||||||
bool thrown = false;
|
bool thrown = false;
|
||||||
try {
|
try {
|
||||||
auto r = client.request("GET", "/long-response");
|
auto r = sync_request_client.request("GET", "/long-response");
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
thrown = true;
|
thrown = true;
|
||||||
|
|
@ -405,7 +409,7 @@ int main() {
|
||||||
size_t calls = 0;
|
size_t calls = 0;
|
||||||
bool end = false;
|
bool end = false;
|
||||||
std::string content;
|
std::string content;
|
||||||
client.request("GET", "/long-response", [&calls, &content, &end](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
|
async_request_client.request("GET", "/long-response", [&calls, &content, &end](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
|
||||||
ASSERT(!ec);
|
ASSERT(!ec);
|
||||||
content += response->content.string();
|
content += response->content.string();
|
||||||
calls++;
|
calls++;
|
||||||
|
|
@ -413,8 +417,8 @@ int main() {
|
||||||
ASSERT(response->content.end == false);
|
ASSERT(response->content.end == false);
|
||||||
end = response->content.end;
|
end = response->content.end;
|
||||||
});
|
});
|
||||||
SimpleWeb::restart(*client.io_service);
|
SimpleWeb::restart(*async_request_client.io_service);
|
||||||
client.io_service->run();
|
async_request_client.io_service->run();
|
||||||
ASSERT(content == long_response);
|
ASSERT(content == long_response);
|
||||||
ASSERT(calls > 2);
|
ASSERT(calls > 2);
|
||||||
ASSERT(end == true);
|
ASSERT(end == true);
|
||||||
|
|
@ -422,15 +426,15 @@ int main() {
|
||||||
{
|
{
|
||||||
size_t calls = 0;
|
size_t calls = 0;
|
||||||
std::string content;
|
std::string content;
|
||||||
client.request("GET", "/long-response", [&calls, &content](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
|
async_request_client.request("GET", "/long-response", [&calls, &content](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
|
||||||
if(calls == 0)
|
if(calls == 0)
|
||||||
ASSERT(!ec);
|
ASSERT(!ec);
|
||||||
content += response->content.string();
|
content += response->content.string();
|
||||||
calls++;
|
calls++;
|
||||||
response->close();
|
response->close();
|
||||||
});
|
});
|
||||||
SimpleWeb::restart(*client.io_service);
|
SimpleWeb::restart(*async_request_client.io_service);
|
||||||
client.io_service->run();
|
async_request_client.io_service->run();
|
||||||
ASSERT(!content.empty());
|
ASSERT(!content.empty());
|
||||||
ASSERT(calls >= 2);
|
ASSERT(calls >= 2);
|
||||||
}
|
}
|
||||||
|
|
@ -438,12 +442,15 @@ int main() {
|
||||||
|
|
||||||
// Test client timeout
|
// Test client timeout
|
||||||
{
|
{
|
||||||
HttpClient client("localhost:8080");
|
// Don't mix synchronous and asynchronous on the same client
|
||||||
client.config.timeout = 2;
|
HttpClient sync_request_client("localhost:8080");
|
||||||
|
HttpClient async_request_client("localhost:8080");
|
||||||
|
sync_request_client.config.timeout = 2;
|
||||||
|
async_request_client.config.timeout = 2;
|
||||||
{
|
{
|
||||||
bool thrown = false;
|
bool thrown = false;
|
||||||
try {
|
try {
|
||||||
auto r = client.request("GET", "/work");
|
auto r = sync_request_client.request("GET", "/work");
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
thrown = true;
|
thrown = true;
|
||||||
|
|
@ -452,12 +459,12 @@ int main() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
bool call = false;
|
bool call = false;
|
||||||
client.request("GET", "/work", [&call](shared_ptr<HttpClient::Response> /*response*/, const SimpleWeb::error_code &ec) {
|
async_request_client.request("GET", "/work", [&call](shared_ptr<HttpClient::Response> /*response*/, const SimpleWeb::error_code &ec) {
|
||||||
ASSERT(ec);
|
ASSERT(ec);
|
||||||
call = true;
|
call = true;
|
||||||
});
|
});
|
||||||
SimpleWeb::restart(*client.io_service);
|
SimpleWeb::restart(*async_request_client.io_service);
|
||||||
client.io_service->run();
|
async_request_client.io_service->run();
|
||||||
ASSERT(call);
|
ASSERT(call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue