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

Private Member Functions

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

Private Attributes

std::map< std::string,
std::list< std::string > > 
m_fields
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 46 of file HttpPostSocket.h.


Constructor & Destructor Documentation

HttpPostSocket::HttpPostSocket ( ISocketHandler h  ) 

Definition at line 57 of file HttpPostSocket.cpp.

00057                                                 : HttpClientSocket(h)
00058 ,m_bMultipart(false)
00059 {
00060 }

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

Definition at line 63 of file HttpPostSocket.cpp.

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

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

HttpPostSocket::~HttpPostSocket (  ) 

Definition at line 80 of file HttpPostSocket.cpp.

00081 {
00082 }

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

Definition at line 74 of file HttpPostSocket.h.

00074 : 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 85 of file HttpPostSocket.cpp.

References AddMultilineField().

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

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

Add multiline field to post.

Definition at line 93 of file HttpPostSocket.cpp.

References m_fields.

Referenced by AddField().

00094 {
00095         m_fields[name] = values;
00096 }

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

Add file to post.

Definition at line 99 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.

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

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 283 of file HttpPostSocket.cpp.

References m_bMultipart.

00284 {
00285         m_bMultipart = true;
00286 }

void HttpPostSocket::Open (  ) 

connect to host:port derived from url in constructor

Definition at line 117 of file HttpPostSocket.cpp.

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

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

void HttpPostSocket::OnConnect (  )  [virtual]

http put client implemented in OnConnect

Reimplemented from Socket.

Definition at line 124 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().

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

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

Definition at line 75 of file HttpPostSocket.h.

00075 { return *this; } // assignment operator

void HttpPostSocket::DoMultipartPost (  )  [private]

Definition at line 174 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().

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


Member Data Documentation

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

Definition at line 78 of file HttpPostSocket.h.

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

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

Definition at line 79 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

std::string HttpPostSocket::m_boundary [private]

Definition at line 80 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 81 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 82 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

Definition at line 83 of file HttpPostSocket.h.

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

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

Definition at line 84 of file HttpPostSocket.h.

Referenced by HttpPostSocket().

Definition at line 85 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