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.

    1: #ifndef SPT_NET_HTTPREQUEST_H
    2: #define SPT_NET_HTTPREQUEST_H
    3:
    4: #if defined( ARDUINO )
    5: #include "../StandardCplusplus/map"
    6: #include "../StandardCplusplus/string"
    7: #else
    8: #include <map>
    9: #include <string>
   10: #endif
   11:
   12: namespace spt
   13: {
   14:   namespace net
   15:   {
   16:     /**
   17:      * @brief A simple class that represents a HTTP request.  Request
   18:      * encapsulates the URI path, any request parameters, header attributes,
   19:      * body etc. as appropriate.
   20:      */
   21:     class HttpRequest
   22:     {
   23:     public:
   24:       /// Map used to represent request parameters and headers.
   25:       typedef std::map<std::string,std::string> Map;
   26:
   27:       /// Constant iterator to access contents of the parameters and headers
   28:       typedef Map::const_iterator Iterator;
   29:
   30:       /// Constructor.  Create a request for the specified server resource
   31:       HttpRequest( const std::string& uri );
   32:
   33:       /// Destructor.  No actions required.
   34:       ~HttpRequest() {}
   35:
   36:       /// Return the uri for which this request was created.
   37:       const std::string& getUri() const { return uri; }
   38:
   39:       /// Return the body to send as part of the request.
   40:       /// For GET requests, this will be empty.
   41:       const std::string& getBody() const { return body; }
   42:
   43:       /// Set the body to send as part of the request.  This is meant
   44:       /// for use primarily with POST/PUT type requests.
   45:       HttpRequest& setBody( const std::string& body );
   46:
   47:       /// Add the specified key/value combination as a request parameter
   48:       /// to this request.  If a mapping already exists with the specified
   49:       /// key, it will be replaced with the specified value.
   50:       HttpRequest& setParameter( const std::string& key, const std::string& value );
   51:
   52:       /// Add the specified key/value combination as a request attribute
   53:       /// to this request.  If a mapping already exists with the specified
   54:       /// key, it will be replaced with the specified value.
   55:       HttpRequest& setHeader( const std::string& key, const std::string& value );
   56:
   57:       /// Return the requests parameters as a string.
   58:       /// \b Note: A leading ? symbol will not be added, which is required
   59:       /// for GET requests.  Calls must add if making a GET request.
   60:       const std::string getParamters() const;
   61:
   62:       /// Return a constant iterator to the beginning of the headers
   63:       /// map.
   64:       Iterator beginHeaders() const { return headers.begin(); }
   65:
   66:       /// Return a constant iterator to the beginning of the headers
   67:       /// map.
   68:       Iterator endHeaders() const { return headers.end(); }
   69:
   70:     private:
   71:       void toHex( unsigned value, int width, std::string& output ) const;
   72:       std::string encode( const std::string& value ) const;
   73:
   74:     private:
   75:       static const std::string ILLEGAL;
   76:
   77:       const std::string uri;
   78:       std::string body;
   79:       Map parameters;
   80:       Map headers;
   81:     };
   82:
   83:   } // namespace net
   84: } // namespace spt
   85:
   86: #endif // SPT_NET_HTTPREQUEST_H



HttpRequest.cpp

Implementation of the HTTP request class.

    1: #include "HttpRequest.h"
    2:
    3: #if defined( ARDUINO )
    4: #include "../StandardCplusplus/cstdio"
    5: #include "../StandardCplusplus/sstream"
    6: #else
    7: #include <cstdio>
    8: #include <sstream>
    9: #endif
   10:
   11: using std::string;
   12: using spt::net::HttpRequest;
   13:
   14: const std::string HttpRequest::ILLEGAL = "%<>{}|\\\"^`";
   15:
   16: HttpRequest::HttpRequest( const std::string& path ) :
   17:   uri( path ), body(), parameters(), headers() {}
   18:
   19:
   20: HttpRequest& HttpRequest::setBody( const std::string& txt )
   21: {
   22:   body = txt;
   23:   return *this;
   24: }
   25:
   26:
   27: HttpRequest& HttpRequest::setParameter( const std::string& key, const std::string& value )
   28: {
   29:   Map::iterator iter = parameters.find( key );
   30:   if ( iter != parameters.end() ) parameters.erase( iter );
   31:   parameters.insert( std::pair<std::string,std::string>( key, value ) );
   32:   return *this;
   33: }
   34:
   35:
   36: HttpRequest& HttpRequest::setHeader( const std::string& key, const std::string& value )
   37: {
   38:   Map::iterator iter = headers.find( key );
   39:   if ( iter != headers.end() ) headers.erase( iter );
   40:   headers.insert( std::pair<std::string,std::string>( key, value ) );
   41:   return *this;
   42: }
   43:
   44:
   45: const std::string HttpRequest::getParamters() const
   46: {
   47:   std::stringstream ss;
   48:
   49:   bool first = true;
   50:   for ( Iterator iter = parameters.begin(); iter != parameters.end(); ++iter )
   51:   {
   52:     if ( ! first ) ss << "&";
   53:     ss << iter->first << "=" << encode( iter->second );
   54:     first = false;
   55:   }
   56:
   57:   return ss.str();
   58: }
   59:
   60:
   61: void HttpRequest::toHex( unsigned value, int width, std::string& output ) const
   62: {
   63:   char buffer[64];
   64:   std::sprintf( buffer, "%0*X", width, value );
   65:   output.append( buffer );
   66: }
   67:
   68:
   69: std::string HttpRequest::encode( const std::string& str ) const
   70: {
   71:   std::string encodedStr;
   72:
   73:   for ( std::string::const_iterator it = str.begin(); it != str.end(); ++it )
   74:   {
   75:     char c = *it;
   76:     if ( ( c >= 'a' && c <= 'z' ) ||
   77:         ( c >= 'A' && c <= 'Z' ) ||
   78:         ( c >= '0' && c <= '9' ) ||
   79:         c == '-' || c == '_' ||
   80:         c == '.' || c == '~' )
   81:     {
   82:       encodedStr += c;
   83:     }
   84:     else if ( c <= 0x20 || c >= 0x7F ||
   85:       ILLEGAL.find(c) != std::string::npos || '#' == c )
   86:     {
   87:       encodedStr += '%';
   88:       toHex( (unsigned) (unsigned char) c, 2, encodedStr );
   89:     }
   90:     else encodedStr += c;
   91:   }
   92:
   93:   return encodedStr;
   94: }