Fix HTTP response parsing bug

This commit is contained in:
antao 2018-09-10 15:50:44 +08:00
parent e28716c343
commit 2391cc1484
6 changed files with 45 additions and 49 deletions

View File

@ -6,23 +6,15 @@
int main()
{
trantor::Logger::setLogLevel(trantor::Logger::TRACE);
struct hostent* he = gethostbyname("www.baidu.com");
struct in_addr addr;
if (he && he->h_addrtype == AF_INET) {
addr = *reinterpret_cast<struct in_addr*>(he->h_addr);
struct sockaddr_in ad;
bzero(&ad, sizeof ad);
ad.sin_family = AF_INET;
ad.sin_addr=addr;
trantor::InetAddress netaddr(ad);
auto client=HttpClient::newHttpClient(netaddr.toIp(),80);
auto client=HttpClient::newHttpClient("http://www.baidu.com");
auto req=HttpRequest::newHttpRequest();
req->setMethod(drogon::HttpRequest::kGet);
req->setPath("/s");
req->setParameter("wd","weixin");
int count=0;
for(int i=0;i<10;i++)
{
client->sendRequest(req,[&](ReqResult result,const HttpResponse &response){
std::cout<<"receive response!"<<std::endl;
//auto headers=response.
@ -30,8 +22,8 @@ int main()
std::cout<<response.getBody()<<std::endl;
std::cout<<"count="<<count<<std::endl;
});
HttpAppFramework::instance().run();
} else {
std::cout<<"can't find the host"<<std::endl;
}
HttpAppFramework::instance().run();
}

View File

@ -35,7 +35,7 @@ namespace drogon{
virtual void sendRequest(const HttpRequestPtr &req,const HttpReqCallback &callback)=0;
virtual ~HttpClient(){}
static HttpClientPtr newHttpClient(const std::string &ip,uint16_t port,bool useSSL=false) ;
static HttpClientPtr newHttpClient(const trantor::InetAddress &addr,bool useSSL=false) ;
// static HttpClientPtr newHttpClient(const trantor::InetAddress &addr,bool useSSL=false) ;
static HttpClientPtr newHttpClient(const std::string &hostString);
protected:
HttpClient()= default;

View File

@ -187,7 +187,7 @@ void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr,tran
{
HttpContext* context = any_cast<HttpContext>(connPtr->getMutableContext());
LOG_TRACE << "###:" << msg->readableBytes();
//LOG_TRACE << "###:" << msg->readableBytes();
if (!context->parseResponse(msg)) {
assert(!_reqAndCallbacks.empty());
auto cb=_reqAndCallbacks.front().second;
@ -231,11 +231,10 @@ HttpClientPtr HttpClient::newHttpClient(const std::string &ip,uint16_t port,bool
{
return std::make_shared<HttpClientImpl>(((HttpAppFrameworkImpl &)(HttpAppFramework::instance())).loop(),trantor::InetAddress(ip,port),useSSL);
}
HttpClientPtr HttpClient::newHttpClient(const trantor::InetAddress &addr,bool useSSL)
{
return std::make_shared<HttpClientImpl>(((HttpAppFrameworkImpl &)(HttpAppFramework::instance())).loop(),addr,useSSL);
}
//HttpClientPtr HttpClient::newHttpClient(const trantor::InetAddress &addr,bool useSSL)
//{
// return std::make_shared<HttpClientImpl>(((HttpAppFrameworkImpl &)(HttpAppFramework::instance())).loop(),addr,useSSL);
//}
HttpClientPtr HttpClient::newHttpClient(const std::string &hostString)
{
return std::make_shared<HttpClientImpl>(((HttpAppFrameworkImpl &)(HttpAppFramework::instance())).loop(),hostString);

View File

@ -374,7 +374,7 @@ bool HttpContext::parseResponse(MsgBuffer *buf)
std::string len(buf->peek(), crlf - buf->peek());
char *end;
response_._current_chunk_length = strtol(len.c_str(), &end, 16);
LOG_TRACE << "chun length : " << response_._current_chunk_length;
//LOG_TRACE << "chun length : " << response_._current_chunk_length;
if (response_._current_chunk_length != 0)
{
res_state_ = HttpResponseParseState::kExpectChunkBody;
@ -392,28 +392,27 @@ bool HttpContext::parseResponse(MsgBuffer *buf)
}
else if (res_state_ == HttpResponseParseState::kExpectChunkBody)
{
const char *crlf = buf->findCRLF();
if (crlf)
//LOG_TRACE<<"expect chunk len="<<response_._current_chunk_length;
if(buf->readableBytes()>=(response_._current_chunk_length+2))
{
if (response_._current_chunk_length == (size_t)(crlf - buf->peek()))
if(*(buf->peek()+response_._current_chunk_length)=='\r'&&
*(buf->peek()+response_._current_chunk_length+1)=='\n' )
{
//current chunk end crlf
response_._body += std::string(buf->peek(), response_._current_chunk_length);
buf->retrieveUntil(crlf + 2);
buf->retrieve(response_._current_chunk_length+2);
response_._current_chunk_length = 0;
res_state_ = HttpResponseParseState::kExpectChunkLen;
}
else if (response_._current_chunk_length > (size_t)(crlf - buf->peek()))
else
{
//current chunk body crlf
response_._body += std::string(buf->peek(), crlf - buf->peek() + 1);
buf->retrieveUntil(crlf + 2);
response_._current_chunk_length -= (crlf - buf->peek() + 2);
//error!
buf->retrieveAll();
return false;
}
}
else
{
hasMore = false;
hasMore=false;
}
}
else if (res_state_ == HttpResponseParseState::kExpectLastEmptyChunk)

View File

@ -128,7 +128,9 @@ namespace drogon
virtual std::string getHeader(const std::string& key) const override
{
auto iter=_headers.find(key);
auto field=key;
transform(field.begin(), field.end(), field.begin(), ::tolower);
auto iter=_headers.find(field);
if(iter == _headers.end())
{
return "";
@ -140,12 +142,15 @@ namespace drogon
}
virtual void addHeader(const std::string& key, const std::string& value) override
{
_headers[key] = value;
auto field=key;
transform(field.begin(), field.end(), field.begin(), ::tolower);
_headers[field] = value;
}
virtual void addHeader(const char* start, const char* colon, const char* end) override
{
std::string field(start, colon);
transform(field.begin(), field.end(), field.begin(), ::tolower);
++colon;
while (colon < end && isspace(*colon)) {
++colon;
@ -155,7 +160,8 @@ namespace drogon
value.resize(value.size() - 1);
}
_headers[field] = value;
transform(field.begin(), field.end(), field.begin(), ::tolower);
//FIXME:reponse cookie should be "Set-Cookie:...."
if(field == "cookie") {
//LOG_INFO<<"cookies!!!:"<<value;
std::string::size_type pos;

@ -1 +1 @@
Subproject commit ca985eac44b2a4d0a6ac3498bac9973e4c52ddfe
Subproject commit 6cb562a6cced825dcd15732be0990c8a7e0ab112