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> &parameters,
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> &parameters);
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> &parameters,
 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> &parameters) {
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
posted @ 2012-04-16 01:19  nepaul  阅读(385)  评论(0编辑  收藏  举报