HttpClient: Fix crash when process redirect

This commit is contained in:
halx99 2021-07-06 02:44:57 +08:00
parent af0a0f1598
commit f4969ee388
3 changed files with 51 additions and 77 deletions

View File

@ -42,37 +42,29 @@ namespace network {
static HttpClient* _httpClient = nullptr; // pointer to singleton static HttpClient* _httpClient = nullptr; // pointer to singleton
template<typename _Cont, typename _Fty> template <typename _Cont, typename _Fty>
static void __clearQueueUnsafe(_Cont& queue, _Fty pred) { static void __clearQueueUnsafe(_Cont& queue, _Fty pred) {
for (auto it = queue.unsafe_begin(); it != queue.unsafe_end();) for (auto it = queue.unsafe_begin(); it != queue.unsafe_end();) {
{ if (!pred || pred((*it))) {
if (!pred || pred((*it)))
{
(*it)->release(); (*it)->release();
it = queue.unsafe_erase(it); it = queue.unsafe_erase(it);
} } else {
else
{
++it; ++it;
} }
} }
} }
// HttpClient implementation // HttpClient implementation
HttpClient* HttpClient::getInstance() HttpClient* HttpClient::getInstance() {
{ if (_httpClient == nullptr) {
if (_httpClient == nullptr)
{
_httpClient = new (std::nothrow) HttpClient(); _httpClient = new (std::nothrow) HttpClient();
} }
return _httpClient; return _httpClient;
} }
void HttpClient::destroyInstance() void HttpClient::destroyInstance() {
{ if (nullptr == _httpClient) {
if (nullptr == _httpClient)
{
CCLOG("HttpClient singleton is nullptr"); CCLOG("HttpClient singleton is nullptr");
return; return;
} }
@ -84,34 +76,24 @@ void HttpClient::destroyInstance()
CCLOG("HttpClient::destroyInstance() finished!"); CCLOG("HttpClient::destroyInstance() finished!");
} }
void HttpClient::enableCookies(const char* cookieFile) void HttpClient::enableCookies(const char* cookieFile) {
{
std::lock_guard<std::recursive_mutex> lock(_cookieFileMutex); std::lock_guard<std::recursive_mutex> lock(_cookieFileMutex);
if (cookieFile) if (cookieFile) {
{
_cookieFilename = std::string(cookieFile); _cookieFilename = std::string(cookieFile);
} } else {
else
{
_cookieFilename = (FileUtils::getInstance()->getNativeWritableAbsolutePath() + "cookieFile.txt"); _cookieFilename = (FileUtils::getInstance()->getNativeWritableAbsolutePath() + "cookieFile.txt");
} }
} }
void HttpClient::setSSLVerification(const std::string& caFile) void HttpClient::setSSLVerification(const std::string& caFile) {
{
std::lock_guard<std::recursive_mutex> lock(_sslCaFileMutex); std::lock_guard<std::recursive_mutex> lock(_sslCaFileMutex);
_sslCaFilename = caFile; _sslCaFilename = caFile;
_service->set_option(yasio::YOPT_S_SSL_CACERT, _sslCaFilename.c_str()); _service->set_option(yasio::YOPT_S_SSL_CACERT, _sslCaFilename.c_str());
} }
HttpClient::HttpClient() HttpClient::HttpClient()
: _isInited(false) : _isInited(false), _dispatchOnWorkThread(false), _timeoutForConnect(30), _timeoutForRead(60), _cookie(nullptr),
, _dispatchOnWorkThread(false) _clearResponsePredicate(nullptr) {
, _timeoutForConnect(30)
, _timeoutForRead(60)
, _cookie(nullptr)
, _clearResponsePredicate(nullptr)
{
CCLOG("In the constructor of HttpClient!"); CCLOG("In the constructor of HttpClient!");
_scheduler = Director::getInstance()->getScheduler(); _scheduler = Director::getInstance()->getScheduler();
@ -126,14 +108,12 @@ HttpClient::HttpClient()
_isInited = true; _isInited = true;
} }
HttpClient::~HttpClient() HttpClient::~HttpClient() {
{
delete _service; delete _service;
CCLOG("HttpClient destructor"); CCLOG("HttpClient destructor");
} }
bool HttpClient::send(HttpRequest* request) bool HttpClient::send(HttpRequest* request) {
{
if (!request) if (!request)
return false; return false;
@ -159,10 +139,12 @@ void HttpClient::processResponse(HttpResponse* response, const std::string& url)
if (channelIndex != -1) { if (channelIndex != -1) {
if (response->prepareForProcess(url)) { if (response->prepareForProcess(url)) {
response->_responseHeaders.clear(); // redirect needs clear old response headers
auto& requestUri = response->getRequestUri(); auto& requestUri = response->getRequestUri();
auto channelHandle = _service->channel_at(channelIndex); auto channelHandle = _service->channel_at(channelIndex);
channelHandle->ud_.ptr = response; channelHandle->ud_.ptr = response;
_service->set_option(YOPT_C_REMOTE_ENDPOINT, channelIndex, requestUri.getHost().c_str(), (int) requestUri.getPort()); _service->set_option(
YOPT_C_REMOTE_ENDPOINT, channelIndex, requestUri.getHost().c_str(), (int) requestUri.getPort());
if (requestUri.isSecure()) if (requestUri.isSecure())
_service->open(channelIndex, YCK_SSL_CLIENT); _service->open(channelIndex, YCK_SSL_CLIENT);
else else
@ -239,7 +221,7 @@ void HttpClient::handleNetworkEvent(yasio::io_event* event) {
bool userAgentSpecified = false; bool userAgentSpecified = false;
bool contentTypeSpecified = false; bool contentTypeSpecified = false;
if(!headers.empty()) { if (!headers.empty()) {
using namespace cxx17; // for string_view literal using namespace cxx17; // for string_view literal
for (auto& header : headers) { for (auto& header : headers) {
obs.write_bytes(header); obs.write_bytes(header);
@ -358,44 +340,37 @@ void HttpClient::clearResponseQueue() {
__clearQueueUnsafe(_responseQueue, ClearResponsePredicate{}); __clearQueueUnsafe(_responseQueue, ClearResponsePredicate{});
} }
void HttpClient::setTimeoutForConnect(int value) void HttpClient::setTimeoutForConnect(int value) {
{
std::lock_guard<std::recursive_mutex> lock(_timeoutForConnectMutex); std::lock_guard<std::recursive_mutex> lock(_timeoutForConnectMutex);
_timeoutForConnect = value; _timeoutForConnect = value;
_service->set_option(YOPT_S_CONNECT_TIMEOUT, value); _service->set_option(YOPT_S_CONNECT_TIMEOUT, value);
} }
int HttpClient::getTimeoutForConnect() int HttpClient::getTimeoutForConnect() {
{
std::lock_guard<std::recursive_mutex> lock(_timeoutForConnectMutex); std::lock_guard<std::recursive_mutex> lock(_timeoutForConnectMutex);
return _timeoutForConnect; return _timeoutForConnect;
} }
void HttpClient::setTimeoutForRead(int value) void HttpClient::setTimeoutForRead(int value) {
{
std::lock_guard<std::recursive_mutex> lock(_timeoutForReadMutex); std::lock_guard<std::recursive_mutex> lock(_timeoutForReadMutex);
_timeoutForRead = value; _timeoutForRead = value;
} }
int HttpClient::getTimeoutForRead() int HttpClient::getTimeoutForRead() {
{
std::lock_guard<std::recursive_mutex> lock(_timeoutForReadMutex); std::lock_guard<std::recursive_mutex> lock(_timeoutForReadMutex);
return _timeoutForRead; return _timeoutForRead;
} }
const std::string& HttpClient::getCookieFilename() const std::string& HttpClient::getCookieFilename() {
{
std::lock_guard<std::recursive_mutex> lock(_cookieFileMutex); std::lock_guard<std::recursive_mutex> lock(_cookieFileMutex);
return _cookieFilename; return _cookieFilename;
} }
const std::string& HttpClient::getSSLVerification() const std::string& HttpClient::getSSLVerification() {
{
std::lock_guard<std::recursive_mutex> lock(_sslCaFileMutex); std::lock_guard<std::recursive_mutex> lock(_sslCaFileMutex);
return _sslCaFilename; return _sslCaFilename;
} }
} } // namespace network
NS_CC_END NS_CC_END

View File

@ -107,7 +107,7 @@ public:
const std::string& getSSLVerification(); const std::string& getSSLVerification();
/** /**
* Add a get request to task queue * Send http request concurrently, non-blocking
* *
* @param request a HttpRequest object, which includes url, response callback etc. * @param request a HttpRequest object, which includes url, response callback etc.
please make sure request->_requestData is clear before calling "send" here. please make sure request->_requestData is clear before calling "send" here.

View File

@ -173,7 +173,6 @@ private:
_finished = false; _finished = false;
_responseData.clear(); _responseData.clear();
_currentHeader.clear(); _currentHeader.clear();
_responseHeaders.clear();
_responseCode = -1; _responseCode = -1;
_internalCode = 0; _internalCode = 0;