NetServices: Implement BHttpSession::Cancel()
Change-Id: Iff0a7726e57f3e6bd4e9d0ebac08a370d25a62d7
This commit is contained in:
parent
2f3b9b18ac
commit
6cbbd9bf4e
@ -183,6 +183,42 @@ namespace Network {
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BHttpSession::Cancel(int32 identifier)
|
||||
\brief Cancel a running request.
|
||||
|
||||
When a request that is scheduled or running is cancelled, its \ref BHttpResult object will
|
||||
be set to the \ref BNetworkRequestError exception with the \c Cancelled type.
|
||||
|
||||
There are three possible outcomes:
|
||||
1. If the request is not yet scheduled, then it will never start. The result will be set to
|
||||
the cancelled error state.
|
||||
2. If the request was started, then processing it will be terminated. The result will be set to
|
||||
the cancelled error state.
|
||||
3. If the request was already finished, then nothing happens. The result will keep the value it
|
||||
had assigned. The same if the request identifier is invalid.
|
||||
|
||||
\param identifier The identifier for the request to cancel.
|
||||
|
||||
\exception std::bad_alloc Error in case memory cannot be allocated.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BHttpSession::Cancel(const BHttpResult& request)
|
||||
\brief Cancel a running \a request.
|
||||
|
||||
See the \ref BHttpSession::Cancel(int32 identifier) method for more details on how this method
|
||||
works.
|
||||
|
||||
\exception std::bad_alloc Error in case memory cannot be allocated.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
} // namespace Network
|
||||
|
||||
} // namespace BPrivate
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
BHttpResult Execute(BHttpRequest&& request,
|
||||
std::unique_ptr<BDataIO> target = nullptr,
|
||||
BMessenger observer = BMessenger());
|
||||
void Cancel(int32 identifier);
|
||||
void Cancel(const BHttpResult& request);
|
||||
|
||||
private:
|
||||
struct Redirect;
|
||||
|
@ -151,6 +151,7 @@ public:
|
||||
BHttpResult Execute(BHttpRequest&& request,
|
||||
std::unique_ptr<BDataIO> target,
|
||||
BMessenger observer);
|
||||
void Cancel(int32 identifier);
|
||||
|
||||
private:
|
||||
// Thread functions
|
||||
@ -239,6 +240,30 @@ BHttpSession::Impl::Execute(BHttpRequest&& request, std::unique_ptr<BDataIO> tar
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
void
|
||||
BHttpSession::Impl::Cancel(int32 identifier)
|
||||
{
|
||||
std::cout << "BHttpSession::Impl::Cancel for " << identifier << std::endl;
|
||||
auto lock = AutoLocker<BLocker>(fLock);
|
||||
// Check if the item is on the control queue
|
||||
auto item = std::find_if(fControlQueue.begin(), fControlQueue.end(),
|
||||
[&identifier](const auto& arg){ return arg.Id() == identifier; });
|
||||
if (item != fControlQueue.end()) {
|
||||
try {
|
||||
throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::Canceled);
|
||||
} catch (...) {
|
||||
item->SetError(std::current_exception());
|
||||
}
|
||||
fControlQueue.erase(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get it on the list for deletion in the data queue
|
||||
fCancelList.push_back(identifier);
|
||||
release_sem(fDataQueueSem);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
BHttpSession::Impl::ControlThreadFunc(void* arg)
|
||||
{
|
||||
@ -389,6 +414,7 @@ BHttpSession::Impl::DataThreadFunc(void* arg)
|
||||
for (auto it = data->connectionMap.cbegin(); it != data->connectionMap.cend(); it++) {
|
||||
offset++;
|
||||
if (it->second.Id() == id) {
|
||||
std::cout << "DataThreadFunc() [" << id << "] cancelling request" << std::endl;
|
||||
data->objectList[offset].events = EVENT_CANCELLED;
|
||||
break;
|
||||
}
|
||||
@ -585,6 +611,20 @@ BHttpSession::Execute(BHttpRequest&& request, std::unique_ptr<BDataIO> target, B
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BHttpSession::Cancel(int32 identifier)
|
||||
{
|
||||
fImpl->Cancel(identifier);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BHttpSession::Cancel(const BHttpResult& request)
|
||||
{
|
||||
fImpl->Cancel(request.Identity());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -- BHttpSession::Request (helpers)
|
||||
|
||||
BHttpSession::Request::Request(BHttpRequest&& request, std::unique_ptr<BDataIO> target,
|
||||
|
@ -496,6 +496,7 @@ HttpIntegrationTest::AddTests(BTestSuite& parent)
|
||||
testCaller->addThread("AutoRedirectTest", &HttpIntegrationTest::AutoRedirectTest);
|
||||
testCaller->addThread("BasicAuthTest", &HttpIntegrationTest::BasicAuthTest);
|
||||
testCaller->addThread("StopOnErrorTest", &HttpIntegrationTest::StopOnErrorTest);
|
||||
testCaller->addThread("RequestCancelTest", &HttpIntegrationTest::RequestCancelTest);
|
||||
|
||||
suite.addTest(testCaller);
|
||||
parent.addTest("HttpIntegrationTest", &suite);
|
||||
@ -518,6 +519,7 @@ HttpIntegrationTest::AddTests(BTestSuite& parent)
|
||||
testCaller->addThread("AutoRedirectTest", &HttpIntegrationTest::AutoRedirectTest);
|
||||
testCaller->addThread("BasicAuthTest", &HttpIntegrationTest::BasicAuthTest);
|
||||
testCaller->addThread("StopOnErrorTest", &HttpIntegrationTest::StopOnErrorTest);
|
||||
testCaller->addThread("RequestCancelTest", &HttpIntegrationTest::RequestCancelTest);
|
||||
|
||||
suite.addTest(testCaller);
|
||||
parent.addTest("HttpsIntegrationTest", &suite);
|
||||
@ -714,3 +716,22 @@ HttpIntegrationTest::StopOnErrorTest()
|
||||
CPPUNIT_ASSERT(result.Fields().CountFields() == 0);
|
||||
CPPUNIT_ASSERT(result.Body().text.Length() == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpIntegrationTest::RequestCancelTest()
|
||||
{
|
||||
// Test the cancellation functionality
|
||||
// TODO: this test potentially fails if the case is executed before the cancellation is
|
||||
// processed. In practise, the cancellation always comes first. When the server
|
||||
// supports a wait parameter, then this test can be made more robust.
|
||||
auto request = BHttpRequest(BUrl(fTestServer.BaseUrl(), "/"));
|
||||
auto result = fSession.Execute(std::move(request));
|
||||
fSession.Cancel(result);
|
||||
try {
|
||||
result.Body();
|
||||
CPPUNIT_FAIL("Expected exception because request was cancelled");
|
||||
} catch (const BNetworkRequestError& e) {
|
||||
CPPUNIT_ASSERT(e.Type() == BNetworkRequestError::Canceled);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
void AutoRedirectTest();
|
||||
void BasicAuthTest();
|
||||
void StopOnErrorTest();
|
||||
void RequestCancelTest();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user