Simple IoT Board用のHTTP GETサンプルです。

Dependencies:   SimpleIoTBoardLib mbed

Revision:
1:08ef13b0cb0e
Parent:
0:0ae1235453b0
--- a/HTTPClient/HTTPClient.cpp	Sun Nov 15 13:29:46 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,739 +0,0 @@
-/* HTTPClient.cpp */
-/* Copyright (C) 2012 mbed.org, MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//Debug is disabled by default
-#if 0
-//Enable debug
-#include <cstdio>
-#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
-#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
-#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
-
-#else
-//Disable debug
-#define DBG(x, ...) 
-#define WARN(x, ...)
-#define ERR(x, ...) 
-
-#endif
-
-#define HTTP_PORT 80
-
-#define OK 0
-
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#define MAX(x,y) (((x)>(y))?(x):(y))
-
-#define CHUNK_SIZE 256
-
-#include <cstring>
-
-#include "HTTPClient.h"
-
-
-HTTPClient::HTTPClient() :
-m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
-{
-
-}
-
-HTTPClient::~HTTPClient()
-{
-
-}
-
-#if 0
-void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
-{
-  m_basicAuthUser = user;
-  m_basicAuthPassword = password;
-}
-#endif
-
-HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
-{
-  return connect(url, HTTP_GET, NULL, pDataIn, timeout);
-}
-
-HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
-{
-  HTTPText str(result, maxResultLen);
-  return get(url, &str, timeout);
-}
-
-HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
-{
-  return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
-}
-
-HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
-{
-  return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
-}
-
-HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
-{
-  return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
-}
-
-
-int HTTPClient::getHTTPResponseCode()
-{
-  return m_httpResponseCode;
-}
-
-#define CHECK_CONN_ERR(ret) \
-  do{ \
-    if(ret) { \
-      m_sock.close(); \
-      ERR("Connection error (%d)", ret); \
-      return HTTP_CONN; \
-    } \
-  } while(0)
-
-#define PRTCL_ERR() \
-  do{ \
-    m_sock.close(); \
-    ERR("Protocol error"); \
-    return HTTP_PRTCL; \
-  } while(0)
-
-HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
-{ 
-  m_httpResponseCode = 0; //Invalidate code
-  m_timeout = timeout;
-  
-  pDataIn->writeReset();
-  if( pDataOut )
-  {
-    pDataOut->readReset();
-  }
-
-  char scheme[8];
-  uint16_t port;
-  char host[32];
-  char path[64];
-  //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
-  HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
-  if(res != HTTP_OK)
-  {
-    ERR("parseURL returned %d", res);
-    return res;
-  }
-
-  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
-  DBG("Connecting socket to server");
-  int ret = m_sock.connect(host, port);
-  if (ret < 0)
-  {
-    m_sock.close();
-    ERR("Could not connect");
-    return HTTP_CONN;
-  }
-  //Send request
-  DBG("Sending request");
-  char buf[CHUNK_SIZE];
-  const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
-  snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
-  ret = send(buf);
-  if(ret)
-  {
-    m_sock.close();
-    ERR("Could not write request");
-    return HTTP_CONN;
-  }
-
-  //Send all headers
-
-  //Send default headers
-  DBG("Sending headers");
-  if( pDataOut != NULL )
-  {
-    if( pDataOut->getIsChunked() )
-    {
-      ret = send("Transfer-Encoding: chunked\r\n");
-      CHECK_CONN_ERR(ret);
-    }
-    else
-    {
-      snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
-      ret = send(buf);
-      CHECK_CONN_ERR(ret);
-    }
-    char type[48];
-    if( pDataOut->getDataType(type, 48) == HTTP_OK )
-    {
-      snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
-      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
-  DBG("Headers sent");
-  ret = send("\r\n");
-  CHECK_CONN_ERR(ret);
-
-  size_t trfLen;
-  
-  //Send data (if available)
-  if( pDataOut != NULL )
-  {
-    DBG("Sending data");
-    while(true)
-    {
-      size_t writtenLen = 0;
-      pDataOut->read(buf, CHUNK_SIZE, &trfLen);
-      if( pDataOut->getIsChunked() )
-      {
-        //Write chunk header
-        char chunkHeader[16];
-        snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
-        ret = send(chunkHeader);
-        CHECK_CONN_ERR(ret);
-      }
-      else if( trfLen == 0 )
-      {
-        break;
-      }
-      if( trfLen != 0 )
-      {
-        ret = send(buf, trfLen);
-        CHECK_CONN_ERR(ret);
-      }
-
-      if( pDataOut->getIsChunked()  )
-      {
-        ret = send("\r\n"); //Chunk-terminating CRLF
-        CHECK_CONN_ERR(ret);
-      }
-      else
-      {
-        writtenLen += trfLen;
-        if( writtenLen >= pDataOut->getDataLen() )
-        {
-          break;
-        }
-      }
-
-      if( trfLen == 0 )
-      {
-        break;
-      }
-    }
-  }
-  
-  //Receive response
-  DBG("Receiving response");
-  ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
-  CHECK_CONN_ERR(ret);
-
-  buf[trfLen] = '\0';
-
-  //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(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);
-    PRTCL_ERR();
-  }
-
-  if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) )
-  {
-    //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 
-    WARN("Response code %d", m_httpResponseCode);
-    PRTCL_ERR();
-  }
-
-  DBG("Reading headers");
-
-  memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
-  trfLen -= (crlfPos + 2);
-
-  size_t recvContentLength = 0;
-  bool recvChunked = false;
-  bool recvLengthUnknown = true;
-  //Now get headers
-  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();
-      }
-    }
-
-    crlfPos = crlfPtr - buf;
-
-    if(crlfPos == 0) //End of headers
-    {
-      DBG("Headers read");
-      memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
-      trfLen -= 2;
-      break;
-    }
-
-    buf[crlfPos] = '\0';
-
-    char key[32];
-    char value[32];
-
-    //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 = 0;
-    
-    char* keyEnd = strchr(buf, ':');
-    if(keyEnd != NULL)
-    {
-      *keyEnd = '\0';
-      if(strlen(buf) < 32)
-      {
-        strcpy(key, buf);
-        n++;
-        char* valueStart = keyEnd + 2;
-        if( (valueStart - buf) < crlfPos )
-        {
-          if(strlen(valueStart) < 32)
-          { 
-            strcpy(value, valueStart);
-            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") )
-      {
-        if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") )
-        {
-          recvChunked = true;
-          recvLengthUnknown = false;
-          pDataIn->setIsChunked(true);
-        }
-      }
-      else if( !strcmp(key, "Content-Type") )
-      {
-        pDataIn->setDataType(value);
-      }
-
-      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
-      trfLen -= (crlfPos + 2);
-
-    }
-    else
-    {
-      ERR("Could not parse header");
-      PRTCL_ERR();
-    }
-
-  }
-
-  //Receive data
-  DBG("Receiving data");
-  while(true)
-  {
-    size_t readLen = 0;
-
-    if( recvChunked )
-    {
-      //Read chunk header
-      bool foundCrlf;
-      do
-      {
-        foundCrlf = false;
-        crlfPos=0;
-        buf[trfLen]=0;
-        if(trfLen >= 2)
-        {
-          for(; crlfPos < trfLen - 2; crlfPos++)
-          {
-            if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' )
-            {
-              foundCrlf = true;
-              break;
-            }
-          }
-        }
-        if(!foundCrlf) //Try to read more
-        {
-          if( trfLen < CHUNK_SIZE )
-          {
-            size_t newTrfLen;
-            ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
-            trfLen += newTrfLen;
-            CHECK_CONN_ERR(ret);
-            continue;
-          }
-          else
-          {
-            PRTCL_ERR();
-          }
-        }
-      } while(!foundCrlf);
-      buf[crlfPos] = '\0';
-      int n = sscanf(buf, "%x", &readLen);
-      if(n!=1)
-      {
-        ERR("Could not read chunk length");
-        PRTCL_ERR();
-      }
-
-      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
-      trfLen -= (crlfPos + 2);
-
-      if( readLen == 0 )
-      {
-        //Last chunk
-        break;
-      }
-    }
-    else
-    {
-      readLen = recvContentLength;
-    }
-
-    DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen);
-
-    do
-    {
-      if(recvLengthUnknown )
-      {
-        readLen = trfLen;
-      }
-      pDataIn->write(buf, MIN(trfLen, readLen));
-      if(!recvLengthUnknown)
-      {
-        if( trfLen > readLen )
-        {
-          memmove(buf, &buf[readLen], trfLen - readLen);
-          trfLen -= readLen;
-          readLen = 0;
-        }
-        else
-        {
-          readLen -= trfLen;
-        }
-      }
-      else
-      {
-        trfLen = 0;
-      }
-
-      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 || recvLengthUnknown);
-
-    if( recvChunked )
-    {
-      if(trfLen < 2)
-      {
-        size_t newTrfLen;
-        //Read missing chars to find end of chunk
-        ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
-        CHECK_CONN_ERR(ret);
-        trfLen += newTrfLen;
-      }
-      if( (buf[0] != '\r') || (buf[1] != '\n') )
-      {
-        ERR("Format error");
-        PRTCL_ERR();
-      }
-      memmove(buf, &buf[2], trfLen - 2);
-      trfLen -= 2;
-    }
-    else
-    {
-      break;
-    }
-
-  }
-
-  m_sock.close();
-  DBG("Completed HTTP transaction");
-
-  return HTTP_OK;
-}
-
-HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
-{
-  DBG("Trying to read between %d and %d bytes", minLen, maxLen);
-  size_t readLen = 0;
-      
-  if(!m_sock.is_connected())
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server 
-  }
-    
-  int ret;
-  while(readLen < maxLen)
-  {
-    if(readLen < minLen)
-    {
-      DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen);
-      m_sock.set_blocking(false, m_timeout);
-      ret = m_sock.receive_all(buf + readLen, minLen - readLen);
-    }
-    else
-    {
-      DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen);
-      m_sock.set_blocking(false, 0);
-      ret = m_sock.receive(buf + readLen, maxLen - readLen);
-    }
-    
-    if( ret > 0)
-    {
-      readLen += ret;
-    }
-    else if( ret == 0 )
-    {
-      break;
-    }
-    else
-    {
-      if(!m_sock.is_connected())
-      {
-        ERR("Connection error (recv returned %d)", ret);
-        *pReadLen = readLen;
-        return HTTP_CONN;
-      }
-      else
-      {
-        break;      
-      }
-    }
-    
-    if(!m_sock.is_connected())
-    {
-      break;
-    }
-  }
-  DBG("Read %d bytes", readLen);
-  *pReadLen = readLen;
-  return HTTP_OK;
-}
-
-HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
-{
-  if(len == 0)
-  {
-    len = strlen(buf);
-  }
-  DBG("Trying to write %d bytes", len);
-  size_t writtenLen = 0;
-    
-  if(!m_sock.is_connected())
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server 
-  }
-  
-  m_sock.set_blocking(false, m_timeout);
-  int ret = m_sock.send_all(buf, len);
-  if(ret > 0)
-  {
-    writtenLen += ret;
-  }
-  else if( ret == 0 )
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server
-  }
-  else
-  {
-    ERR("Connection error (send returned %d)", ret);
-    return HTTP_CONN;
-  }
-  
-  DBG("Written %d bytes", writtenLen);
-  return HTTP_OK;
-}
-
-HTTPResult HTTPClient::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
-{
-  char* schemePtr = (char*) url;
-  char* hostPtr = (char*) strstr(url, "://");
-  if(hostPtr == NULL)
-  {
-    WARN("Could not find host");
-    return HTTP_PARSE; //URL is invalid
-  }
-
-  if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
-  {
-    WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
-    return HTTP_PARSE;
-  }
-  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)
-    {
-      WARN("Could not find port");
-      return HTTP_PARSE;
-    }
-  }
-  else
-  {
-    *port=0;
-  }
-  char* pathPtr = strchr(hostPtr, '/');
-  if( hostLen == 0 )
-  {
-    hostLen = pathPtr - hostPtr;
-  }
-
-  if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
-  {
-    WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
-    return HTTP_PARSE;
-  }
-  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( maxPathLen < pathLen + 1 ) //including NULL-terminating char
-  {
-    WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
-    return HTTP_PARSE;
-  }
-  memcpy(path, pathPtr, pathLen);
-  path[pathLen] = '\0';
-  
-  return HTTP_OK;
-}