Logo
~Sockets~
~Examples~
~Contact~


HttpPostSocket Class Reference
[HTTP Sockets]

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

#include <HttpPostSocket.h>

Inheritance diagram for HttpPostSocket:

Inheritance graph
[legend]
Collaboration diagram for HttpPostSocket:

Collaboration graph
[legend]
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

Detailed Description

Generate a http post request, get response.

Definition at line 45 of file HttpPostSocket.h.


Constructor & Destructor Documentation

HttpPostSocket::HttpPostSocket ( ISocketHandler  ) 

Definition at line 51 of file HttpPostSocket.cpp.

00051                                                 : HttpClientSocket(h)
00052 ,m_bMultipart(false)
00053 {
00054 }

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

Definition at line 57 of file HttpPostSocket.cpp.

References m_boundary, and Socket::Random().

00057                                                                         : HttpClientSocket(h, url_in)
00058 ,m_bMultipart(false)
00059 {
00060         m_boundary = "----";
00061         for (int i = 0; i < 12; i++)
00062         {
00063                 char c = 0;
00064                 while (!isalnum(c))
00065                 {
00066                         c = (char)(Random() % 96 + 32);
00067                 }
00068                 m_boundary += c;
00069         }
00070 }

HttpPostSocket::~HttpPostSocket (  ) 

Definition at line 73 of file HttpPostSocket.cpp.

00074 {
00075 }

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

Definition at line 73 of file HttpPostSocket.h.

00073 : 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 78 of file HttpPostSocket.cpp.

References AddMultilineField().

00079 {
00080         std::list<std::string> vec;
00081         vec.push_back(value);
00082         AddMultilineField(name, vec);
00083 }

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

Add multiline field to post.

Definition at line 86 of file HttpPostSocket.cpp.

References m_fields.

Referenced by AddField().

00087 {
00088         m_fields[name] = values;
00089 }

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

Add file to post.

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

00093 {
00094         struct stat st;
00095         if (!stat(filename.c_str(), &st))
00096         {
00097                 m_files[name] = filename;
00098                 m_content_length[filename] = st.st_size;
00099                 m_content_type[filename] = type;
00100                 m_bMultipart = true;
00101         }
00102         else
00103         {
00104                 Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00105                 SetCloseAndDelete();
00106         }
00107 }

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

References m_bMultipart.

00277 {
00278         m_bMultipart = true;
00279 }

void HttpPostSocket::Open (  ) 

connect to host:port derived from url in constructor

Definition at line 110 of file HttpPostSocket.cpp.

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

00111 {
00112         // why do I have to specify TcpSocket:: to get to the Open() method??
00113         TcpSocket::Open(GetUrlHost(), GetUrlPort());
00114 }

void HttpPostSocket::OnConnect (  )  [virtual]

http put client implemented in OnConnect

Reimplemented from Socket.

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

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

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

Definition at line 74 of file HttpPostSocket.h.

00074 { return *this; } // assignment operator

void HttpPostSocket::DoMultipartPost (  )  [private]

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

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


Member Data Documentation

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

Definition at line 77 of file HttpPostSocket.h.

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

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

Definition at line 78 of file HttpPostSocket.h.

Referenced by AddFile(), and DoMultipartPost().

std::string HttpPostSocket::m_boundary [private]

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

Referenced by AddFile(), and DoMultipartPost().

Definition at line 82 of file HttpPostSocket.h.

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


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