diff --git a/src/Http/HttpClient.cpp b/src/Http/HttpClient.cpp index 272cc405..385619fe 100644 --- a/src/Http/HttpClient.cpp +++ b/src/Http/HttpClient.cpp @@ -138,7 +138,7 @@ void HttpClient::onRecvBytes(const char *data, int size) { } void HttpClient::onErr(const SockException &ex) { - if (ex.getErrCode() == Err_eof && _totalBodySize == INT64_MAX) { + if (ex.getErrCode() == Err_eof && _totalBodySize < 0) { //如果Content-Length未指定 但服务器断开链接 //则认为本次http请求完成 onResponseCompleted_l(); @@ -148,52 +148,53 @@ void HttpClient::onErr(const SockException &ex) { int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) { _parser.Parse(data); - onResponseHeader(_parser.Url(), _parser.getValues()); checkCookie(_parser.getValues()); + _totalBodySize = onResponseHeader(_parser.Url(), _parser.getValues()); - if(_parser["Content-Length"].empty()){ - //没有Content-Length字段 - auto ret = onResponseCompleted_l(); - if(ret){ - return 0; - } - //如果http回复未声明Content-Length字段,但是却有content内容,那说明可能是个不限长度的content - _totalBodySize = INT64_MAX; - _recvedBodySize = 0; - //返回-1代表不限制content回复大小 - return -1; + if(!_parser["Content-Length"].empty()){ + //有Content-Length字段时忽略onResponseHeader的返回值 + _totalBodySize = atoll(_parser["Content-Length"].data()); } - //有Content-Length字段 - _recvedBodySize = 0; - _totalBodySize = atoll(_parser["Content-Length"].data()); - if(_totalBodySize == 0){ - //content长度为0,本次http请求结束 + //后续没content,本次http请求结束 onResponseCompleted_l(); return 0; } - //虽然我们知道content的确切大小, + //当_totalBodySize != 0时到达这里,代表后续有content + //虽然我们在_totalBodySize >0 时知道content的确切大小, //但是由于我们没必要等content接收完毕才回调onRecvContent(因为这样浪费内存并且要多次拷贝数据) //所以返回-1代表我们接下来分段接收content + _recvedBodySize = 0; return -1; } void HttpClient::onRecvContent(const char *data, uint64_t len) { auto recvedBodySize = _recvedBodySize + len; - if (recvedBodySize < _totalBodySize) { + if(_totalBodySize < 0){ + //不限长度的content,最大支持INT64_MAX个字节 + onResponseBody(data, len, recvedBodySize, INT64_MAX); + _recvedBodySize = recvedBodySize; + return; + } + + //固定长度的content + if ( recvedBodySize < _totalBodySize ) { + //content还未接收完毕 onResponseBody(data, len, recvedBodySize, _totalBodySize); _recvedBodySize = recvedBodySize; - } else { - onResponseBody(data, _totalBodySize - _recvedBodySize, _totalBodySize, _totalBodySize); - bool biggerThanExpected = recvedBodySize > _totalBodySize; - onResponseCompleted_l(); - if(biggerThanExpected) { - //声明的content数据比真实的小,那么我们只截取前面部分的并断开链接 - shutdown(); - onDisconnect(SockException(Err_other, "http response content size bigger than expected")); - } + return; + } + + //content接收完毕 + onResponseBody(data, _totalBodySize - _recvedBodySize, _totalBodySize, _totalBodySize); + bool biggerThanExpected = recvedBodySize > _totalBodySize; + onResponseCompleted_l(); + if(biggerThanExpected) { + //声明的content数据比真实的小,那么我们只截取前面部分的并断开链接 + shutdown(); + onDisconnect(SockException(Err_other, "http response content size bigger than expected")); } } @@ -214,7 +215,7 @@ void HttpClient::onSend() { } void HttpClient::onManager() { - if (_aliveTicker.elapsedTime() > 3 * 1000 && _totalBodySize == INT64_MAX) { + if (_aliveTicker.elapsedTime() > 3 * 1000 && _totalBodySize < 0) { //如果Content-Length未指定 但接收数据超时 //则认为本次http请求完成 onResponseCompleted_l(); @@ -227,14 +228,11 @@ void HttpClient::onManager() { } } -bool HttpClient::onResponseCompleted_l() { +void HttpClient::onResponseCompleted_l() { _totalBodySize = 0; _recvedBodySize = 0; - bool ret = onResponseCompleted(); - if(ret){ - HttpRequestSplitter::reset(); - } - return ret; + HttpRequestSplitter::reset(); + onResponseCompleted(); } void HttpClient::checkCookie(const HttpClient::HttpHeader &headers) { diff --git a/src/Http/HttpClient.h b/src/Http/HttpClient.h index 00f9c062..acc28a1c 100644 --- a/src/Http/HttpClient.h +++ b/src/Http/HttpClient.h @@ -247,9 +247,13 @@ protected: * 收到http回复头 * @param status 状态码,譬如:200 OK * @param headers http头 + * @return 返回后续content的长度;-1:后续数据全是content;>=0:固定长度content + * 需要指出的是,在http头中带有Content-Length字段时,该返回值无效 */ - virtual void onResponseHeader(const string &status,const HttpHeader &headers){ + virtual int64_t onResponseHeader(const string &status,const HttpHeader &headers){ DebugL << status; + //无Content-Length字段时默认后面全是content + return -1; }; /** @@ -265,11 +269,9 @@ protected: /** * 接收http回复完毕, - * @return 是否真的结束数据接收 */ - virtual bool onResponseCompleted(){ + virtual void onResponseCompleted(){ DebugL; - return true; } /** @@ -295,7 +297,7 @@ protected: virtual void onSend() override; virtual void onManager() override; private: - bool onResponseCompleted_l(); + void onResponseCompleted_l(); void checkCookie(const HttpHeader &headers ); protected: bool _isHttps; diff --git a/src/Http/HttpDownloader.cpp b/src/Http/HttpDownloader.cpp index a8724e31..f379b115 100644 --- a/src/Http/HttpDownloader.cpp +++ b/src/Http/HttpDownloader.cpp @@ -63,7 +63,7 @@ void HttpDownloader::startDownload(const string& url, const string& filePath,boo sendRequest(url,timeOutSecond); } -void HttpDownloader::onResponseHeader(const string& status,const HttpHeader& headers) { +int64_t HttpDownloader::onResponseHeader(const string& status,const HttpHeader& headers) { if(status != "200" && status != "206"){ //失败 shutdown(); @@ -75,6 +75,8 @@ void HttpDownloader::onResponseHeader(const string& status,const HttpHeader& hea _onResult = nullptr; } } + //后续全部是content + return -1; } void HttpDownloader::onResponseBody(const char* buf, size_t size, size_t recvedSize, size_t totalSize) { @@ -83,7 +85,7 @@ void HttpDownloader::onResponseBody(const char* buf, size_t size, size_t recvedS } } -bool HttpDownloader::onResponseCompleted() { +void HttpDownloader::onResponseCompleted() { closeFile(); //InfoL << "md5Sum:" << getMd5Sum(_filePath); _bDownloadSuccess = true; @@ -91,7 +93,6 @@ bool HttpDownloader::onResponseCompleted() { _onResult(Err_success,"success",_filePath.data()); _onResult = nullptr; } - return true; } void HttpDownloader::onDisconnect(const SockException &ex) { diff --git a/src/Http/HttpDownloader.h b/src/Http/HttpDownloader.h index 591c1504..4b3e3fae 100644 --- a/src/Http/HttpDownloader.h +++ b/src/Http/HttpDownloader.h @@ -47,9 +47,9 @@ public: _onResult = cb; } private: - void onResponseHeader(const string &status,const HttpHeader &headers) override; + int64_t onResponseHeader(const string &status,const HttpHeader &headers) override; void onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) override; - bool onResponseCompleted() override; + void onResponseCompleted() override; void onDisconnect(const SockException &ex) override; void closeFile(); private: diff --git a/src/Http/HttpRequester.cpp b/src/Http/HttpRequester.cpp index 8b0f3e85..62ea4d96 100644 --- a/src/Http/HttpRequester.cpp +++ b/src/Http/HttpRequester.cpp @@ -34,20 +34,21 @@ HttpRequester::~HttpRequester(){ } -void HttpRequester::onResponseHeader(const string &status,const HttpHeader &headers) { +int64_t HttpRequester::onResponseHeader(const string &status,const HttpHeader &headers) { _strRecvBody.clear(); + //后续全部是content + return -1; } void HttpRequester::onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) { _strRecvBody.append(buf,size); } -bool HttpRequester::onResponseCompleted() { +void HttpRequester::onResponseCompleted() { if(_onResult){ _onResult(SockException(),responseStatus(),responseHeader(),_strRecvBody); _onResult = nullptr; } - return true; } void HttpRequester::onDisconnect(const SockException &ex){ diff --git a/src/Http/HttpRequester.h b/src/Http/HttpRequester.h index 1ce3ca59..3b43d96b 100644 --- a/src/Http/HttpRequester.h +++ b/src/Http/HttpRequester.h @@ -40,9 +40,9 @@ public: virtual ~HttpRequester(); void startRequester(const string &url,const HttpRequesterResult &onResult,float timeOutSecond = 10); private: - void onResponseHeader(const string &status,const HttpHeader &headers) override; + int64_t onResponseHeader(const string &status,const HttpHeader &headers) override; void onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) override; - bool onResponseCompleted() override; + void onResponseCompleted() override; void onDisconnect(const SockException &ex) override; private: string _strRecvBody;