Sans Pareil Technologies, Inc.

Key To Your Business

HttpRequest



The HttpRequest class encapsulates information that is to be sent to a HTTP server. Provides a means of encapsulating the server resource URI, request headers, request parameters etc.
HttpRequest.h 
Header file that defines the interface for a HTTP request object.
#ifndef SPT_NET_HTTPREQUEST_H
#define SPT_NET_HTTPREQUEST_H

#if defined( ARDUINO )
#include "../StandardCplusplus/map"
#include "../StandardCplusplus/string"
#else
#include <map>
#include <string>
#endif

namespace spt
{
  namespace net
  {
    /**
     * @brief A simple class that represents a HTTP request.  Request
     * encapsulates the URI path, any request parameters, header attributes,
     * body etc. as appropriate.
     */
    class HttpRequest
    {
    public:
      /// Map used to represent request parameters and headers.
      typedef std::map<std::string,std::string> Map;

      /// Constant iterator to access contents of the parameters and headers
      typedef Map::const_iterator Iterator;

      /// Constructor.  Create a request for the specified server resource
      HttpRequest( const std::string& uri );

      /// Destructor.  No actions required.
      ~HttpRequest() {}

      /// Return the uri for which this request was created.
      const std::string& getUri() const { return uri; }

      /// Return the body to send as part of the request.
      /// For GET requests, this will be empty.
      const std::string& getBody() const { return body; }

      /// Set the body to send as part of the request.  This is meant
      /// for use primarily with POST/PUT type requests.
      HttpRequest& setBody( const std::string& body );

      /// Add the specified key/value combination as a request parameter
      /// to this request.  If a mapping already exists with the specified
      /// key, it will be replaced with the specified value.
      HttpRequest& setParameter( const std::string& key, const std::string& value );

      /// Add the specified key/value combination as a request attribute
      /// to this request.  If a mapping already exists with the specified
      /// key, it will be replaced with the specified value.
      HttpRequest& setHeader( const std::string& key, const std::string& value );

      /// Return the requests parameters as a string.
      /// \b Note: A leading ? symbol will not be added, which is required
      /// for GET requests.  Calls must add if making a GET request.
      const std::string getParamters() const;

      /// Return a constant iterator to the beginning of the headers
      /// map.
      Iterator beginHeaders() const { return headers.begin(); }

      /// Return a constant iterator to the beginning of the headers
      /// map.
      Iterator endHeaders() const { return headers.end(); }

    private:
      void toHex( unsigned value, int width, std::string& output ) const;
      std::string encode( const std::string& value ) const;

    private:
      static const std::string ILLEGAL;

      const std::string uri;
      std::string body;
      Map parameters;
      Map headers;
    };

  } // namespace net
} // namespace spt

#endif // SPT_NET_HTTPREQUEST_H
HttpRequest.cpp 
Implementation of the HTTP request class.
#include "HttpRequest.h"

#if defined( ARDUINO )
#include "../StandardCplusplus/cstdio"
#include "../StandardCplusplus/sstream"
#else
#include <cstdio>
#include <sstream>
#endif

using std::string;
using spt::net::HttpRequest;

const std::string HttpRequest::ILLEGAL = "%<>{}|\\\"^`";

HttpRequest::HttpRequest( const std::string& path ) :
  uri( path ), body(), parameters(), headers() {}


HttpRequest& HttpRequest::setBody( const std::string& txt )
{
  body = txt;
  return *this;
}


HttpRequest& HttpRequest::setParameter( const std::string& key, const std::string& value )
{
  Map::iterator iter = parameters.find( key );
  if ( iter != parameters.end() ) parameters.erase( iter );
  parameters.insert( std::pair<std::string,std::string>( key, value ) );
  return *this;
}


HttpRequest& HttpRequest::setHeader( const std::string& key, const std::string& value )
{
  Map::iterator iter = headers.find( key );
  if ( iter != headers.end() ) headers.erase( iter );
  headers.insert( std::pair<std::string,std::string>( key, value ) );
  return *this;
}


const std::string HttpRequest::getParamters() const
{
  std::stringstream ss;

  bool first = true;
  for ( Iterator iter = parameters.begin(); iter != parameters.end(); ++iter )
  {
    if ( ! first ) ss << "&";
    ss << iter->first << "=" << encode( iter->second );
    first = false;
  }

  return ss.str();
}


void HttpRequest::toHex( unsigned value, int width, std::string& output ) const
{
  char buffer[64];
  std::sprintf( buffer, "%0*X", width, value );
  output.append( buffer );
}


std::string HttpRequest::encode( const std::string& str ) const
{
  std::string encodedStr;

  for ( std::string::const_iterator it = str.begin(); it != str.end(); ++it )
  {
    char c = *it;
    if ( ( c >= 'a' && c <= 'z' ) ||
        ( c >= 'A' && c <= 'Z' ) ||
        ( c >= '0' && c <= '9' ) ||
        c == '-' || c == '_' ||
        c == '.' || c == '~' )
    {
      encodedStr += c;
    }
    else if ( c <= 0x20 || c >= 0x7F ||
      ILLEGAL.find(c) != std::string::npos || '#' == c )
    {
      encodedStr += '%';
      toHex( (unsigned) (unsigned char) c, 2, encodedStr );
    }
    else encodedStr += c;
  }

  return encodedStr;
}
Instances of HttpRequest are created and used to perform actions provided via the HttpClient class.