Browse Source

fix #358: handle no Content-Length case

ithewei 2 years ago
parent
commit
c9eda2fc88
4 changed files with 36 additions and 23 deletions
  1. 5 0
      http/Http1Parser.h
  2. 2 0
      http/HttpParser.h
  3. 19 11
      http/client/AsyncHttpClient.cpp
  4. 10 12
      http/client/HttpClient.cpp

+ 5 - 0
http/Http1Parser.h

@@ -69,6 +69,11 @@ public:
         return state == HP_MESSAGE_COMPLETE;
     }
 
+    virtual bool IsEof() {
+        FeedRecvData(NULL, 0);
+        return IsComplete();
+    }
+
     virtual int GetError() {
         return parser.http_errno;
     }

+ 2 - 0
http/HttpParser.h

@@ -32,6 +32,8 @@ public:
     // Http2Parser: (state == H2_RECV_HEADERS || state == H2_RECV_DATA) && stream_closed
     virtual bool IsComplete() = 0;
 
+    virtual bool IsEof() { return false; }
+
     // client
     // SubmitRequest -> while(GetSendData) {send} -> InitResponse -> do {recv -> FeedRecvData} while(WantRecv)
     virtual int SubmitRequest(HttpRequest* req) = 0;

+ 19 - 11
http/client/AsyncHttpClient.cpp

@@ -108,20 +108,28 @@ int AsyncHttpClient::doTask(const HttpClientTaskPtr& task) {
         if (iter != conn_pools.end()) {
             iter->second.remove(channel->fd());
         }
+
         const HttpClientTaskPtr& task = ctx->task;
-        if (task && task->req && task->req->retry_count-- > 0) {
-            if (task->req->retry_delay > 0) {
-                // try again after delay
-                setTimeout(task->req->retry_delay, [this, task](TimerID timerID){
-                    hlogi("retry %s %s", http_method_str(task->req->method), task->req->url.c_str());
-                    sendInLoop(task);
-                });
-            } else {
-                send(task);
+        if (task) {
+            if (ctx->parser && ctx->parser->IsEof()) {
+                ctx->successCallback();
+            }
+            else if (task->req && task->req->retry_count-- > 0) {
+                if (task->req->retry_delay > 0) {
+                    // try again after delay
+                    setTimeout(task->req->retry_delay, [this, task](TimerID timerID){
+                        hlogi("retry %s %s", http_method_str(task->req->method), task->req->url.c_str());
+                        sendInLoop(task);
+                    });
+                } else {
+                    send(task);
+                }
+            }
+            else {
+                ctx->errorCallback();
             }
-        } else {
-            ctx->errorCallback();
         }
+
         removeChannel(channel);
     };
 

+ 10 - 12
http/client/HttpClient.cpp

@@ -324,16 +324,15 @@ send:
             }
             nsend = http_client_send_data(cli, data + total_nsend, len - total_nsend);
             if (nsend <= 0) {
+                err = socket_errno();
+                if (err == EINTR) continue;
                 if (++fail_cnt == 1) {
                     // maybe keep-alive timeout, try again
                     cli->Close();
+                    err = 0;
                     goto connect;
                 }
-                else {
-                    err = socket_errno();
-                    if (err == EINTR) continue;
-                    goto disconnect;
-                }
+                goto disconnect;
             }
             total_nsend += nsend;
         }
@@ -351,20 +350,19 @@ recv:
         }
         nrecv = http_client_recv_data(cli, recvbuf, sizeof(recvbuf));
         if (nrecv <= 0) {
-            if (resp->content_length == 0 && resp->http_major == 1 && resp->http_minor == 0) {
-                // HTTP/1.0, assume close after body
+            err = socket_errno();
+            if (err == EINTR) continue;
+            if (cli->parser->IsEof()) {
+                err = 0;
                 goto disconnect;
             }
             if (++fail_cnt == 1) {
                 // maybe keep-alive timeout, try again
                 cli->Close();
+                err = 0;
                 goto connect;
             }
-            else {
-                err = socket_errno();
-                if (err == EINTR) continue;
-                goto disconnect;
-            }
+            goto disconnect;
         }
         int nparse = cli->parser->FeedRecvData(recvbuf, nrecv);
         if (nparse != nrecv) {