mirror of https://github.com/axmolengine/axmol.git
Add clear request and responses method to httpclient (#19598)
* Added functionality to clear pending responses and requests in the http client * Responses and Requests now are processed in similar way * Fix for clearing the http requests * Added tests for HttpClient::clearResponseAndRequestQueue
This commit is contained in:
parent
c3a0205652
commit
62d20a9825
|
@ -885,6 +885,8 @@ HttpClient::HttpClient()
|
|||
, _threadCount(0)
|
||||
, _cookie(nullptr)
|
||||
, _requestSentinel(new HttpRequest())
|
||||
, _clearRequestPredicate(nullptr)
|
||||
, _clearResponsePredicate(nullptr)
|
||||
{
|
||||
CCLOG("In the constructor of HttpClient!");
|
||||
increaseThreadCount();
|
||||
|
@ -991,6 +993,39 @@ void HttpClient::dispatchResponseCallbacks()
|
|||
}
|
||||
}
|
||||
|
||||
void HttpClient::clearResponseAndRequestQueue()
|
||||
{
|
||||
_requestQueueMutex.lock();
|
||||
if (_requestQueue.size())
|
||||
{
|
||||
for (auto it = _requestQueue.begin(); it != _requestQueue.end();)
|
||||
{
|
||||
if(!_clearRequestPredicate ||
|
||||
_clearRequestPredicate((*it)))
|
||||
{
|
||||
(*it)->release();
|
||||
it =_requestQueue.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_requestQueueMutex.unlock();
|
||||
|
||||
_responseQueueMutex.lock();
|
||||
if (_clearResponsePredicate)
|
||||
{
|
||||
_responseQueue.erase(std::remove_if(_responseQueue.begin(), _responseQueue.end(), _clearResponsePredicate), _responseQueue.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
_responseQueue.clear();
|
||||
}
|
||||
_responseQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void HttpClient::increaseThreadCount()
|
||||
{
|
||||
_threadCountMutex.lock();
|
||||
|
|
|
@ -371,6 +371,8 @@ HttpClient::HttpClient()
|
|||
, _threadCount(0)
|
||||
, _cookie(nullptr)
|
||||
, _requestSentinel(new HttpRequest())
|
||||
, _clearRequestPredicate(nullptr)
|
||||
, _clearResponsePredicate(nullptr)
|
||||
{
|
||||
CCLOG("In the constructor of HttpClient!");
|
||||
memset(_responseMessage, 0, sizeof(char) * RESPONSE_BUFFER_SIZE);
|
||||
|
@ -534,7 +536,39 @@ void HttpClient::processResponse(HttpResponse* response, char* responseMessage)
|
|||
response->setErrorBuffer(responseMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HttpClient::clearResponseAndRequestQueue()
|
||||
{
|
||||
_requestQueueMutex.lock();
|
||||
if (_requestQueue.size())
|
||||
{
|
||||
for (auto it = _requestQueue.begin(); it != _requestQueue.end();)
|
||||
{
|
||||
if(!_clearRequestPredicate ||
|
||||
_clearRequestPredicate((*it)))
|
||||
{
|
||||
(*it)->release();
|
||||
it =_requestQueue.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_requestQueueMutex.unlock();
|
||||
|
||||
_responseQueueMutex.lock();
|
||||
if (_clearResponsePredicate)
|
||||
{
|
||||
_responseQueue.erase(std::remove_if(_responseQueue.begin(), _responseQueue.end(), _clearResponsePredicate), _responseQueue.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
_responseQueue.clear();
|
||||
}
|
||||
_responseQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void HttpClient::increaseThreadCount()
|
||||
{
|
||||
|
|
|
@ -403,6 +403,8 @@ HttpClient::HttpClient()
|
|||
, _threadCount(0)
|
||||
, _cookie(nullptr)
|
||||
, _requestSentinel(new HttpRequest())
|
||||
, _clearRequestPredicate(nullptr)
|
||||
, _clearResponsePredicate(nullptr)
|
||||
{
|
||||
CCLOG("In the constructor of HttpClient!");
|
||||
memset(_responseMessage, 0, RESPONSE_BUFFER_SIZE * sizeof(char));
|
||||
|
@ -575,6 +577,39 @@ void HttpClient::processResponse(HttpResponse* response, char* responseMessage)
|
|||
response->setSucceed(true);
|
||||
}
|
||||
}
|
||||
|
||||
void HttpClient::clearResponseAndRequestQueue()
|
||||
{
|
||||
_requestQueueMutex.lock();
|
||||
if (_requestQueue.size())
|
||||
{
|
||||
for (auto it = _requestQueue.begin(); it != _requestQueue.end();)
|
||||
{
|
||||
if(!_clearRequestPredicate ||
|
||||
_clearRequestPredicate((*it)))
|
||||
{
|
||||
(*it)->release();
|
||||
it =_requestQueue.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_requestQueueMutex.unlock();
|
||||
|
||||
_responseQueueMutex.lock();
|
||||
if (_clearResponsePredicate)
|
||||
{
|
||||
_responseQueue.erase(std::remove_if(_responseQueue.begin(), _responseQueue.end(), _clearResponsePredicate), _responseQueue.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
_responseQueue.clear();
|
||||
}
|
||||
_responseQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void HttpClient::increaseThreadCount()
|
||||
{
|
||||
|
|
|
@ -150,6 +150,34 @@ public:
|
|||
std::mutex& getCookieFileMutex() {return _cookieFileMutex;}
|
||||
|
||||
std::mutex& getSSLCaFileMutex() {return _sslCaFileMutex;}
|
||||
|
||||
typedef std::function<bool(HttpRequest*)> ClearRequestPredicate;
|
||||
typedef std::function<bool(HttpResponse*)> ClearResponsePredicate;
|
||||
|
||||
/**
|
||||
* Clears the pending http responses and http requests
|
||||
* If defined, the method uses the ClearRequestPredicate and ClearResponsePredicate
|
||||
* to check for each request/response which to delete
|
||||
*/
|
||||
void clearResponseAndRequestQueue();
|
||||
|
||||
/**
|
||||
* Sets a predicate function that is going to be called to determine if we proceed
|
||||
* each of the pending requests
|
||||
*
|
||||
* @param predicate function that will be called
|
||||
*/
|
||||
void setClearRequestPredicate(ClearRequestPredicate predicate) { _clearRequestPredicate = predicate; }
|
||||
|
||||
/**
|
||||
Sets a predicate function that is going to be called to determine if we proceed
|
||||
* each of the pending requests
|
||||
*
|
||||
* @param cb predicate function that will be called
|
||||
*/
|
||||
void setClearResponsePredicate(ClearResponsePredicate predicate) { _clearResponsePredicate = predicate; }
|
||||
|
||||
|
||||
private:
|
||||
HttpClient();
|
||||
virtual ~HttpClient();
|
||||
|
@ -203,6 +231,9 @@ private:
|
|||
char _responseMessage[RESPONSE_BUFFER_SIZE];
|
||||
|
||||
HttpRequest* _requestSentinel;
|
||||
|
||||
ClearRequestPredicate _clearRequestPredicate;
|
||||
ClearResponsePredicate _clearResponsePredicate;
|
||||
};
|
||||
|
||||
} // namespace network
|
||||
|
|
|
@ -33,6 +33,7 @@ using namespace cocos2d::network;
|
|||
HttpClientTests::HttpClientTests()
|
||||
{
|
||||
ADD_TEST_CASE(HttpClientTest);
|
||||
ADD_TEST_CASE(HttpClientClearRequestsTest);
|
||||
}
|
||||
|
||||
HttpClientTest::HttpClientTest()
|
||||
|
@ -398,3 +399,149 @@ void HttpClientTest::onHttpRequestCompleted(HttpClient *sender, HttpResponse *re
|
|||
log("request ref count not 2, is %d", response->getHttpRequest()->getReferenceCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HttpClientClearRequestsTest::HttpClientClearRequestsTest()
|
||||
: _labelStatusCode(nullptr)
|
||||
{
|
||||
auto winSize = Director::getInstance()->getWinSize();
|
||||
|
||||
const int MARGIN = 40;
|
||||
const int SPACE = 35;
|
||||
|
||||
const int CENTER = winSize.width / 2;
|
||||
|
||||
auto menuRequest = Menu::create();
|
||||
menuRequest->setPosition(Vec2::ZERO);
|
||||
addChild(menuRequest);
|
||||
|
||||
// Get
|
||||
auto labelGet = Label::createWithTTF("Test Clear all Get", "fonts/arial.ttf", 22);
|
||||
auto itemGet = MenuItemLabel::create(labelGet, CC_CALLBACK_1(HttpClientClearRequestsTest::onMenuCancelAllClicked, this));
|
||||
itemGet->setPosition(CENTER, winSize.height - MARGIN - SPACE);
|
||||
menuRequest->addChild(itemGet);
|
||||
|
||||
// Post
|
||||
auto labelPost = Label::createWithTTF("Test Clear but only with the tag DELETE", "fonts/arial.ttf", 22);
|
||||
auto itemPost = MenuItemLabel::create(labelPost, CC_CALLBACK_1(HttpClientClearRequestsTest::onMenuCancelSomeClicked, this));
|
||||
itemPost->setPosition(CENTER, winSize.height - MARGIN - 2 * SPACE);
|
||||
menuRequest->addChild(itemPost);
|
||||
|
||||
// Response Code Label
|
||||
_labelStatusCode = Label::createWithTTF("HTTP Status Code", "fonts/arial.ttf", 18);
|
||||
_labelStatusCode->setPosition(winSize.width / 2, winSize.height - MARGIN - 6 * SPACE);
|
||||
addChild(_labelStatusCode);
|
||||
|
||||
// Tracking Data Label
|
||||
_labelTrakingData = Label::createWithTTF("Got 0 of 0 expected http requests", "fonts/arial.ttf", 16);
|
||||
_labelTrakingData->setPosition(CENTER, winSize.height - MARGIN - 5 * SPACE);
|
||||
addChild(_labelTrakingData);
|
||||
|
||||
_totalExpectedRequests = 0;
|
||||
_totalProcessedRequests = 0;
|
||||
}
|
||||
|
||||
HttpClientClearRequestsTest::~HttpClientClearRequestsTest()
|
||||
{
|
||||
HttpClient::destroyInstance();
|
||||
}
|
||||
|
||||
void HttpClientClearRequestsTest::onMenuCancelAllClicked(cocos2d::Ref *sender)
|
||||
{
|
||||
for (int i=0; i < 10; i++)
|
||||
{
|
||||
HttpRequest* request = new (std::nothrow) HttpRequest();
|
||||
std::stringstream url;
|
||||
url << "http://cocos2d-x.org/images/logo.png?id=" << std::to_string(i);
|
||||
request->setUrl(url.str());
|
||||
request->setRequestType(HttpRequest::Type::GET);
|
||||
request->setResponseCallback(CC_CALLBACK_2(HttpClientClearRequestsTest::onHttpRequestCompleted, this));
|
||||
|
||||
url.str("");
|
||||
url << "TEST_" << std::to_string(i);
|
||||
request->setTag(url.str());
|
||||
HttpClient::getInstance()->send(request);
|
||||
request->release();
|
||||
}
|
||||
|
||||
_totalProcessedRequests = 0;
|
||||
_totalExpectedRequests = 1;
|
||||
|
||||
HttpClient::getInstance()->setClearRequestPredicate(nullptr);
|
||||
HttpClient::getInstance()->setClearResponsePredicate(nullptr);
|
||||
HttpClient::getInstance()->clearResponseAndRequestQueue();
|
||||
|
||||
// waiting
|
||||
_labelStatusCode->setString("waiting...");
|
||||
}
|
||||
|
||||
void HttpClientClearRequestsTest::onMenuCancelSomeClicked(cocos2d::Ref *sender)
|
||||
{
|
||||
// test 1
|
||||
for (int i=0; i < 10; i++)
|
||||
{
|
||||
HttpRequest* request = new (std::nothrow) HttpRequest();
|
||||
std::stringstream url;
|
||||
url << "http://cocos2d-x.org/images/logo.png?id=" << std::to_string(i);
|
||||
request->setUrl(url.str());
|
||||
request->setRequestType(HttpRequest::Type::GET);
|
||||
request->setResponseCallback(CC_CALLBACK_2(HttpClientClearRequestsTest::onHttpRequestCompleted, this));
|
||||
|
||||
url.str("");
|
||||
if (i < 5) {
|
||||
url << "TEST_" << std::to_string(i);
|
||||
_totalExpectedRequests++;
|
||||
}
|
||||
else {
|
||||
url << "DELETE_" << std::to_string(i);
|
||||
}
|
||||
request->setTag(url.str());
|
||||
HttpClient::getInstance()->send(request);
|
||||
request->release();
|
||||
}
|
||||
|
||||
HttpClient::getInstance()->setClearRequestPredicate([&](HttpRequest* req)
|
||||
{
|
||||
auto r = !!strstr(req->getTag(), "DELETE_");
|
||||
return r;
|
||||
});
|
||||
HttpClient::getInstance()->setClearResponsePredicate(nullptr);
|
||||
HttpClient::getInstance()->clearResponseAndRequestQueue();
|
||||
|
||||
|
||||
// waiting
|
||||
_labelStatusCode->setString("waiting...");
|
||||
|
||||
}
|
||||
|
||||
void HttpClientClearRequestsTest::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
|
||||
{
|
||||
if (!response)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// You can get original request type from: response->request->reqType
|
||||
if (0 != strlen(response->getHttpRequest()->getTag()))
|
||||
{
|
||||
log("%s completed", response->getHttpRequest()->getTag());
|
||||
}
|
||||
|
||||
long statusCode = response->getResponseCode();
|
||||
char statusString[64] = {};
|
||||
sprintf(statusString, "HTTP Status Code: %ld, tag = %s", statusCode, response->getHttpRequest()->getTag());
|
||||
_labelStatusCode->setString(statusString);
|
||||
log("response code: %ld", statusCode);
|
||||
|
||||
_totalProcessedRequests++;
|
||||
sprintf(statusString, "Got %d of %d expected http requests", _totalProcessedRequests, _totalExpectedRequests);
|
||||
_labelTrakingData->setString(statusString);
|
||||
|
||||
if (!response->isSucceed())
|
||||
{
|
||||
log("response failed");
|
||||
log("error buffer: %s", response->getErrorBuffer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,4 +56,28 @@ private:
|
|||
cocos2d::Label* _labelStatusCode;
|
||||
};
|
||||
|
||||
class HttpClientClearRequestsTest : public TestCase
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(HttpClientClearRequestsTest);
|
||||
|
||||
HttpClientClearRequestsTest();
|
||||
virtual ~HttpClientClearRequestsTest();
|
||||
|
||||
//Menu Callbacks
|
||||
void onMenuCancelAllClicked(cocos2d::Ref *sender);
|
||||
void onMenuCancelSomeClicked(cocos2d::Ref *sender);
|
||||
|
||||
//Http Response Callback
|
||||
void onHttpRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response);
|
||||
|
||||
virtual std::string title() const override { return "Http Request Test"; }
|
||||
|
||||
private:
|
||||
int _totalExpectedRequests;
|
||||
int _totalProcessedRequests;
|
||||
cocos2d::Label* _labelTrakingData;
|
||||
cocos2d::Label* _labelStatusCode;
|
||||
};
|
||||
|
||||
#endif //__HTTPREQUESTHTTP_H
|
||||
|
|
Loading…
Reference in New Issue