![]() |
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 |
Definition at line 45 of file HttpPostSocket.h.
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 | ( | ) |
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 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] |
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 }
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] |
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().
bool HttpPostSocket::m_bMultipart [private] |
Definition at line 82 of file HttpPostSocket.h.
Referenced by AddFile(), OnConnect(), and SetMultipart().