GDP group 24 node core

Dependencies:   EthernetInterface SDFileSystem mbed-rtos mbed snail MbedJSONValue

http.cpp

Committer:
jakehodges
Date:
2015-01-27
Revision:
23:b57a47c7862a
Parent:
12:daddfc44a0f5
Child:
27:61e67ab47da5

File content as of revision 23:b57a47c7862a:

#include "mbed.h"
#include "http.h"
#include <string>
#include <vector>

void http::connect()
{
    #ifdef DEBUG
        printf("[HTTP] Ethernet connecting...\r\n");
    #endif
    
    eth.init();
    eth.connect();
    
    #ifdef DEBUG
        printf("[HTTP] Ethernet connected, IP: %s\r\n", eth.getIPAddress());
    #endif
}

string http::get(string address, int port, string url, int replyTimeout)
{
    #ifdef DEBUG
        printf("[HTTP] Sending GET request to %s:%i%s\r\n", address.c_str(), port, url.c_str());
    #endif
    
    TCPSocketConnection sock;
    sock.connect(address.c_str(), port);
    
    #ifdef DEBUG
        printf("[HTTP] Connected to endpoint...\r\n");
    #endif
    
    string httpget = "GET " + url + " HTTP/1.1";
    httpget += "\nHost: " + address + "\n\n";
    
    //get a writable char* (I.E. not const char* returned by c_str), put it into a vector 
    vector<char> writable(httpget.begin(), httpget.end());
    writable.push_back('\0');
    
    sock.send_all(&writable[0], writable.size()-1);
    
    string message = this->receiveFromSock(sock, replyTimeout);
      
    sock.close();
    
    return this->parse(message);
}

string http::post(string address, int port, string url, string jsonPayload, int replyTimeout)
{   
    #ifdef DEBUG
        printf("[HTTP] Sending POST request to %s:%i%s\r\n", address.c_str(), port, url.c_str());
    #endif
    
    TCPSocketConnection sock;
    sock.connect(address.c_str(), port);
    
    #ifdef DEBUG
        printf("[HTTP] Connected to endpoint...\r\n");
    #endif
    
    char buffer[20];
    sprintf(buffer, "%i", jsonPayload.size());
    string contentLengthStr = string(buffer);
    
    string httppost = "POST " + url + " HTTP/1.1";
    httppost += "\nHost: " + address;
    httppost += "\nContent-Type: application/json";
    httppost += "\nContent-Length: " + contentLengthStr;
    httppost += "\nAuthorization: Key 1";
    httppost += "\n\n" + jsonPayload;
    
    //to get a writable char* (I.E. not const char* returned by string.c_str), put it into a vector 
    vector<char> writable(httppost.begin(), httppost.end());
    writable.push_back('\0');
    
    sock.send_all(&writable[0], writable.size()-1);
    
    string message = this->receiveFromSock(sock, replyTimeout);
    
    sock.close();
    
    return this->parse(message);
}

string http::receiveFromSock(TCPSocketConnection sock, int replyTimeout)
{
    char buffer[1024];
    int receiveByteCount;
    string message;
    
    bool headersSet = false;
    int contentLength = -1;
    string responseBody;
    
    string contentLengthNeedle = "Content-Length: ";
    
    while (true)
    {
        receiveByteCount = sock.receive(buffer, sizeof(buffer)-1);//spare a byte for null termination byte
        
        //if the connection is closed by the remote client
        if (receiveByteCount <= 0)
            break;
            
        buffer[receiveByteCount] = '\0';
        message += buffer;
        
        //if the response header has been received and includes the required headers
        if (!headersSet && message.find("\r\n\r\n") != string::npos && message.find(contentLengthNeedle) != string::npos)
        {
            //headers have been fully received, ensure this check is not performed again
            headersSet = true;
            //end point of the "Content-Length: " string, beginning of the integer it specifies
            int cl = message.find(contentLengthNeedle) + contentLengthNeedle.size();
            //extract the content length from the header
            string length = message.substr(cl, message.find_first_of("\r\n", cl) - cl);
            contentLength = atoi(length.c_str());
        }
        
        //if the headers have been set, extract the message body
        if (headersSet)
            responseBody = message.substr(message.find("\r\n\r\n"), contentLength);
        
        //if the response body is of the expected length, we're done
        if (responseBody.size() >= contentLength)
            break;
    }
    
    return message;
}

string http::parse(string httpReply)
{
    int payloadBegin = httpReply.find("\r\n\r\n");
    if (payloadBegin > -1)
    {
        string payload(httpReply.begin() + payloadBegin + 4, httpReply.end());
        
        return payload;
    }
    else
    {
        return "";
    }
}