优化http处理无content字段时的逻辑

This commit is contained in:
xiongziliang 2018-11-13 22:50:43 +08:00
parent 022838a7d3
commit 57dcb63b6b
6 changed files with 53 additions and 51 deletions

View File

@ -138,7 +138,7 @@ void HttpClient::onRecvBytes(const char *data, int size) {
} }
void HttpClient::onErr(const SockException &ex) { void HttpClient::onErr(const SockException &ex) {
if (ex.getErrCode() == Err_eof && _totalBodySize == INT64_MAX) { if (ex.getErrCode() == Err_eof && _totalBodySize < 0) {
//如果Content-Length未指定 但服务器断开链接 //如果Content-Length未指定 但服务器断开链接
//则认为本次http请求完成 //则认为本次http请求完成
onResponseCompleted_l(); onResponseCompleted_l();
@ -148,52 +148,53 @@ void HttpClient::onErr(const SockException &ex) {
int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) { int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) {
_parser.Parse(data); _parser.Parse(data);
onResponseHeader(_parser.Url(), _parser.getValues());
checkCookie(_parser.getValues()); checkCookie(_parser.getValues());
_totalBodySize = onResponseHeader(_parser.Url(), _parser.getValues());
if(_parser["Content-Length"].empty()){ if(!_parser["Content-Length"].empty()){
//没有Content-Length字段 //有Content-Length字段时忽略onResponseHeader的返回值
auto ret = onResponseCompleted_l(); _totalBodySize = atoll(_parser["Content-Length"].data());
if(ret){
return 0;
}
//如果http回复未声明Content-Length字段但是却有content内容那说明可能是个不限长度的content
_totalBodySize = INT64_MAX;
_recvedBodySize = 0;
//返回-1代表不限制content回复大小
return -1;
} }
//有Content-Length字段
_recvedBodySize = 0;
_totalBodySize = atoll(_parser["Content-Length"].data());
if(_totalBodySize == 0){ if(_totalBodySize == 0){
//content长度为0本次http请求结束 //后续没content本次http请求结束
onResponseCompleted_l(); onResponseCompleted_l();
return 0; return 0;
} }
//虽然我们知道content的确切大小 //当_totalBodySize != 0时到达这里代表后续有content
//虽然我们在_totalBodySize >0 时知道content的确切大小
//但是由于我们没必要等content接收完毕才回调onRecvContent(因为这样浪费内存并且要多次拷贝数据) //但是由于我们没必要等content接收完毕才回调onRecvContent(因为这样浪费内存并且要多次拷贝数据)
//所以返回-1代表我们接下来分段接收content //所以返回-1代表我们接下来分段接收content
_recvedBodySize = 0;
return -1; return -1;
} }
void HttpClient::onRecvContent(const char *data, uint64_t len) { void HttpClient::onRecvContent(const char *data, uint64_t len) {
auto recvedBodySize = _recvedBodySize + 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); onResponseBody(data, len, recvedBodySize, _totalBodySize);
_recvedBodySize = recvedBodySize; _recvedBodySize = recvedBodySize;
} else { return;
onResponseBody(data, _totalBodySize - _recvedBodySize, _totalBodySize, _totalBodySize); }
bool biggerThanExpected = recvedBodySize > _totalBodySize;
onResponseCompleted_l(); //content接收完毕
if(biggerThanExpected) { onResponseBody(data, _totalBodySize - _recvedBodySize, _totalBodySize, _totalBodySize);
//声明的content数据比真实的小那么我们只截取前面部分的并断开链接 bool biggerThanExpected = recvedBodySize > _totalBodySize;
shutdown(); onResponseCompleted_l();
onDisconnect(SockException(Err_other, "http response content size bigger than expected")); 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() { void HttpClient::onManager() {
if (_aliveTicker.elapsedTime() > 3 * 1000 && _totalBodySize == INT64_MAX) { if (_aliveTicker.elapsedTime() > 3 * 1000 && _totalBodySize < 0) {
//如果Content-Length未指定 但接收数据超时 //如果Content-Length未指定 但接收数据超时
//则认为本次http请求完成 //则认为本次http请求完成
onResponseCompleted_l(); onResponseCompleted_l();
@ -227,14 +228,11 @@ void HttpClient::onManager() {
} }
} }
bool HttpClient::onResponseCompleted_l() { void HttpClient::onResponseCompleted_l() {
_totalBodySize = 0; _totalBodySize = 0;
_recvedBodySize = 0; _recvedBodySize = 0;
bool ret = onResponseCompleted(); HttpRequestSplitter::reset();
if(ret){ onResponseCompleted();
HttpRequestSplitter::reset();
}
return ret;
} }
void HttpClient::checkCookie(const HttpClient::HttpHeader &headers) { void HttpClient::checkCookie(const HttpClient::HttpHeader &headers) {

View File

@ -247,9 +247,13 @@ protected:
* http回复头 * http回复头
* @param status :200 OK * @param status :200 OK
* @param headers http头 * @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; DebugL << status;
//无Content-Length字段时默认后面全是content
return -1;
}; };
/** /**
@ -265,11 +269,9 @@ protected:
/** /**
* http回复完毕, * http回复完毕,
* @return
*/ */
virtual bool onResponseCompleted(){ virtual void onResponseCompleted(){
DebugL; DebugL;
return true;
} }
/** /**
@ -295,7 +297,7 @@ protected:
virtual void onSend() override; virtual void onSend() override;
virtual void onManager() override; virtual void onManager() override;
private: private:
bool onResponseCompleted_l(); void onResponseCompleted_l();
void checkCookie(const HttpHeader &headers ); void checkCookie(const HttpHeader &headers );
protected: protected:
bool _isHttps; bool _isHttps;

View File

@ -63,7 +63,7 @@ void HttpDownloader::startDownload(const string& url, const string& filePath,boo
sendRequest(url,timeOutSecond); 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"){ if(status != "200" && status != "206"){
//失败 //失败
shutdown(); shutdown();
@ -75,6 +75,8 @@ void HttpDownloader::onResponseHeader(const string& status,const HttpHeader& hea
_onResult = nullptr; _onResult = nullptr;
} }
} }
//后续全部是content
return -1;
} }
void HttpDownloader::onResponseBody(const char* buf, size_t size, size_t recvedSize, size_t totalSize) { 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(); closeFile();
//InfoL << "md5Sum:" << getMd5Sum(_filePath); //InfoL << "md5Sum:" << getMd5Sum(_filePath);
_bDownloadSuccess = true; _bDownloadSuccess = true;
@ -91,7 +93,6 @@ bool HttpDownloader::onResponseCompleted() {
_onResult(Err_success,"success",_filePath.data()); _onResult(Err_success,"success",_filePath.data());
_onResult = nullptr; _onResult = nullptr;
} }
return true;
} }
void HttpDownloader::onDisconnect(const SockException &ex) { void HttpDownloader::onDisconnect(const SockException &ex) {

View File

@ -47,9 +47,9 @@ public:
_onResult = cb; _onResult = cb;
} }
private: 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; 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 onDisconnect(const SockException &ex) override;
void closeFile(); void closeFile();
private: private:

View File

@ -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(); _strRecvBody.clear();
//后续全部是content
return -1;
} }
void HttpRequester::onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) { void HttpRequester::onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) {
_strRecvBody.append(buf,size); _strRecvBody.append(buf,size);
} }
bool HttpRequester::onResponseCompleted() { void HttpRequester::onResponseCompleted() {
if(_onResult){ if(_onResult){
_onResult(SockException(),responseStatus(),responseHeader(),_strRecvBody); _onResult(SockException(),responseStatus(),responseHeader(),_strRecvBody);
_onResult = nullptr; _onResult = nullptr;
} }
return true;
} }
void HttpRequester::onDisconnect(const SockException &ex){ void HttpRequester::onDisconnect(const SockException &ex){

View File

@ -40,9 +40,9 @@ public:
virtual ~HttpRequester(); virtual ~HttpRequester();
void startRequester(const string &url,const HttpRequesterResult &onResult,float timeOutSecond = 10); void startRequester(const string &url,const HttpRequesterResult &onResult,float timeOutSecond = 10);
private: 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; 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 onDisconnect(const SockException &ex) override;
private: private:
string _strRecvBody; string _strRecvBody;