Created
March 11, 2014 11:06
-
-
Save kuhar/9483699 to your computer and use it in GitHub Desktop.
cocos2d-x 2.x HttpClient - checking file size before downloading
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KL_HTTP_CLIENT_H | |
#define KL_HTTP_CLIENT_H | |
#include "cocos2d.h" | |
#include "cocos-ext.h" | |
#include "ExtensionMacros.h" | |
USING_NS_CC; | |
USING_NS_CC_EXT; | |
#include "downloader/HttpRequest.h" | |
#include "downloader/HttpResponse.h" | |
namespace KoalaLib | |
{ | |
/** @brief Singleton that handles asynchrounous http requests | |
* Once the request completed, a callback will issued in main thread when it provided during make request | |
*/ | |
class HttpClient : public CCObject | |
{ | |
public: | |
static HttpClient* getInstance(); | |
static void destroyInstance(); | |
void send ( HttpRequest* request ); | |
inline void setTimeoutForConnect ( int value ) | |
{ | |
_timeoutForConnect = value; | |
}; | |
inline int getTimeoutForConnect() | |
{ | |
return _timeoutForConnect; | |
} | |
inline void setTimeoutForRead ( int value ) | |
{ | |
_timeoutForRead = value; | |
}; | |
inline int getTimeoutForRead() | |
{ | |
return _timeoutForRead; | |
}; | |
private: | |
HttpClient(); | |
virtual ~HttpClient(); | |
bool init ( void ); | |
bool lazyInitThreadSemphore(); | |
/** Poll function called from main thread to dispatch callbacks when http requests finished **/ | |
void dispatchResponseCallbacks ( float delta ); | |
int _timeoutForConnect; | |
int _timeoutForRead; | |
}; | |
} /* namespace KoalaLib */ | |
#endif //KL_HTTP_CLIENT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "downloader/HttpClient.h" | |
#if ( CC_TARGET_PLATFORM != CC_PLATFORM_WP8 ) | |
#include <queue> | |
#include <pthread.h> | |
#include <errno.h> | |
#include "curl/curl.h" | |
namespace KoalaLib | |
{ | |
static pthread_t s_networkThread; | |
static pthread_mutex_t s_requestQueueMutex; | |
static pthread_mutex_t s_responseQueueMutex; | |
static pthread_mutex_t s_SleepMutex; | |
static pthread_cond_t s_SleepCondition; | |
static unsigned long s_asyncRequestCount = 0; | |
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) | |
typedef int int32_t; | |
#endif | |
static bool need_quit = false; | |
static CCArray* s_requestQueue = NULL; | |
static CCArray* s_responseQueue = NULL; | |
static HttpClient* s_pHttpClient = NULL; // pointer to singleton | |
static char s_errorBuffer[CURL_ERROR_SIZE]; | |
typedef size_t ( *write_callback ) ( void* ptr, size_t size, size_t nmemb, | |
void* stream ); | |
// Callback function used by libcurl for collect response data | |
static size_t writeData ( void* ptr, size_t size, size_t nmemb, void* stream ) | |
{ | |
std::vector<char>* recvBuffer = ( std::vector<char>* ) stream; | |
size_t sizes = size * nmemb; | |
// add data to the end of recvBuffer | |
// write data maybe called more than once in a single request | |
recvBuffer->insert ( recvBuffer->end(), ( char* ) ptr, ( char* ) ptr + sizes ); | |
return sizes; | |
} | |
// Callback function used by libcurl for collect header data | |
static size_t writeHeaderData ( void* ptr, size_t size, size_t nmemb, | |
void* stream ) | |
{ | |
std::vector<char>* recvBuffer = ( std::vector<char>* ) stream; | |
size_t sizes = size * nmemb; | |
// add data to the end of recvBuffer | |
// write data maybe called more than once in a single request | |
recvBuffer->insert ( recvBuffer->end(), ( char* ) ptr, ( char* ) ptr + sizes ); | |
return sizes; | |
} | |
static int processGetTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* errorCode, write_callback headerCallback, | |
void* headerStream ); | |
static int processSizeTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* errorCode, write_callback headerCallback, | |
void* headerStream ); | |
static int processPostTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* errorCode, write_callback headerCallback, | |
void* headerStream ); | |
static int processPutTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* errorCode, write_callback headerCallback, | |
void* headerStream ); | |
static int processDeleteTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* errorCode, write_callback headerCallback, | |
void* headerStream ); | |
// int processDownloadTask(HttpRequest *task, write_callback callback, void *stream, int32_t *errorCode); | |
// Worker thread | |
static void* networkThread ( void* data ) | |
{ | |
HttpRequest* request = NULL; | |
while ( true ) | |
{ | |
if ( need_quit ) | |
{ | |
break; | |
} | |
// step 1: send http request if the requestQueue isn't empty | |
request = NULL; | |
pthread_mutex_lock ( &s_requestQueueMutex ); //Get request task from queue | |
if ( 0 != s_requestQueue->count() ) | |
{ | |
request = dynamic_cast<HttpRequest*> ( s_requestQueue->objectAtIndex ( 0 ) ); | |
s_requestQueue->removeObjectAtIndex ( 0 ); | |
// request's refcount = 1 here | |
} | |
pthread_mutex_unlock ( &s_requestQueueMutex ); | |
if ( NULL == request ) | |
{ | |
// Wait for http request tasks from main thread | |
pthread_cond_wait ( &s_SleepCondition, &s_SleepMutex ); | |
continue; | |
} | |
// step 2: libcurl sync access | |
// Create a HttpResponse object, the default setting is http access failed | |
HttpResponse* response = new HttpResponse ( request ); | |
// request's refcount = 2 here, it's retained by HttpRespose constructor | |
request->release(); | |
// ok, refcount = 1 now, only HttpResponse hold it. | |
int32_t responseCode = -1; | |
int retValue = 0; | |
// Process the request -> get response packet | |
switch ( request->getRequestType() ) | |
{ | |
case HttpRequest::kHttpGet: // HTTP GET | |
retValue = processGetTask ( request, | |
writeData, | |
response->getResponseData(), | |
&responseCode, | |
writeHeaderData, | |
response->getResponseHeader() ); | |
break; | |
case HttpRequest::kHttpSize: // HTTP GET REMOTE FILE SIZE | |
retValue = processSizeTask ( request, | |
writeData, | |
response->getResponseData(), | |
&responseCode, | |
writeHeaderData, | |
response->getResponseHeader() ); | |
break; | |
case HttpRequest::kHttpPost: // HTTP POST | |
retValue = processPostTask ( request, | |
writeData, | |
response->getResponseData(), | |
&responseCode, | |
writeHeaderData, | |
response->getResponseHeader() ); | |
break; | |
case HttpRequest::kHttpPut: | |
retValue = processPutTask ( request, | |
writeData, | |
response->getResponseData(), | |
&responseCode, | |
writeHeaderData, | |
response->getResponseHeader() ); | |
break; | |
case HttpRequest::kHttpDelete: | |
retValue = processDeleteTask ( request, | |
writeData, | |
response->getResponseData(), | |
&responseCode, | |
writeHeaderData, | |
response->getResponseHeader() ); | |
break; | |
default: | |
CCAssert ( true, | |
"HttpClient: unkown request type, only GET, POST and SIZE are supported" ); | |
break; | |
} | |
// write data to HttpResponse | |
response->setResponseCode ( responseCode ); | |
if ( retValue != 0 ) | |
{ | |
response->setSucceed ( false ); | |
response->setErrorBuffer ( s_errorBuffer ); | |
} | |
else | |
{ | |
response->setSucceed ( true ); | |
} | |
// add response packet into queue | |
pthread_mutex_lock ( &s_responseQueueMutex ); | |
s_responseQueue->addObject ( response ); | |
pthread_mutex_unlock ( &s_responseQueueMutex ); | |
// resume dispatcher selector | |
CCDirector::sharedDirector()->getScheduler()->resumeTarget ( | |
HttpClient::getInstance() ); | |
} | |
// cleanup: if worker thread received quit signal, clean up un-completed request queue | |
pthread_mutex_lock ( &s_requestQueueMutex ); | |
s_requestQueue->removeAllObjects(); | |
pthread_mutex_unlock ( &s_requestQueueMutex ); | |
s_asyncRequestCount -= s_requestQueue->count(); | |
if ( s_requestQueue != NULL ) | |
{ | |
pthread_mutex_destroy ( &s_requestQueueMutex ); | |
pthread_mutex_destroy ( &s_responseQueueMutex ); | |
pthread_mutex_destroy ( &s_SleepMutex ); | |
pthread_cond_destroy ( &s_SleepCondition ); | |
s_requestQueue->release(); | |
s_requestQueue = NULL; | |
s_responseQueue->release(); | |
s_responseQueue = NULL; | |
} | |
pthread_exit ( NULL ); | |
return 0; | |
} | |
//Configure curl's timeout property | |
static bool configureCURL ( CURL* handle ) | |
{ | |
if ( !handle ) | |
{ | |
return false; | |
} | |
int32_t code; | |
code = curl_easy_setopt ( handle, CURLOPT_ERRORBUFFER, s_errorBuffer ); | |
if ( code != CURLE_OK ) | |
{ | |
return false; | |
} | |
code = curl_easy_setopt ( handle, CURLOPT_TIMEOUT, | |
HttpClient::getInstance()->getTimeoutForRead() ); | |
if ( code != CURLE_OK ) | |
{ | |
return false; | |
} | |
code = curl_easy_setopt ( handle, CURLOPT_CONNECTTIMEOUT, | |
HttpClient::getInstance()->getTimeoutForConnect() ); | |
if ( code != CURLE_OK ) | |
{ | |
return false; | |
} | |
curl_easy_setopt ( handle, CURLOPT_SSL_VERIFYPEER, 0L ); | |
curl_easy_setopt ( handle, CURLOPT_SSL_VERIFYHOST, 0L ); | |
return true; | |
} | |
class CURLRaii | |
{ | |
/// Instance of CURL | |
CURL* m_curl; | |
/// Keeps custom header data | |
curl_slist* m_headers; | |
int m_downloadLength; | |
public: | |
CURLRaii() : | |
m_curl ( curl_easy_init() ), | |
m_headers ( NULL ), | |
m_downloadLength ( -1 ) | |
{ | |
} | |
~CURLRaii() | |
{ | |
if ( m_curl ) | |
{ | |
curl_easy_cleanup ( m_curl ); | |
} | |
/* free the linked list for header data */ | |
if ( m_headers ) | |
{ | |
curl_slist_free_all ( m_headers ); | |
} | |
} | |
template <class T> | |
bool setOption ( CURLoption option, T data ) | |
{ | |
return CURLE_OK == curl_easy_setopt ( m_curl, option, data ); | |
} | |
/** | |
* @brief Inits CURL instance for common usage | |
* @param request Null not allowed | |
* @param callback Response write callback | |
* @param stream Response write stream | |
*/ | |
bool init ( HttpRequest* request, write_callback callback, void* stream, | |
write_callback headerCallback, void* headerStream ) | |
{ | |
if ( !m_curl ) | |
{ | |
return false; | |
} | |
if ( !configureCURL ( m_curl ) ) | |
{ | |
return false; | |
} | |
/* get custom header data (if set) */ | |
std::vector<std::string> headers = request->getHeaders(); | |
if ( !headers.empty() ) | |
{ | |
/* append custom headers one by one */ | |
for ( std::vector<std::string>::iterator it = headers.begin(); | |
it != headers.end(); ++it ) | |
{ | |
m_headers = curl_slist_append ( m_headers, it->c_str() ); | |
} | |
/* set custom headers for curl */ | |
if ( !setOption ( CURLOPT_HTTPHEADER, m_headers ) ) | |
{ | |
return false; | |
} | |
} | |
return setOption ( CURLOPT_URL, request->getUrl() ) | |
&& setOption ( CURLOPT_WRITEFUNCTION, callback ) | |
&& setOption ( CURLOPT_WRITEDATA, stream ) | |
&& setOption ( CURLOPT_HEADERFUNCTION, headerCallback ) | |
&& setOption ( CURLOPT_HEADERDATA, headerStream ); | |
} | |
/// @param responseCode Null not allowed | |
bool perform ( int* responseCode ) | |
{ | |
if ( CURLE_OK != curl_easy_perform ( m_curl ) ) | |
{ | |
return false; | |
} | |
CURLcode code = curl_easy_getinfo ( m_curl, CURLINFO_RESPONSE_CODE, | |
responseCode ); | |
if ( code != CURLE_OK || *responseCode != 200 ) | |
{ | |
return false; | |
} | |
// Get some moar data. | |
double res = -1; //why the is that returned as double!!!???? | |
curl_easy_getinfo ( m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &res ); | |
m_downloadLength = res; | |
return true; | |
} | |
int getDownloadLenght() | |
{ | |
return m_downloadLength; | |
} | |
}; | |
//Process Get Request | |
static int processGetTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* responseCode, write_callback headerCallback, | |
void* headerStream ) | |
{ | |
CURLRaii curl; | |
bool ok = curl.init ( request, callback, stream, headerCallback, headerStream ) | |
&& curl.setOption ( CURLOPT_FOLLOWLOCATION, true ) | |
&& curl.perform ( responseCode ); | |
return ok ? 0 : 1; | |
} | |
//Process Size Request | |
static int processSizeTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* responseCode, write_callback headerCallback, | |
void* headerStream ) | |
{ | |
CURLRaii curl; | |
bool ok = curl.init ( request, callback, stream, headerCallback, headerStream ) | |
&& curl.setOption ( CURLOPT_HEADER, true ) | |
&& curl.setOption ( CURLOPT_NOBODY, true ) | |
&& curl.setOption ( CURLOPT_FOLLOWLOCATION, true ) | |
&& curl.perform ( responseCode ); | |
CCLog ( "Download lenght: %d\n", curl.getDownloadLenght() ); | |
request->setUserData ( ( void* ) ( long ) curl.getDownloadLenght() ); | |
return ok ? 0 : 1; | |
} | |
//Process POST Request | |
static int processPostTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* responseCode, write_callback headerCallback, | |
void* headerStream ) | |
{ | |
CURLRaii curl; | |
bool ok = curl.init ( request, callback, stream, headerCallback, headerStream ) | |
&& curl.setOption ( CURLOPT_POST, 1 ) | |
&& curl.setOption ( CURLOPT_POSTFIELDS, request->getRequestData() ) | |
&& curl.setOption ( CURLOPT_POSTFIELDSIZE, request->getRequestDataSize() ) | |
&& curl.perform ( responseCode ); | |
return ok ? 0 : 1; | |
} | |
//Process PUT Request | |
static int processPutTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* responseCode, write_callback headerCallback, | |
void* headerStream ) | |
{ | |
CURLRaii curl; | |
bool ok = curl.init ( request, callback, stream, headerCallback, headerStream ) | |
&& curl.setOption ( CURLOPT_CUSTOMREQUEST, "PUT" ) | |
&& curl.setOption ( CURLOPT_POSTFIELDS, request->getRequestData() ) | |
&& curl.setOption ( CURLOPT_POSTFIELDSIZE, request->getRequestDataSize() ) | |
&& curl.perform ( responseCode ); | |
return ok ? 0 : 1; | |
} | |
//Process DELETE Request | |
static int processDeleteTask ( HttpRequest* request, write_callback callback, | |
void* stream, int32_t* responseCode, write_callback headerCallback, | |
void* headerStream ) | |
{ | |
CURLRaii curl; | |
bool ok = curl.init ( request, callback, stream, headerCallback, headerStream ) | |
&& curl.setOption ( CURLOPT_CUSTOMREQUEST, "DELETE" ) | |
&& curl.setOption ( CURLOPT_FOLLOWLOCATION, true ) | |
&& curl.perform ( responseCode ); | |
return ok ? 0 : 1; | |
} | |
// HttpClient implementation | |
HttpClient* HttpClient::getInstance() | |
{ | |
if ( s_pHttpClient == NULL ) | |
{ | |
s_pHttpClient = new | |
HttpClient(); | |
} | |
return s_pHttpClient; | |
} | |
void HttpClient::destroyInstance() | |
{ | |
CCAssert ( s_pHttpClient, "" ); | |
CCDirector::sharedDirector()->getScheduler()->unscheduleSelector ( | |
schedule_selector ( | |
HttpClient::dispatchResponseCallbacks ), s_pHttpClient ); | |
s_pHttpClient->release(); | |
} | |
HttpClient::HttpClient() | |
: _timeoutForConnect ( 30 ) | |
, _timeoutForRead ( 60 ) | |
{ | |
CCDirector::sharedDirector()->getScheduler()->scheduleSelector ( | |
schedule_selector ( | |
HttpClient::dispatchResponseCallbacks ), this, 0, false ); | |
CCDirector::sharedDirector()->getScheduler()->pauseTarget ( this ); | |
} | |
HttpClient::~HttpClient() | |
{ | |
need_quit = true; | |
if ( s_requestQueue != NULL ) | |
{ | |
pthread_cond_signal ( &s_SleepCondition ); | |
} | |
s_pHttpClient = NULL; | |
} | |
//Lazy create semaphore & mutex & thread | |
bool HttpClient::lazyInitThreadSemphore() | |
{ | |
if ( s_requestQueue != NULL ) | |
{ | |
return true; | |
} | |
else | |
{ | |
s_requestQueue = new CCArray(); | |
s_requestQueue->init(); | |
s_responseQueue = new CCArray(); | |
s_responseQueue->init(); | |
pthread_mutex_init ( &s_requestQueueMutex, NULL ); | |
pthread_mutex_init ( &s_responseQueueMutex, NULL ); | |
pthread_mutex_init ( &s_SleepMutex, NULL ); | |
pthread_cond_init ( &s_SleepCondition, NULL ); | |
pthread_create ( &s_networkThread, NULL, networkThread, NULL ); | |
pthread_detach ( s_networkThread ); | |
need_quit = false; | |
} | |
return true; | |
} | |
//Add a get task to queue | |
void HttpClient::send ( HttpRequest* request ) | |
{ | |
if ( false == lazyInitThreadSemphore() ) | |
{ | |
return; | |
} | |
if ( !request ) | |
{ | |
return; | |
} | |
++s_asyncRequestCount; | |
request->retain(); | |
pthread_mutex_lock ( &s_requestQueueMutex ); | |
s_requestQueue->addObject ( request ); | |
pthread_mutex_unlock ( &s_requestQueueMutex ); | |
// Notify thread start to work | |
pthread_cond_signal ( &s_SleepCondition ); | |
} | |
// Poll and notify main thread if responses exists in queue | |
void HttpClient::dispatchResponseCallbacks ( float delta ) | |
{ | |
HttpResponse* response = NULL; | |
pthread_mutex_lock ( &s_responseQueueMutex ); | |
if ( s_responseQueue->count() ) | |
{ | |
response = dynamic_cast<HttpResponse*> ( s_responseQueue->objectAtIndex ( 0 ) ); | |
s_responseQueue->removeObjectAtIndex ( 0 ); | |
} | |
pthread_mutex_unlock ( &s_responseQueueMutex ); | |
if ( response ) | |
{ | |
--s_asyncRequestCount; | |
HttpRequest* request = response->getHttpRequest(); | |
CCObject* pTarget = request->getTarget(); | |
SEL_KL_HttpResponse pSelector = request->getSelector(); | |
if ( pTarget && pSelector ) | |
{ | |
( pTarget->*pSelector ) ( this, response ); | |
} | |
response->release(); | |
} | |
if ( 0 == s_asyncRequestCount ) | |
{ | |
CCDirector::sharedDirector()->getScheduler()->pauseTarget ( this ); | |
} | |
} | |
} /* namespace KoalaLib */ | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KL_HTTP_REQUEST_H | |
#define KL_HTTP_REQUEST_H | |
#include "cocos2d.h" | |
#include "ExtensionMacros.h" | |
namespace KoalaLib | |
{ | |
class HttpClient; | |
class HttpResponse; | |
typedef void ( CCObject::*SEL_KL_HttpResponse ) ( HttpClient* client, | |
HttpResponse* response ); | |
#define kl_httpresponse_selector(_SELECTOR) (KoalaLib::SEL_KL_HttpResponse)(&_SELECTOR) | |
class HttpRequest : public CCObject | |
{ | |
public: | |
typedef enum | |
{ | |
kHttpGet, | |
kHttpPost, | |
kHttpPut, | |
kHttpDelete, | |
kHttpSize, | |
kHttpUnkown, | |
} HttpRequestType; | |
/** Constructor | |
Because HttpRequest object will be used between UI thead and network thread, | |
requestObj->autorelease() is forbidden to avoid crashes in CCAutoreleasePool | |
new/retain/release still works, which means you need to release it manually | |
Please refer to HttpRequestTest.cpp to find its usage | |
*/ | |
HttpRequest() | |
{ | |
_requestType = kHttpUnkown; | |
_url.clear(); | |
_requestData.clear(); | |
_tag.clear(); | |
_pTarget = NULL; | |
_pSelector = NULL; | |
_pUserData = NULL; | |
} | |
/** Destructor */ | |
virtual ~HttpRequest() | |
{ | |
if ( _pTarget ) | |
{ | |
_pTarget->release(); | |
} | |
} | |
CCObject* autorelease ( void ) | |
{ | |
CCAssert ( false, "HttpResponse is used between network thread and ui thread \ | |
therefore, autorelease is forbidden here" ); | |
return NULL; | |
} | |
// setter/getters for properties | |
/** Required field for HttpRequest object before being sent. | |
kHttpGet & kHttpPost is currently supported | |
*/ | |
inline void setRequestType ( HttpRequestType type ) | |
{ | |
_requestType = type; | |
} | |
inline HttpRequestType getRequestType() | |
{ | |
return _requestType; | |
} | |
inline void setUrl ( const char* url ) | |
{ | |
_url = url; | |
} | |
inline const char* getUrl() | |
{ | |
return _url.c_str(); | |
} | |
inline void setRequestData ( const char* buffer, unsigned int len ) | |
{ | |
_requestData.assign ( buffer, buffer + len ); | |
} | |
inline char* getRequestData() | |
{ | |
return & ( _requestData.front() ); | |
} | |
inline int getRequestDataSize() | |
{ | |
return _requestData.size(); | |
} | |
inline void setTag ( const char* tag ) | |
{ | |
_tag = tag; | |
} | |
inline const char* getTag() | |
{ | |
return _tag.c_str(); | |
} | |
inline void setUserData ( void* pUserData ) | |
{ | |
_pUserData = pUserData; | |
} | |
inline void* getUserData() | |
{ | |
return _pUserData; | |
} | |
inline void setResponseCallback ( CCObject* pTarget, | |
SEL_KL_HttpResponse pSelector ) | |
{ | |
_pTarget = pTarget; | |
_pSelector = pSelector; | |
if ( _pTarget ) | |
{ | |
_pTarget->retain(); | |
} | |
} | |
inline CCObject* getTarget() | |
{ | |
return _pTarget; | |
} | |
class _prxy | |
{ | |
public: | |
_prxy ( SEL_KL_HttpResponse cb ) : _cb ( cb ) {} | |
~_prxy() {}; | |
operator SEL_KL_HttpResponse() const | |
{ | |
return _cb; | |
} | |
CC_DEPRECATED_ATTRIBUTE operator SEL_CallFuncND() const | |
{ | |
return ( SEL_CallFuncND ) _cb; | |
} | |
protected: | |
SEL_KL_HttpResponse _cb; | |
}; | |
inline _prxy getSelector() | |
{ | |
return _prxy ( _pSelector ); | |
} | |
inline void setHeaders ( std::vector<std::string> pHeaders ) | |
{ | |
_headers = pHeaders; | |
} | |
inline std::vector<std::string> getHeaders() | |
{ | |
return _headers; | |
} | |
protected: | |
// properties | |
HttpRequestType | |
_requestType; /// kHttpRequestGet, kHttpRequestPost or other enums | |
std::string _url; /// target url that this request is sent to | |
std::vector<char> _requestData; /// used for POST | |
std::string | |
_tag; /// user defined tag, to identify different requests in response callback | |
CCObject* _pTarget; /// callback target of pSelector function | |
SEL_KL_HttpResponse | |
_pSelector; /// callback function, e.g. MyLayer::onHttpResponse(HttpClient *sender, HttpResponse * response) | |
void* _pUserData; /// You can add your customed data here | |
std::vector<std::string> _headers; /// custom http headers | |
}; | |
} /* namespace KoalaLib */ | |
#endif //KL_HTTP_REQUEST_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KL_HTTP_RESPONSE_H | |
#define KL_HTTP_RESPONSE_H | |
#include "cocos2d.h" | |
#include "ExtensionMacros.h" | |
#include "downloader/HttpRequest.h" | |
namespace KoalaLib | |
{ | |
/** | |
@brief defines the object which users will receive at onHttpCompleted(sender, HttpResponse) callback | |
Please refer to samples/TestCpp/Classes/ExtensionTest/NetworkTest/HttpClientTest.cpp as a sample | |
@since v2.0.2 | |
*/ | |
class HttpResponse : public CCObject | |
{ | |
public: | |
/** Constructor, it's used by CCHttpClient internal, users don't need to create HttpResponse manually | |
@param request the corresponding HttpRequest which leads to this response | |
*/ | |
HttpResponse ( HttpRequest* request ) : | |
_responseCode ( 0 ) | |
{ | |
_pHttpRequest = request; | |
if ( _pHttpRequest ) | |
{ | |
_pHttpRequest->retain(); | |
} | |
_succeed = false; | |
_responseData.clear(); | |
_errorBuffer.clear(); | |
} | |
/** Destructor, it will be called in CCHttpClient internal, | |
users don't need to desturct HttpResponse object manully | |
*/ | |
virtual ~HttpResponse() | |
{ | |
if ( _pHttpRequest ) | |
{ | |
_pHttpRequest->release(); | |
} | |
} | |
/** Override autorelease method to prevent developers from calling it */ | |
CCObject* autorelease ( void ) | |
{ | |
CCAssert ( false, "HttpResponse is used between network thread and ui thread \ | |
therefore, autorelease is forbidden here" ); | |
return NULL; | |
} | |
/** Get the corresponding HttpRequest object which leads to this response | |
There's no paired setter for it, coz it's already setted in class constructor | |
*/ | |
inline HttpRequest* getHttpRequest() | |
{ | |
return _pHttpRequest; | |
} | |
/** To see if the http reqeust is returned successfully, | |
Althrough users can judge if (http return code = 200), we want an easier way | |
If this getter returns false, you can call getResponseCode and getErrorBuffer to find more details | |
*/ | |
inline bool isSucceed() | |
{ | |
return _succeed; | |
} | |
/** Get the http response raw data */ | |
inline std::vector<char>* getResponseData() | |
{ | |
return &_responseData; | |
} | |
/** get the Rawheader **/ | |
inline std::vector<char>* getResponseHeader() | |
{ | |
return &_responseHeader; | |
} | |
/** Get the http response errorCode | |
* I know that you want to see http 200 :) | |
*/ | |
inline int getResponseCode() | |
{ | |
return _responseCode; | |
} | |
inline const char* getErrorBuffer() | |
{ | |
return _errorBuffer.c_str(); | |
} | |
/** Set if the http request is returned successfully, | |
Althrough users can judge if (http code == 200), we want a easier way | |
This setter is mainly used in CCHttpClient, users mustn't set it directly | |
*/ | |
inline void setSucceed ( bool value ) | |
{ | |
_succeed = value; | |
} | |
inline void setResponseData ( std::vector<char>* data ) | |
{ | |
_responseData = *data; | |
} | |
inline void setResponseHeader ( std::vector<char>* data ) | |
{ | |
_responseHeader = *data; | |
} | |
inline void setResponseCode ( int value ) | |
{ | |
_responseCode = value; | |
} | |
inline void setErrorBuffer ( const char* value ) | |
{ | |
_errorBuffer.clear(); | |
_errorBuffer.assign ( value ); | |
}; | |
protected: | |
bool initWithRequest ( HttpRequest* request ); | |
// properties | |
HttpRequest* | |
_pHttpRequest; /// the corresponding HttpRequest pointer who leads to this response | |
bool _succeed; /// to indecate if the http reqeust is successful simply | |
std::vector<char> | |
_responseData; /// the returned raw data. You can also dump it as a string | |
std::vector<char> | |
_responseHeader; /// the returned raw header data. You can also dump it as a string | |
int _responseCode; /// the status code returned from libcurl, e.g. 200, 404 | |
std::string | |
_errorBuffer; /// if _responseCode != 200, please read _errorBuffer to find the reason | |
}; | |
} /* namespace KoalaLib */ | |
#endif //__HTTP_RESPONSE_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment