HTTPClient

Fork of HTTPClient by Donatien Garnier

Revision:
17:679e15a3d3db
Parent:
16:1f743885e7de
Child:
18:277279a1891e
diff -r 1f743885e7de -r 679e15a3d3db HTTPClient.cpp
--- a/HTTPClient.cpp	Thu Aug 30 15:38:57 2012 +0000
+++ b/HTTPClient.cpp	Fri May 02 13:13:39 2014 +0000
@@ -193,6 +193,24 @@
       ret = send(buf);
       CHECK_CONN_ERR(ret);
     }
+    
+    //Send specific headers
+    while( pDataOut->getHeader(buf, sizeof(buf) - 3) ) //must have space left for CRLF + 0 terminating char
+    {
+      size_t headerlen = strlen(buf);
+      snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
+      ret = send(buf);
+      CHECK_CONN_ERR(ret);
+    }
+  }
+  
+  //Send specific headers
+  while( pDataIn->getHeader(buf, sizeof(buf) - 3) )
+  {
+    size_t headerlen = strlen(buf);
+    snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
+    ret = send(buf);
+    CHECK_CONN_ERR(ret);
   }
   
   //Close headers
@@ -247,27 +265,50 @@
         break;
       }
     }
-
   }
   
   //Receive response
   DBG("Receiving response");
-  ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
+  ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
   CHECK_CONN_ERR(ret);
 
   buf[trfLen] = '\0';
 
-  char* crlfPtr = strstr(buf, "\r\n");
+  //Make sure we got the first response line
+  char* crlfPtr = NULL;
+  while( true )
+  {
+    crlfPtr = strstr(buf, "\r\n");
   if(crlfPtr == NULL)
   {
+      if( trfLen < CHUNK_SIZE - 1 )
+      {
+        size_t newTrfLen;
+        ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+        trfLen += newTrfLen;
+        buf[trfLen] = '\0';
+        DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
+        CHECK_CONN_ERR(ret);
+        continue;
+      }
+      else
+      {
     PRTCL_ERR();
   }
+    }
+    break;
+  }
 
   int crlfPos = crlfPtr - buf;
   buf[crlfPos] = '\0';
 
   //Parse HTTP response
-  if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
+  //if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
+  if(crlfPos > 13)
+  {
+    buf[13] = '\0';
+  }
+  if( sscanf(buf, "HTTP/%*d.%*d %d", &m_httpResponseCode) != 1 ) //Kludge for newlib nano
   {
     //Cannot match string, error
     ERR("Not a correct HTTP answer : %s\n", buf);
@@ -288,6 +329,7 @@
 
   size_t recvContentLength = 0;
   bool recvChunked = false;
+  bool recvLengthUnknown = true;
   //Now get headers
   while( true )
   {
@@ -325,16 +367,41 @@
     char key[32];
     char value[32];
 
-    key[31] = '\0';
-    value[31] = '\0';
+    //key[31] = '\0';
+    //value[31] = '\0';
+
+    memset(key, 0, 32);
+    memset(value, 0, 32);
 
-    int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
+    //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
+    
+    int n = 0;
+    
+    char* keyEnd = strchr(buf, ':');
+    if(keyEnd != NULL)
+    {
+      *keyEnd = '\0';
+    
+      if(sscanf(buf, "%31c", key) == 1)
+      {
+        n++;
+        char* valueStart = keyEnd + 2;
+        if( (valueStart - buf) < crlfPos )
+        {
+          if(sscanf(valueStart, "%31c", value) == 1)
+          {
+            n++;
+          }
+        }
+      }
+    }
     if ( n == 2 )
     {
       DBG("Read header : %s: %s\n", key, value);
       if( !strcmp(key, "Content-Length") )
       {
         sscanf(value, "%d", &recvContentLength);
+        recvLengthUnknown = false;
         pDataIn->setDataLen(recvContentLength);
       }
       else if( !strcmp(key, "Transfer-Encoding") )
@@ -342,6 +409,7 @@
         if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") )
         {
           recvChunked = true;
+          recvLengthUnknown = false;
           pDataIn->setIsChunked(true);
         }
       }
@@ -426,28 +494,49 @@
       readLen = recvContentLength;
     }
 
-    DBG("Retrieving %d bytes", readLen);
+    DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen);
 
     do
     {
+      if(recvLengthUnknown )
+      {
+        readLen = trfLen;
+      }
       pDataIn->write(buf, MIN(trfLen, readLen));
-      if( trfLen > readLen )
+      if(!recvLengthUnknown)
       {
-        memmove(buf, &buf[readLen], trfLen - readLen);
-        trfLen -= readLen;
-        readLen = 0;
+        if( trfLen > readLen )
+        {
+          memmove(buf, &buf[readLen], trfLen - readLen);
+          trfLen -= readLen;
+          readLen = 0;
+        }
+        else
+        {
+          readLen -= trfLen;
+        }
       }
       else
       {
-        readLen -= trfLen;
+        trfLen = 0;
       }
 
-      if(readLen)
+      if(readLen || recvLengthUnknown)
       {
         ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
+        if(recvLengthUnknown && (ret == HTTP_CLOSED))
+        {
+          //Write and exit
+          pDataIn->write(buf, trfLen);
+          break;
+        }
         CHECK_CONN_ERR(ret);
+        if(recvLengthUnknown && (trfLen == 0))
+        {
+          break;
+        }
       }
-    } while(readLen);
+    } while(readLen || recvLengthUnknown);
 
     if( recvChunked )
     {