Google APIs Client Library for C++
|
00001 /* 00002 * \copyright Copyright 2013 Google Inc. All Rights Reserved. 00003 * \license @{ 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * 00017 * @} 00018 */ 00019 00020 // Author: ewiseblatt@google.com (Eric Wiseblatt) 00021 00022 /* 00023 * @defgroup PlatformLayerUri Platform Layer - URI Support Module 00024 * 00025 * The URI Support module provides various classes and free 00026 * functions to support the use and application of URIs in general. 00027 */ 00028 #ifndef APISERVING_CLIENTS_CPP_UTIL_URI_UTILS_H_ 00029 #define APISERVING_CLIENTS_CPP_UTIL_URI_UTILS_H_ 00030 00031 #include <string> 00032 using std::string; 00033 #include <utility> 00034 using std::make_pair; 00035 using std::pair; 00036 #include <vector> 00037 using std::vector; 00038 #include "googleapis/client/util/date_time.h" 00039 #include "googleapis/strings/numbers.h" 00040 #include "googleapis/strings/strcat.h" 00041 #include "googleapis/strings/stringpiece.h" 00042 namespace googleapis { 00043 00044 namespace client { 00045 00046 /* 00047 * Parses a url as described in 2.4 of 00048 * <a href='http://www.ietf.org/rfc/rfc1808.txt'>RFC 1808</a>. 00049 * @ingroup PlatformLayerUri 00050 * 00051 * This is an extension of 00052 * <a href='http://www.ietf.org/rfc/rfc1838.txt'>RFC 1738</a> 00053 * that includes fragments. 00054 * 00055 * In RFC 1808 the URL is in the form: 00056 * [scheme]://[netloc]/[path];[params]?[query]#[fragment] 00057 * Each of these parts is optional. 00058 * 00059 * In RFC 1738 the URL form is a function of the scheme, but for http it is 00060 * http://[host]:[port]/[path]?[searchpart] 00061 * where here we: 00062 * - treat [netloc] = [host]:[port] 00063 * - allow [path] to have ';'[params] 00064 * - subdivide [searchpart] into [query]'#'[fragment] 00065 * 00066 * Note that the [fragment] and '#' that proceeds it is not actually 00067 * part of the URL but is here because it is commonly used within the 00068 * same string context as a URL as specified in RFC 1808. 00069 */ 00070 class ParsedUrl { 00071 public: 00072 /* 00073 * Type used for getting individual query parameter bindings. 00074 * The values will be unescaped. 00075 */ 00076 typedef pair<StringPiece, string> QueryParameterAssignment; 00077 00078 /* 00079 * Construct the parsed url from a URL. 00080 */ 00081 explicit ParsedUrl(const StringPiece& url); 00082 00083 /* 00084 * Standard destructor. 00085 */ 00086 ~ParsedUrl(); 00087 00088 /* 00089 * Returns the URL that was parsed. 00090 */ 00091 const string& url() const { return url_; } 00092 00093 /* 00094 * Returns the URL's scheme. 00095 * 00096 * @return The scheme (e.g. 'https') or empty if none 00097 */ 00098 StringPiece scheme() const { return scheme_; } 00099 00100 /* 00101 * Returns the URL's network location. 00102 * 00103 * @return The network location, including port if explicitly specified 00104 * (e.g. 'www.googleapis.com'). This might be empty. 00105 */ 00106 StringPiece netloc() const { return netloc_; } 00107 00108 /* 00109 * Returns the URL's path. 00110 * 00111 * @return The URL's path (e.g. '/drive/v2/files'). This might be empty. 00112 */ 00113 StringPiece path() const { return path_; } 00114 00115 /* 00116 * Returns the URL's parameters. 00117 * 00118 * @return The URL's parameters are the content between the ';' and 00119 * query parameters or fragment or end of string. It may be empty. 00120 */ 00121 StringPiece params() const { return params_; } 00122 00123 /* 00124 * Returns the URL's query string. 00125 * 00126 * @return The URL's query string is the URL content between the '?' and 00127 * fragment (or end of string if no fragment). It may be empty. 00128 */ 00129 StringPiece query() const { return query_; } 00130 00131 /* 00132 * Returns the URL's fragment. 00133 * 00134 * @return The URL's fragment does not include the leading '#'. It may 00135 * be empty. 00136 */ 00137 StringPiece fragment() const { return fragment_; } 00138 00139 /* 00140 * Returns whether the URL was valid or not. 00141 */ 00142 bool IsValid() const; 00143 00144 /* 00145 * Returns the detailed assignments for individual query parameters. 00146 * 00147 * This method is not thread-safe for the first invocation. 00148 */ 00149 const vector<QueryParameterAssignment>& GetQueryParameterAssignments() const; 00150 00151 /* 00152 * Looks up value of query paraemter if it is there. 00153 * 00154 * @param[in] name The value to look for. 00155 * @param[out] value The [unescaped] value found. 00156 * @return true if parameter was present, false if not. 00157 */ 00158 bool GetQueryParameter(const StringPiece& name, string* value) const; 00159 00160 /* 00161 * Conditionally joins two strings for a URL segment. 00162 * 00163 * This is a helper function for joining together an attribute with its 00164 * separator. 00165 * 00166 * @param[in] join If true then join the strings, if false then return empty. 00167 * @param[in] a The prefix of the joined string. 00168 * @param[in] b The postfix of the joined string. 00169 * 00170 * @return Either a + b or "". 00171 */ 00172 static string SegmentOrEmpty( 00173 bool join, const StringPiece& a, const StringPiece& b) { 00174 return join ? StrCat(a, b) : ""; 00175 } 00176 00177 private: 00178 string url_; 00179 StringPiece scheme_; // does not include trailing ':' 00180 StringPiece netloc_; // does not include leading '//' 00181 StringPiece path_; // includes leading '/' if absolute 00182 StringPiece params_; // does not include leading ';' 00183 StringPiece query_; // does not include leading '?' 00184 StringPiece fragment_; // does not include leading '#' 00185 00186 // Constructed on first request, not thread-safe but not typically 00187 // used in a multi-threaded context and not typically used at all. 00188 mutable vector<QueryParameterAssignment> query_param_assignments_; 00189 00190 // Indicates whether the url is valid or not. 00191 mutable bool valid_; 00192 }; 00193 00194 /* 00195 * Resolve a [possibly] relative url into an absolute url. 00196 * @ingroup PlatformLayerUri 00197 * 00198 * This function implements <a href='http://www.ietf.org/rfc/rfc1808.txt'> 00199 * RFC 1808 Relative Uniform Resource Locators</a> to resolve a url relative 00200 * to a base url. Note that the actual RFC handles URLs embedded into complex 00201 * documents. Here we only have a single base url. 00202 * 00203 * @param[in] base_url The base url. 00204 * @param[in] new_url The url to be resolved against the base. 00205 * @return The resolved URL or empty string on failure. 00206 */ 00207 string ResolveUrl(const StringPiece& base_url, const StringPiece& new_url); 00208 00209 /* 00210 * Join two fragments together into a path. 00211 * @ingroup PlatformLayerUri 00212 * 00213 * @param[in] a The first fragment may or may not have a trailing '/'. 00214 * @param[in] b The second fragment may or may not have a leading '/'. 00215 * @return The path "a/b" containing exactly one '/' between fragments a and b. 00216 */ 00217 string JoinPath(const StringPiece& a, const StringPiece& b); 00218 00219 /* 00220 * Escape a string so that it is valid in a URL. 00221 * @ingroup PlatformLayerUri 00222 * 00223 * @param[in] s The string to escape. 00224 * @return the escaped string. 00225 */ 00226 string EscapeForUrl(const StringPiece& s); 00227 bool UnescapeFromUrl(const StringPiece& s, string* to); 00228 00229 /* 00230 * Templated function that encodes a primitive C++ value for use in a URL. 00231 * @ingroup PlatformLayerUri 00232 * 00233 * @param[in] value The C++ value 00234 * @return The string encoding suitable for use in a URL. 00235 */ 00236 template<typename T> string CppValueToEscapedUrlValue(const T& value); 00237 00238 /* 00239 * Templated function that encodes a C++ STL container for use as in a URL. 00240 * @ingroup PlatformLayerUri 00241 * 00242 * The values in the array are those returned by the iterator. 00243 * This does not put a leading (or ending) separator so you should 00244 * form the uri with either a leading '&' or '?' to indicate that parameters 00245 * are following. 00246 * 00247 * @param[in] begin The start of the array sequence. 00248 * @param[in] end The end of the array sequence. 00249 * @param[in] param_name The name of the URL parameter being added. 00250 * @param[in,out] target The string to append the string-encoded value into. 00251 */ 00252 template<typename T> 00253 void AppendIteratorToUrl( 00254 const T& begin, const T& end, 00255 const StringPiece param_name, string *target); 00256 00257 /* 00258 * Implements append a scalar value into a URL. 00259 * 00260 * This function is intended for scalar types: [u]int(16|32|64) 00261 */ 00262 template<typename T> 00263 inline string CppValueToEscapedUrlValue(const T& value) { 00264 return SimpleItoa(value); 00265 } 00266 00267 /* 00268 * Implements append a character value into a URL. 00269 */ 00270 template<> 00271 inline string CppValueToEscapedUrlValue<char>(const char& value) { 00272 return string(1, value); 00273 } 00274 00275 /* 00276 * Implements append a boolean value into a URL. 00277 */ 00278 template<> 00279 inline string CppValueToEscapedUrlValue<bool>(const bool& value) { 00280 return value ? "true" : "false"; 00281 } 00282 00283 /* 00284 * Implements append a float value into a URL. 00285 */ 00286 template<> 00287 inline string CppValueToEscapedUrlValue<float>(const float& value) { 00288 return SimpleFtoa(value); 00289 } 00290 00291 /* 00292 * Implements append a double value into a URL. 00293 */ 00294 template<> 00295 inline string CppValueToEscapedUrlValue<double>(const double& value) { 00296 return SimpleDtoa(value); 00297 } 00298 00299 /* 00300 * Implements append a string value into a URL. 00301 */ 00302 template<> 00303 inline string CppValueToEscapedUrlValue<string>(const string& value) { 00304 return EscapeForUrl(value); 00305 } 00306 00307 /* 00308 * Implements append a DateTime value into a URL. 00309 */ 00310 template<> 00311 inline string CppValueToEscapedUrlValue<DateTime>(const DateTime& value) { 00312 return EscapeForUrl(value.ToString()); 00313 } 00314 00315 /* 00316 * Implements default templated AppendIteratorToUrl. 00317 */ 00318 template<typename T> 00319 void AppendIteratorToUrl( 00320 const T& begin, const T& end, const StringPiece param_name, 00321 string* target) { 00322 const char* sep = ""; 00323 for (T it = begin; it != end; ++it) { 00324 StrAppend(target, sep, param_name, "=", CppValueToEscapedUrlValue(*it)); 00325 sep = "&"; 00326 } 00327 } 00328 00329 } // namespace client 00330 00331 } // namespace googleapis 00332 #endif // APISERVING_CLIENTS_CPP_UTIL_URI_UTILS_H_