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

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  ) 

Definition at line 56 of file HttpPostSocket.cpp.

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

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

Definition at line 62 of file HttpPostSocket.cpp.

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

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

HttpPostSocket::~HttpPostSocket (  ) 

Definition at line 79 of file HttpPostSocket.cpp.

00080 {
00081 }

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

References AddMultilineField().

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

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

Add multiline field to post.

Definition at line 92 of file HttpPostSocket.cpp.

References m_fields.

Referenced by AddField().

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

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

Add file to post.

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

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

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

References m_bMultipart.

00283 {
00284         m_bMultipart = true;
00285 }

void HttpPostSocket::Open (  ) 

connect to host:port derived from url in constructor

Definition at line 116 of file HttpPostSocket.cpp.

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

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

void HttpPostSocket::OnConnect (  )  [virtual]

http put client implemented in OnConnect

Reimplemented from Socket.

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

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

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 173 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().

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


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