Google APIs Client Library for C++
uri_utils.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines