Logo
~Sockets~
~Examples~
~Contact~


HttpPostSocket Class Reference
[HTTP Sockets]

Generate a http post request, get response. More...

#include <HttpPostSocket.h>

Inheritance diagram for HttpPostSocket:
Collaboration diagram for HttpPostSocket:

List of all members.


Public Member Functions

 HttpPostSocket (ISocketHandler &)
 HttpPostSocket (ISocketHandler &, const std::string &url_in)
 ~HttpPostSocket ()
void AddField (const std::string &name, const std::string &value)
 Add field to post.
void AddMultilineField (const std::string &name, std::list< std::string > &values)
 Add multiline field to post.
void AddFile (const std::string &name, const std::string &filename, const std::string &type)
 Add file to post.
void SetMultipart ()
 use this to post with content-type multipart/form-data.
void Open ()
 connect to host:port derived from url in constructor
void OnConnect ()
 http put client implemented in OnConnect

Protected Attributes

std::map< std::string,
std::list< std::string > > 
m_fields

Private Member Functions

 HttpPostSocket (const HttpPostSocket &s)
HttpPostSocketoperator= (const HttpPostSocket &)
void DoMultipartPost ()

Private Attributes

std::map< std::string,
std::string > 
m_files
std::string m_boundary
std::map< std::string, long > m_content_length
 Content-length header received from remote.
std::map< std::string,
std::string > 
m_content_type
 Content-type: header from response.
bool m_bMultipart

Static Private Attributes

static int m_boundary_count = 0
static Mutex m_boundary_mutex

Detailed Description

Generate a http post request, get response.

Definition at line 48 of file HttpPostSocket.h.


Constructor & Destructor Documentation

HttpPostSocket::HttpPostSocket ( ISocketHandler h  ) 

Definition at line 59 of file HttpPostSocket.cpp.

00059                                                 : HttpClientSocket(h)
00060 ,m_bMultipart(false)
00061 {
00062 }

HttpPostSocket::HttpPostSocket ( ISocketHandler h,
const std::string &  url_in 
)

Definition at line 65 of file HttpPostSocket.cpp.

References Utility::l2string(), m_boundary, m_boundary_count, and m_boundary_mutex.

00065                                                                         : HttpClientSocket(h, url_in)
00066 ,m_bMultipart(false)
00067 {
00068         Lock lock(m_boundary_mutex);
00069 
00070         m_boundary = "----";
00071         for (int i = 0; i < 12; i++)
00072         {
00073                 char c = m_boundary_count++ % 128;
00074                 while (!isalnum(c))
00075                         c = m_boundary_count++ % 128;
00076                 m_boundary += c;
00077         }
00078         m_boundary += "__" + Utility::l2string(m_boundary_count++);
00079 }

HttpPostSocket::~HttpPostSocket (  ) 

Definition at line 82 of file HttpPostSocket.cpp.

00083 {
00084 }

HttpPostSocket::HttpPostSocket ( const HttpPostSocket s  )  [inline, private]

Definition at line 79 of file HttpPostSocket.h.

00079 : HttpClientSocket(s) {} // copy constructor


Member Function Documentation

void HttpPostSocket::AddField ( const std::string &  name,
const std::string &  value 
)

Add field to post.

Definition at line 87 of file HttpPostSocket.cpp.

References AddMultilineField().

00088 {
00089         std::list<std::string> vec;
00090         vec.push_back(value);
00091         AddMultilineField(name, vec);
00092 }

void HttpPostSocket::AddMultilineField ( const std::string &  name,
std::list< std::string > &  values 
)

Add multiline field to post.

Definition at line 95 of file HttpPostSocket.cpp.

References m_fields.

Referenced by AddField().

00096 {
00097         m_fields[name] = values;
00098 }

void HttpPostSocket::AddFile ( const std::string &  name,
const std::string &  filename,
const std::string &  type 
)

Add file to post.

Definition at line 101 of file HttpPostSocket.cpp.

References Errno, Socket::Handler(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_bMultipart, m_content_length, m_content_type, m_files, Socket::SetCloseAndDelete(), and StrError.

00102 {
00103         struct stat st;
00104         if (!stat(filename.c_str(), &st))
00105         {
00106                 m_files[name] = filename;
00107                 m_content_length[filename] = st.st_size;
00108                 m_content_type[filename] = type;
00109                 m_bMultipart = true;
00110         }
00111         else
00112         {
00113                 Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00114                 SetCloseAndDelete();
00115         }
00116 }

void HttpPostSocket::SetMultipart (  ) 

use this to post with content-type multipart/form-data.

when adding a file to the post, this is the default and only content-type

Definition at line 285 of file HttpPostSocket.cpp.

References m_bMultipart.

00286 {
00287         m_bMultipart = true;
00288 }

void HttpPostSocket::Open (  ) 

connect to host:port derived from url in constructor

Definition at line 119 of file HttpPostSocket.cpp.

References HttpClientSocket::GetUrlHost(), HttpClientSocket::GetUrlPort(), and TcpSocket::Open().

00120 {
00121         // why do I have to specify TcpSocket:: to get to the Open() method??
00122         TcpSocket::Open(GetUrlHost(), GetUrlPort());
00123 }

void HttpPostSocket::OnConnect (  )  [virtual]

http put client implemented in OnConnect

Reimplemented from Socket.

Definition at line 126 of file HttpPostSocket.cpp.

References HTTPSocket::AddResponseHeader(), DoMultipartPost(), HttpClientSocket::GetUrlHost(), Utility::l2string(), m_bMultipart, m_fields, HTTPSocket::MyUseragent(), Utility::rfc1738_encode(), TcpSocket::Send(), HTTPSocket::SendRequest(), HTTPSocket::SetHttpVersion(), and HTTPSocket::SetMethod().

00127 {
00128         if (m_bMultipart)
00129         {
00130                 DoMultipartPost();
00131         }
00132         else
00133         {
00134                 std::string body;
00135 
00136                 // only fields, no files, add urlencoding
00137                 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
00138                 {
00139                         std::string name = (*it).first;
00140                         std::list<std::string>& ref = (*it).second;
00141                         if (body.size())
00142                         {
00143                                 body += '&';
00144                         }
00145                         body += name + "=";
00146                         bool first = true;
00147                         for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
00148                         {
00149                                 std::string value = *it;
00150                                 if (!first)
00151                                 {
00152                                         body += "%0d%0a"; // CRLF
00153                                 }
00154                                 body += Utility::rfc1738_encode(value);
00155                                 first = false;
00156                         }
00157                 }
00158 
00159                 // build header, send body
00160                 SetMethod("POST");
00161                 SetHttpVersion( "HTTP/1.1" );
00162                 AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
00163                 AddResponseHeader( "User-agent", MyUseragent());
00164                 AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00165                 AddResponseHeader( "Connection", "close" );
00166                 AddResponseHeader( "Content-type", "application/x-www-form-urlencoded" );
00167                 AddResponseHeader( "Content-length", Utility::l2string((long)body.size()) );
00168                 SendRequest();
00169 
00170                 // send body
00171                 Send( body );
00172         }
00173 }

HttpPostSocket& HttpPostSocket::operator= ( const HttpPostSocket  )  [inline, private]

Definition at line 80 of file HttpPostSocket.h.

00080 { return *this; } // assignment operator

void HttpPostSocket::DoMultipartPost (  )  [private]

Definition at line 176 of file HttpPostSocket.cpp.

References HTTPSocket::AddResponseHeader(), HttpClientSocket::GetUrlHost(), Utility::l2string(), m_boundary, m_content_length, m_content_type, m_fields, m_files, HTTPSocket::MyUseragent(), TcpSocket::Send(), TcpSocket::SendBuf(), HTTPSocket::SendRequest(), HTTPSocket::SetHttpVersion(), and HTTPSocket::SetMethod().

Referenced by OnConnect().

00177 {
00178         long length = 0; // calculate content_length of our post body
00179         std::string tmp;
00180 
00181         // fields
00182         {
00183                 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
00184                 {
00185                         std::string name = (*it).first;
00186                         std::list<std::string>& ref = (*it).second;
00187                         tmp = "--" + m_boundary + "\r\n"
00188                                 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00189                                 "\r\n";
00190                         for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
00191                         {
00192                                 std::string value = *it;
00193                                 tmp += value + "\r\n";
00194                         }
00195                         length += (long)tmp.size();
00196                 }
00197         }
00198 
00199         // files
00200         {
00201                 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); ++it)
00202                 {
00203                         std::string name = (*it).first;
00204                         std::string filename = (*it).second;
00205                         long content_length = m_content_length[filename];
00206                         std::string content_type = m_content_type[filename];
00207                         tmp = "--" + m_boundary + "\r\n"
00208                                 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00209                                 "content-type: " + content_type + "\r\n"
00210                                 "\r\n";
00211                         length += (long)tmp.size();
00212                         length += content_length;
00213                         length += 2; // crlf after file
00214                 }
00215         }
00216 
00217         // end
00218         tmp = "--" + m_boundary + "--\r\n";
00219         length += (long)tmp.size();
00220 
00221         // build header, send body
00222         SetMethod("POST");
00223         SetHttpVersion( "HTTP/1.1" );
00224         AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
00225         AddResponseHeader( "User-agent", MyUseragent());
00226         AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00227         AddResponseHeader( "Connection", "close" );
00228         AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary );
00229         AddResponseHeader( "Content-length", Utility::l2string(length) );
00230 
00231         SendRequest();
00232 
00233         // send fields
00234         {
00235                 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
00236                 {
00237                         std::string name = (*it).first;
00238                         std::list<std::string>& ref = (*it).second;
00239                         tmp = "--" + m_boundary + "\r\n"
00240                                 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00241                                 "\r\n";
00242                         for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
00243                         {
00244                                 std::string value = *it;
00245                                 tmp += value + "\r\n";
00246                         }
00247                         Send( tmp );
00248                 }
00249         }
00250 
00251         // send files
00252         {
00253                 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); ++it)
00254                 {
00255                         std::string name = (*it).first;
00256                         std::string filename = (*it).second;
00257                         std::string content_type = m_content_type[filename];
00258                         tmp = "--" + m_boundary + "\r\n"
00259                                 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00260                                 "content-type: " + content_type + "\r\n"
00261                                 "\r\n";
00262                         Send( tmp );
00263                         {
00264                                 std::auto_ptr<IFile> fil = std::auto_ptr<IFile>(new File);
00265                                 if (fil -> fopen(filename, "rb"))
00266                                 {
00267                                         char slask[2000]; // for fread
00268                                         size_t n;
00269                                         while ((n = fil -> fread(slask, 1, 2000)) > 0)
00270                                         {
00271                                                 SendBuf(slask, n);
00272                                         }
00273                                         fil -> fclose();
00274                                 }
00275                         }
00276                         Send("\r\n");
00277                 }
00278         }
00279 
00280         // end of send
00281         Send("--" + m_boundary + "--\r\n");
00282 }


Member Data Documentation

std::map<std::string,std::list<std::string> > HttpPostSocket::m_fields [protected]

Definition at line 76 of file HttpPostSocket.h.

Referenced by AddMultilineField(), DoMultipartPost(), and OnConnect().

std::map<std::string,std::string> HttpPostSocket::m_files [private]

Definition at line 83 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

std::string HttpPostSocket::m_boundary [private]

Definition at line 84 of file HttpPostSocket.h.

Referenced by DoMultipartPost(), and HttpPostSocket().

std::map<std::string,long> HttpPostSocket::m_content_length [private]

Content-length header received from remote.

Reimplemented from HttpClientSocket.

Definition at line 85 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

std::map<std::string,std::string> HttpPostSocket::m_content_type [private]

Content-type: header from response.

Reimplemented from HttpClientSocket.

Definition at line 86 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

Definition at line 87 of file HttpPostSocket.h.

Referenced by AddFile(), OnConnect(), and SetMultipart().

int HttpPostSocket::m_boundary_count = 0 [static, private]

Definition at line 88 of file HttpPostSocket.h.

Referenced by HttpPostSocket().

Definition at line 89 of file HttpPostSocket.h.

Referenced by HttpPostSocket().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4