![]() |
HttpPostSocket Class ReferenceGenerate a http post request, get response.
More...
|
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) | |
HttpPostSocket & | operator= (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 |
Definition at line 46 of file HttpPostSocket.h.
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 | ( | ) |
HttpPostSocket::HttpPostSocket | ( | const HttpPostSocket & | s | ) | [inline, private] |
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] |
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 }
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] |
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().
bool HttpPostSocket::m_bMultipart [private] |
Definition at line 83 of file HttpPostSocket.h.
Referenced by AddFile(), OnConnect(), and SetMultipart().
int HttpPostSocket::m_boundary_count = 0 [static, private] |
Mutex HttpPostSocket::m_boundary_mutex [static, private] |