The code from https://github.com/vpcola/Nucleo

Revision:
0:5464d5e415e5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HttpClient.cpp	Wed Oct 08 11:00:24 2014 +0000
@@ -0,0 +1,357 @@
+#include "HttpClient.h"
+#include "Utility.h"
+#include <string>
+#include <cstring>
+#include <vector>
+
+extern Serial pc;
+
+#if 1
+//Enable debug
+#include <cstdio>
+#define DBG(x, ...) pc.printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
+#define WARN(x, ...) pc.printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
+#define ERR(x, ...) pc.printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+#else
+//Disable debug
+#define DBG(x, ...) 
+#define WARN(x, ...)
+#define ERR(x, ...) 
+#endif
+
+
+
+
+HttpClient::HttpClient(const char * hostname)
+	: _hostname(hostname)
+{
+}
+
+int HttpClient::get(const char * url, char * buffer, size_t buf_len, HeaderInfo & hinfo, int timeout)
+{
+	char scheme[8];
+  uint16_t port;
+  char host[32];
+  char path[64];
+
+	_timeout = timeout;
+	
+  if(parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)))
+  {
+    ERR("Error parsing URL");
+    return -1;
+  }
+
+  if(port == 0) //TODO do handle HTTPS->443
+  {
+    port = 80;
+  }
+
+  DBG("Scheme: %s", scheme);
+  DBG("Host: %s", host);
+  DBG("Port: %d", port);
+  DBG("Path: %s", path);
+	
+	// Connect to server
+  int ret = m_sock.connect(host, port);
+  if (ret < 0)
+  {
+    m_sock.close();
+    ERR("Could not connect");
+    return -1;
+  }
+
+  //Send request
+	std::string req_header = build_http_headers("GET", (const char *) path);
+  ret = send((char *) req_header.c_str(), req_header.size());
+  if(ret)
+  {
+    m_sock.close();
+    ERR("Could not write request\r\n");
+    return -1;
+  }
+	// Process the response
+	// First get the header
+	DBG("Reading HTTP header ...\r\n");
+	char header_buf[512];
+	int header_line = 0, numread = 0;
+	
+	do {
+		memset(header_buf, 0, sizeof(header_buf));
+		numread = recv_until(header_buf, sizeof(header_buf), '\n');
+		// remove trailing \r\n
+		std::string line(header_buf, numread);
+		line = trim(line, " \t\r\n");
+		
+		DBG("Header line [%s]\r\n", line.c_str());
+		parse_headers(line, hinfo, header_line);
+		header_line++;
+	}while(numread > 2); // empty line for \r\n
+	
+	// Show the header information
+	DBG("Http response: %d\r\n", hinfo.http_response);
+	DBG("Http response text: %s\r\n", hinfo.http_response_text.c_str());
+	for(std::map<std::string, std::string>::iterator it = hinfo.http_info.begin();
+		it != hinfo.http_info.end();
+		it++)
+	{
+		DBG("Key [%s] : Value [%s]\r\n", it->first.c_str(), it->second.c_str());
+	}
+	
+	// Read the rest of the data based on content type
+	return read_data(hinfo, buffer, buf_len);
+	
+}
+
+int HttpClient::read_data(HeaderInfo & hinfo, char * buffer, size_t buf_len)
+{
+	int chunk_size = 0;
+	char tmp_buf[10]; // just for reading the \r\n values
+	char * buf_ptr = buffer;
+	int numread = 0;
+	
+	m_sock.set_blocking(false, _timeout);
+	if (hinfo.http_info["Transfer-Encoding"] == "chunked")
+	{
+		do {
+			// read the chunk size
+			DBG("Reading chunk size ...\r\n");
+			if ( m_sock.receive_until(tmp_buf, 10, '\n') > 0)
+			{
+				chunk_size = strtoul(tmp_buf, NULL, 16);
+				DBG("Chunk size: %d\r\n", chunk_size);
+			}else
+				break;
+
+			if (chunk_size > 0)
+			{
+				// read one char at a time untill chunk size
+				int cur_read2 = 0;
+				do {
+						if (m_sock.receive(buf_ptr,1) < 0)
+						{
+							DBG("Error reading chunks with total read [%d]...\r\n", numread);
+							return -1;
+						}
+						cur_read2 ++;
+						buf_ptr ++;
+				}while(cur_read2 < chunk_size);
+				DBG("Read %d chunk\r\n", cur_read2);
+			}
+	
+			numread += chunk_size;
+			DBG("Consuming new lines ...\r\n");
+			// Consume the next new line
+			m_sock.receive_until(tmp_buf, 10, '\n');
+			
+		}while((chunk_size > 0) && ((buf_ptr - buffer) < buf_len)); 
+		
+	}else
+	{
+			DBG("Reading complete data in one go ...\r\n");
+			numread = m_sock.receive_all(buffer, buf_len);
+	}
+	
+	DBG("Read %d bytes", numread);
+	
+	// Finally close the socket
+	m_sock.close();
+		
+	return numread;
+}
+
+int HttpClient::parse_headers(std::string header_line, HeaderInfo & hinfo, int lineno)
+{
+	std::vector<std::string> tokens;
+	// remove the trailing \n
+	
+	if (lineno == 0)
+	{
+		// Tokenize the first line using spaces
+		split(tokens, header_line, " ");
+		if (tokens.size() == 3)
+		{
+			//for(int i=0; i < tokens.size() ; i++)
+			//	pc.printf("Token[%d] = [%s]\r\n", i, tokens[i].c_str());
+			
+			// The second part is the http response
+			hinfo.http_response = atol(tokens[1].c_str());
+			DBG("HTTP response [%d]\r\n", hinfo.http_response);
+			hinfo.http_response_text = trim(tokens[2]);
+			DBG("HTTP text [%s]\r\n", hinfo.http_response_text.c_str());
+		}
+	}else
+	{
+		
+		// Scan for key value pairs
+		split(tokens, header_line, ":");
+		if (tokens.size() == 2)
+		{
+			//for(int i=0; i < tokens.size() ; i++)
+			//	pc.printf("Token[%d] = [%s]\r\n", i, tokens[i].c_str());
+			
+			std::string key = trim(tokens[0]);
+			std::string value = trim(tokens[1]);
+			
+			hinfo.http_info[key] = value;
+		}
+	}
+	
+	return 0;
+}
+
+std::string HttpClient::build_http_headers(std::string type, std::string path)
+{
+	std::string request_hdr = type + " " + path + " " + "HTTP/1.1" + "\r\n";
+	request_hdr += "Host:" + _hostname + "\r\n";
+	request_hdr += "\r\n"; // empty line terminates the header
+	
+	return request_hdr;
+	
+}
+
+int HttpClient::parse_url(const char* url, char* scheme, 
+	size_t scheme_len, 
+	char* host, 
+	size_t host_len, 
+	uint16_t* port, 
+	char* path, 
+	size_t path_len) //Parse URL
+{
+  char* schemePtr = (char*) url;
+  char* hostPtr = (char*) strstr(url, "://");
+  if(hostPtr == NULL)
+	{
+		ERR("Invalid URL [%s]\r\n", url);
+    return -1; //URL is invalid
+	}
+
+  if( scheme_len < hostPtr - schemePtr + 1 ) //including NULL-terminating char
+  {
+    ERR("Scheme str is too small (%d >= %d)\r\n", scheme_len, hostPtr - schemePtr + 1);
+    return -1;
+  }
+  memcpy(scheme, schemePtr, hostPtr - schemePtr);
+  scheme[hostPtr - schemePtr] = '\0';
+
+  hostPtr+=3;
+
+  size_t hostLen = 0;
+
+  char* portPtr = strchr(hostPtr, ':');
+  if( portPtr != NULL )
+  {
+    hostLen = portPtr - hostPtr;
+    portPtr++;
+    if( sscanf(portPtr, "%hu", port) != 1)
+    {
+      ERR("Could not find port\r\n");
+      return -1;
+    }
+  }
+  else
+  {
+    *port=0;
+  }
+  char* pathPtr = strchr(hostPtr, '/');
+  if( hostLen == 0 )
+  {
+    hostLen = pathPtr - hostPtr;
+  }
+
+  if( host_len < hostLen + 1 ) //including NULL-terminating char
+  {
+    ERR("Host str is too small (%d >= %d)\r\n", host_len, hostLen + 1);
+    return -1;
+  }
+  memcpy(host, hostPtr, hostLen);
+  host[hostLen] = '\0';
+
+  size_t pathLen;
+  char* fragmentPtr = strchr(hostPtr, '#');
+  if(fragmentPtr != NULL)
+  {
+    pathLen = fragmentPtr - pathPtr;
+  }
+  else
+  {
+    pathLen = strlen(pathPtr);
+  }
+
+  if( path_len < pathLen + 1 ) //including NULL-terminating char
+  {
+    ERR("Path str is too small (%d >= %d)\r\n", path_len, pathLen + 1);
+    return -1;
+  }
+  memcpy(path, pathPtr, pathLen);
+  path[pathLen] = '\0';
+
+  return 0;
+}
+
+int HttpClient::recv_until(char * buf, size_t len, char term)
+{
+	int numread = 0;
+  if(!m_sock.is_connected())
+  {
+    ERR("Connection was closed by server\r\n");
+    return -1; //Connection was closed by server 
+  }
+  
+  m_sock.set_blocking(false, _timeout);
+  int ret = m_sock.receive_until(buf, len, term);
+  if(ret > 0)
+  {
+    numread += ret;
+  }
+  else if( ret == 0 )
+  {
+    ERR("Connection was closed by server\r\n");
+    return -1; //Connection was closed by server
+  }
+  else
+  {
+    ERR("Connection error (recv returned %d)\r\n", ret);
+    return -1;
+  }
+  
+  DBG("Received %d bytes", numread);
+  return numread;	
+}
+
+int HttpClient::send(char* buf, size_t len) //0 on success, err code on failure
+{
+  if(len == 0)
+  {
+    len = strlen(buf);
+  }
+  //pc.printf("Trying to write %d bytes\r\n", len);
+  size_t writtenLen = 0;
+    
+  if(!m_sock.is_connected())
+  {
+    ERR("Connection was closed by server\r\n");
+    return -1; //Connection was closed by server 
+  }
+  
+  m_sock.set_blocking(false, _timeout);
+  int ret = m_sock.send_all(buf, len);
+  if(ret > 0)
+  {
+    writtenLen += ret;
+  }
+  else if( ret == 0 )
+  {
+    ERR("Connection was closed by server\r\n");
+    return -1; //Connection was closed by server
+  }
+  else
+  {
+    ERR("Connection error (send returned %d)\r\n", ret);
+    return -1;
+  }
+  
+  DBG("Written %d bytes\r\n", writtenLen);
+  return 0;
+}
+