HTTP协议(超文本传输协议)
以后有空系统整理:
1. 维基百科:点这里,其中说到请求的方法有一种是
POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
2. 可以结合breakpad的代码深入理解一下:
http_upload.h
View Code
1 /*********http_upload.h***********/ 2 3 // Copyright (c) 2006, Google Inc. 4 // All rights reserved. 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 // HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST 33 // request using libcurl. It currently supports requests that contain 34 // a set of string parameters (key/value pairs), and a file to upload. 35 36 #ifndef COMMON_LINUX_HTTP_UPLOAD_H__ 37 #define COMMON_LINUX_HTTP_UPLOAD_H__ 38 39 #include <map> 40 #include <string> 41 42 namespace google_breakpad { 43 44 using std::string; 45 using std::map; 46 47 class HTTPUpload { 48 public: 49 // Sends the given set of parameters, along with the contents of 50 // upload_file, as a multipart POST request to the given URL. 51 // file_part_name contains the name of the file part of the request 52 // (i.e. it corresponds to the name= attribute on an <input type="file">. 53 // Parameter names must contain only printable ASCII characters, 54 // and may not contain a quote (") character. 55 // Only HTTP(S) URLs are currently supported. Returns true on success. 56 // If the request is successful and response_body is non-NULL, 57 // the response body will be returned in response_body. 58 // If the send fails, a description of the error will be 59 // returned in error_description. 60 static bool SendRequest(const string &url, 61 const map<string, string> ¶meters, 62 const string &upload_file, 63 const string &file_part_name, 64 const string &proxy, 65 const string &proxy_user_pwd, 66 const string &ca_certificate_file, 67 string *response_body, 68 string *error_description); 69 70 private: 71 // Checks that the given list of parameters has only printable 72 // ASCII characters in the parameter name, and does not contain 73 // any quote (") characters. Returns true if so. 74 static bool CheckParameters(const map<string, string> ¶meters); 75 76 // No instances of this class should be created. 77 // Disallow all constructors, destructors, and operator. 78 HTTPUpload(); 79 explicit HTTPUpload(const HTTPUpload &); 80 void operator=(const HTTPUpload &); 81 ~HTTPUpload(); 82 }; 83 84 } // namespace google_breakpad 85 86 #endif // COMMON_LINUX_HTTP_UPLOAD_H__
http_upload.cc
View Code
1 // Copyright (c) 2006, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 #include "common/linux/http_upload.h" 31 32 #include <assert.h> 33 #include <dlfcn.h> 34 #include "third_party/curl/curl.h" 35 36 namespace { 37 38 // Callback to get the response data from server. 39 static size_t WriteCallback(void *ptr, size_t size, 40 size_t nmemb, void *userp) { 41 if (!userp) 42 return 0; 43 44 std::string *response = reinterpret_cast<std::string *>(userp); 45 size_t real_size = size * nmemb; 46 response->append(reinterpret_cast<char *>(ptr), real_size); 47 return real_size; 48 } 49 50 } // namespace 51 52 namespace google_breakpad { 53 54 static const char kUserAgent[] = "Breakpad/1.0 (Linux)"; 55 56 // static 57 bool HTTPUpload::SendRequest(const string &url, 58 const map<string, string> ¶meters, 59 const string &upload_file, 60 const string &file_part_name, 61 const string &proxy, 62 const string &proxy_user_pwd, 63 const string &ca_certificate_file, 64 string *response_body, 65 string *error_description) { 66 if (!CheckParameters(parameters)) 67 return false; 68 69 void *curl_lib = dlopen("libcurl.so", RTLD_NOW); 70 if (!curl_lib) { 71 if (error_description != NULL) 72 *error_description = dlerror(); 73 curl_lib = dlopen("libcurl.so.4", RTLD_NOW); 74 } 75 if (!curl_lib) { 76 // Debian gives libcurl a different name when it is built against GnuTLS 77 // instead of OpenSSL. 78 curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_NOW); 79 } 80 if (!curl_lib) { 81 curl_lib = dlopen("libcurl.so.3", RTLD_NOW); 82 } 83 if (!curl_lib) { 84 return false; 85 } 86 87 CURL* (*curl_easy_init)(void); 88 *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init"); 89 CURL *curl = (*curl_easy_init)(); 90 if (error_description != NULL) 91 *error_description = "No Error"; 92 93 if (!curl) { 94 dlclose(curl_lib); 95 return false; 96 } 97 98 CURLcode err_code = CURLE_OK; 99 CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...); 100 *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt"); 101 (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str()); 102 (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent); 103 // Set proxy information if necessary. 104 if (!proxy.empty()) 105 (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str()); 106 if (!proxy_user_pwd.empty()) 107 (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str()); 108 109 if (!ca_certificate_file.empty()) 110 (*curl_easy_setopt)(curl, CURLOPT_CAINFO, ca_certificate_file.c_str()); 111 112 struct curl_httppost *formpost = NULL; 113 struct curl_httppost *lastptr = NULL; 114 // Add form data. 115 CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...); 116 *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd"); 117 map<string, string>::const_iterator iter = parameters.begin(); 118 for (; iter != parameters.end(); ++iter) 119 (*curl_formadd)(&formpost, &lastptr, 120 CURLFORM_COPYNAME, iter->first.c_str(), 121 CURLFORM_COPYCONTENTS, iter->second.c_str(), 122 CURLFORM_END); 123 124 // Add form file. 125 (*curl_formadd)(&formpost, &lastptr, 126 CURLFORM_COPYNAME, file_part_name.c_str(), 127 CURLFORM_FILE, upload_file.c_str(), 128 CURLFORM_END); 129 130 (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost); 131 132 // Disable 100-continue header. 133 struct curl_slist *headerlist = NULL; 134 char buf[] = "Expect:"; 135 struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *); 136 *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append"); 137 headerlist = (*curl_slist_append)(headerlist, buf); 138 (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist); 139 140 if (response_body != NULL) { 141 (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback); 142 (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA, 143 reinterpret_cast<void *>(response_body)); 144 } 145 146 // Fail if 400+ is returned from the web server. 147 (*curl_easy_setopt)(curl, CURLOPT_FAILONERROR, 1); 148 149 CURLcode (*curl_easy_perform)(CURL *); 150 *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform"); 151 err_code = (*curl_easy_perform)(curl); 152 const char* (*curl_easy_strerror)(CURLcode); 153 *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror"); 154 #ifndef NDEBUG 155 if (err_code != CURLE_OK) 156 fprintf(stderr, "Failed to send http request to %s, error: %s\n", 157 url.c_str(), 158 (*curl_easy_strerror)(err_code)); 159 #endif 160 if (error_description != NULL) 161 *error_description = (*curl_easy_strerror)(err_code); 162 163 void (*curl_easy_cleanup)(CURL *); 164 *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup"); 165 (*curl_easy_cleanup)(curl); 166 if (formpost != NULL) { 167 void (*curl_formfree)(struct curl_httppost *); 168 *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree"); 169 (*curl_formfree)(formpost); 170 } 171 if (headerlist != NULL) { 172 void (*curl_slist_free_all)(struct curl_slist *); 173 *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all"); 174 (*curl_slist_free_all)(headerlist); 175 } 176 dlclose(curl_lib); 177 return err_code == CURLE_OK; 178 } 179 180 // static 181 bool HTTPUpload::CheckParameters(const map<string, string> ¶meters) { 182 for (map<string, string>::const_iterator pos = parameters.begin(); 183 pos != parameters.end(); ++pos) { 184 const string &str = pos->first; 185 if (str.size() == 0) 186 return false; // disallow empty parameter names 187 for (unsigned int i = 0; i < str.size(); ++i) { 188 int c = str[i]; 189 if (c < 32 || c == '"' || c > 127) { 190 return false; 191 } 192 } 193 } 194 return true; 195 } 196 197 } // namespace google_breakpad