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 ClientServiceLayer Client Service Layer 00024 * 00025 * The Client Service Layer provides application-level support for interacting 00026 * with Google Cloud Platform services and endpoints. It makes use of the 00027 * HTTP Transport Layer for the actual messaging and response handling but 00028 * hides these low level details with higher level abstractions specialized 00029 * for specific use cases. 00030 * 00031 * Much of this layer is geared around the consumption of services that present 00032 * REST-style interfaces. 00033 * 00034 * Typically programmers use the Google APIs Code Generator to generate a 00035 * C++ library specific to the service(s) they will be using. The output 00036 * of the code generator are libraries built ontop of the offerings in this 00037 * module. 00038 * 00039 * The client service layer also includes additional helper classes such as 00040 * the ServiceRequetsPager for paging through large resources using finer 00041 * granularity requests. 00042 */ 00043 #ifndef APISERVING_CLIENTSCPP_SERVICE_CLIENT_SERVICE_H_ 00044 #define APISERVING_CLIENTSCPP_SERVICE_CLIENT_SERVICE_H_ 00045 00046 #include <string> 00047 using std::string; 00048 #include "googleapis/base/macros.h" 00049 #include "googleapis/base/scoped_ptr.h" 00050 #include "googleapis/client/transport/http_transport.h" 00051 #include "googleapis/strings/stringpiece.h" 00052 #include "googleapis/util/status.h" 00053 namespace googleapis { 00054 00055 namespace client { 00056 class SerializableJson; 00057 class AuthorizationCredential; 00058 class HttpRequest; 00059 struct UriTemplateConfig; 00060 00061 class ClientService; 00062 /* 00063 * Base class for requests made to a ClientService. 00064 * @ingroup ClientServiceLayer 00065 * 00066 * This class is based on a Command Pattern. The instance is given the service 00067 * endpoint to invoke and is given the arguments to invoke with as expected 00068 * by that endpoint. When its Execute() method is called, it will invoke 00069 * the command and wait for the response. The caller can get any response 00070 * data as well as the overall status from the request instance. 00071 * 00072 * When using the code generator to create custom APIs for a given service, 00073 * the code generator will subclass these requests for each endpoint API. 00074 * The specialized subclasses will contain higher level methods for setting 00075 * the various arguments and parameters that are available to use. Those 00076 * class instances are created using the ClientService instance (i.e. the 00077 * ClientService acts as a ClientSrviceRequet factory. Therefore this class 00078 * is not typically explicitly instantiated. Lower level code may use this 00079 * class directly since it is concrete and fully capable. 00080 * 00081 * You should not explicitly destroy this class (or derived classes) when 00082 * making asynchronous requests unless you know that the request has 00083 * completely finished executing (its underlying HttpRequest is done). 00084 * It is safest to use DestroyWhenDone() instead. Otherwise code on the stack 00085 * may still be referencing the instance after it is destroyed, and your 00086 * program will crash. 00087 * 00088 * Requests are given a service and 00089 * <a href='http://tools.ietf.org/html/rfc6570'>RFC 6570</a> 00090 * URI Template to invoke within that service. The purpose of the URI 00091 * template is to ultimately provide the URL within the service. The 00092 * request instance can resolve the parameters in the template. This is 00093 * described in more detail with the PrepareUrl() method. 00094 */ 00095 class ClientServiceRequest { 00096 public: 00097 /* 00098 * Construct a new request. 00099 * 00100 * @param[in] service The service to send the request to 00101 * @param[in] credential If not NULL, the credentials to invoke with 00102 * @param[in] method The HTTP method when making the HTTP request 00103 * @param[in] uri_template The URI template specifying the url to invoke 00104 * 00105 * @see DestroyWhenDone 00106 * @see Execute 00107 * @see ExecuteAsync 00108 */ 00109 ClientServiceRequest( 00110 const ClientService* service, AuthorizationCredential* credential, 00111 const HttpRequest::HttpMethod& method, const StringPiece& uri_template); 00112 00113 /* 00114 * Standard instance destructor. 00115 * 00116 * @pre The HttpRequestState must be HttpRequestState::done() 00117 * @see DestroyWhenDone 00118 */ 00119 virtual ~ClientServiceRequest(); 00120 00121 /* 00122 * Tell instance to self-destruct (destroy itself) once it is safe to. 00123 * 00124 * This is the preferred means to destroy instances that are used 00125 * asynchronously. The instance will remain active until after the 00126 * callback (if any) has finished running and after any signaling has 00127 * been performed to HttpResponse::WaitUntilDone(). 00128 * 00129 * This method will destroy the object immediately if it is safe to do so. 00130 */ 00131 void DestroyWhenDone(); 00132 00133 /* 00134 * Ask the service to execute the request synchronously. 00135 * 00136 * The response data will be in the embedded HttpRequest 00137 * 00138 * @return status indicating the overall status of performing the request. 00139 * 00140 * @note HTTP failures (e.g. 4xx HTTP codes) are considered errors 00141 * as are transport level errors (e.g. unknown host). Finer grained status 00142 * information is available from the underlying HttpRequest. 00143 * 00144 * @see ExecuteAsync 00145 * @see ExecuteAndParseResponse 00146 * @see mutable_http_request 00147 * @see http_response 00148 */ 00149 virtual util::Status Execute(); 00150 00151 /* 00152 * Ask the service to execute the request asynchronously. 00153 * 00154 * @param[in] callback If not NULL then run this once the request is done. 00155 * 00156 * The callback will be called once the HttpRequest::done() criteria are 00157 * satisfied on the underlying HttpRequest. This is always the case, even 00158 * on fundamental transport errors such as unknown host or if the request 00159 * is invalid. 00160 * 00161 * The callback can check the HttpRequest details, including its HttpResponse 00162 * to get status and response details. These will be valid while the callback 00163 * is running, but will no longer be valid once the request is destroyed. 00164 * 00165 * @warning The callback might be called from another thread than this one. 00166 * For normal execution flows where the request can be sent to the service, 00167 * the callback will be invoked from the bound executor's context. If there 00168 * is a fundamental problem with the request or it could not be queued then 00169 * it may (but not necessarily) be called from the current context before 00170 * the method returns. 00171 * 00172 * @warning If DestroyWhenDone() has been called before invoking this method 00173 * then the instance might complete and thus be destroyed before this method 00174 * returns. This is ok, but you will have no way of knowing this without 00175 * recording extra state in your callback. 00176 * 00177 * @see Execute 00178 * @see mutable_http_request 00179 */ 00180 virtual void ExecuteAsync(HttpRequestCallback* callback); 00181 00182 /* 00183 * Returns the underlying HttpRequest. 00184 * 00185 * The request is set and managed by this instance. 00186 * The options on the request can be tuned. The request is owned by this 00187 * instance so you should not set its destroy_when_done attribute. Use 00188 * DestroyWhenDone on this instance instead if desired. 00189 */ 00190 HttpRequest* mutable_http_request() { return http_request_.get(); } 00191 00192 /* 00193 * Returns the underlying HttpReqeust. 00194 * 00195 * The request is set and managed by this instance. 00196 * The request provides access to its current HttpRequestState, response 00197 * status, and the actual response. 00198 */ 00199 const HttpRequest* http_request() const { return http_request_.get(); } 00200 00201 /* 00202 * Returns the underlying response. 00203 * 00204 * The response is set and managed by this instance (actually by the 00205 * instance's request). It is only valid over the lifetime of this instance 00206 * so be sure to look at any values before you destroy the request. 00207 */ 00208 HttpResponse* http_response() { return http_request_->response(); } 00209 00210 protected: 00211 /* 00212 * Fills out the mutable_http_request() owned by this instance with the 00213 * information specified by this request. 00214 * 00215 * The base class implementation calls PrepareUrl and snd sets the url 00216 * on the underlying request. Specialized classes may have other needs, 00217 * such as setting the requset payload. 00218 * 00219 * @param callback [in] If not NULL then this will be called on failure. 00220 */ 00221 virtual util::Status PrepareHttpRequest( 00222 HttpRequestCallback* callback = NULL); 00223 00224 /* 00225 * Resolves the templated URL into the actual URL to use. 00226 * 00227 * The base class implementation assumes that the content was set in the 00228 * constructor. It uses UriTemplate to handle URL parameters and expects 00229 * that specialized subclasses will override the ApendVariable method to 00230 * resolve the values for the variables that this method finds in the 00231 * template. 00232 * 00233 * @param[in] templated_url An 00234 * <a href='http://tools.ietf.org/html/rfc6570'>RFC 6570</a> formatted URL. 00235 * @param[out] prepared_url The templated_url after resolving the variables. 00236 * 00237 * @note Conceptually this method is <code>const</code>. However technically 00238 * it is not because so it can used as a callback method where the mechanism 00239 * does not permit non-const methods. 00240 */ 00241 virtual util::Status PrepareUrl( 00242 const StringPiece& templated_url, string* prepared_url); 00243 00244 /* 00245 * Appends the variable value to the target string. 00246 * 00247 * This method should use UriTemplate for the actual string append once 00248 * it locally determines what the value shoudl be. 00249 * 00250 * @param[in] variable_name The name of the variable to append 00251 * @param[in] config A pass through parameter needed when asking 00252 * UriTemplate to append the strings. The value of this paraemter is 00253 * determined internally by the methods within this class that invoke this 00254 * method. 00255 * @param[out] target The string to append to. 00256 */ 00257 virtual util::Status AppendVariable( 00258 const StringPiece& variable_name, 00259 const UriTemplateConfig& config, 00260 string* target); 00261 00262 /* 00263 * Appends the optional query parameters to the url. 00264 * 00265 * This method is called by the default PrepareHttpReqeuest to add the 00266 * optional parameters that might not be explicitly stated in the URI 00267 * template that was bound to the request. 00268 * 00269 * The base method simply returns success. Specialized requests should 00270 * add any optional query parameters that have been added into the request. 00271 */ 00272 virtual util::Status AppendOptionalQueryParameters(string* target); 00273 00274 /* 00275 * Execute the request synchronously. If the response suggests success then 00276 * load the response payload into the provided data parameter. 00277 * 00278 * @param[out] data The data will be cleared if the Execute was not 00279 * successful. 00280 * @return success if the Execute was successful and the response payload 00281 * could be loaded into the data object. Otherwise it will fail. If you want 00282 * to distinguish execute failures from response handling failures then you 00283 * will need to look at the http_response() details. 00284 * 00285 * This method is protected since it does not make sense on methods that 00286 * do not return json data objects. For those that do, their specialized 00287 * classes can expose this method by adding a public method that delegates 00288 * to this implementation. 00289 */ 00290 util::Status ExecuteAndParseResponse(SerializableJson* data); 00291 00292 /* 00293 * Accessor for the use_media_download attribute. 00294 * 00295 * This attribute should only be exposed by methods that support it. 00296 * @return true if the request should use HTTP media download. 00297 */ 00298 bool get_use_media_download() const { return use_media_download_; } 00299 00300 /* 00301 * Setter for the use_media_download attribute. 00302 * 00303 * This attribute should only be exposed by methods that support it. 00304 * @param[in] use True if HTTP should use media download. 00305 */ 00306 void set_use_media_download(bool use) { use_media_download_ = use; } 00307 00308 /* 00309 * Parse the response payload (i.e. its body_reader) as a data instance. 00310 * 00311 * @param[in,out] response The response to parse is modified as it is read. 00312 * @param[out] data The data to parse into 00313 * 00314 * @return Failure if the response has no data or cannot be parsed. 00315 * @see HttpResponse::body_reader() 00316 */ 00317 static util::Status ParseResponse( 00318 HttpResponse* response, SerializableJson* data); 00319 00320 private: 00321 scoped_ptr<HttpRequest> http_request_; 00322 bool destroy_when_done_; 00323 00324 /* 00325 * States whether request should use HTTP media download. 00326 * 00327 * This adds an implied optional query parameter 'alt=media' when true. 00328 * The parameter gets appended in the base AppendOptionalQueryParameters. 00329 */ 00330 bool use_media_download_; 00331 00332 /* 00333 * A helper method. 00334 * 00335 * This is an implementation for UriTemplate::AppendVariableCallback that 00336 * calls the virtual AppendVariable() method on this instance so that 00337 * subclasses can feed ther values into the template. 00338 */ 00339 util::Status CallAppendVariable( 00340 const StringPiece& variable_name, 00341 const UriTemplateConfig& config, 00342 string* target); 00343 00344 /* 00345 * A helper method. 00346 * 00347 * This is an HttpRequestCallback implementation used to auto-destroy 00348 * instances when done. 00349 */ 00350 void CallbackThenDestroy( 00351 HttpRequestCallback* callback, HttpRequest* request); 00352 00353 DISALLOW_COPY_AND_ASSIGN(ClientServiceRequest); 00354 }; 00355 00356 /* 00357 * Base class for denoting a cloud service. 00358 * @ingroup ClientServiceLayer 00359 * 00360 * A ClientService is a proxy to some service endpoint in the cloud. 00361 * It acts as a Facade to a particular service and Factory for specific 00362 * ClientServiceRequest instances to make requests of specific service 00363 * interfaces. There are no service methods common across all services so 00364 * the base class has an empty Facade and no requests to provide a factory 00365 * for. The specialized subclasses are more interesting with regard to these 00366 * roles. 00367 */ 00368 class ClientService { 00369 public: 00370 /* 00371 * Constructs a service instance acting as a proxy to a given service 00372 * endpoint. 00373 * 00374 * @param[in] root_url The root_url to access the given service. 00375 * Usually this is for the webserver that is hosting the service. 00376 * 00377 * @param[in] service_path The additional path to append to the url 00378 * to get at the particular service. 00379 * 00380 * @param[in] transport A transport instance to use when sending requests 00381 * to the service. The service instance will take ownership of the transport. 00382 */ 00383 ClientService( 00384 const StringPiece& root_url, 00385 const StringPiece& service_path, 00386 HttpTransport* transport); 00387 00388 /* 00389 * Standard destructor. 00390 */ 00391 virtual ~ClientService(); 00392 00393 /* 00394 * Returns the bound url_root attribute. 00395 */ 00396 const StringPiece& url_root() const { return url_root_; } 00397 00398 /* 00399 * Returns the bound url_path attribute. 00400 */ 00401 const StringPiece& url_path() const { return url_path_; } 00402 00403 /* 00404 * Returns the complete url to the service. 00405 * @return url_root + url_path 00406 */ 00407 const string& service_url() const { return service_url_; } 00408 00409 /* 00410 * Allows you to change the service_url. 00411 * 00412 * This method is intended as a hook to change the service_url location 00413 * from the default constructor, especially of specialized services that 00414 * might be created elsewhere. It is intended to point to a different 00415 * instance or location, such as for testing or staging. 00416 * 00417 * If you are going to change the URL, you should do so before you start 00418 * creating requests to send to it. 00419 * 00420 * @param[in] url_root The root url for the web server. 00421 * @param[in] url_path the path in the root_url for the service. 00422 * The service_url will be JoinPath(url_root,url_path) 00423 */ 00424 void ChangeServiceUrl( 00425 const StringPiece& url_root, const StringPiece& url_path); 00426 00427 /* 00428 * Returns the transport instance bound in the constructor. 00429 */ 00430 HttpTransport* transport() const { return transport_.get(); } 00431 00432 private: 00433 string service_url_; 00434 StringPiece url_root_; // Subset of service_url_ 00435 StringPiece url_path_; // Subset of service_url_ 00436 00437 scoped_ptr<HttpTransport> transport_; 00438 00439 DISALLOW_COPY_AND_ASSIGN(ClientService); 00440 }; 00441 00442 } // namespace client 00443 00444 } // namespace googleapis 00445 #endif // APISERVING_CLIENTSCPP_SERVICE_CLIENT_SERVICE_H_