Google APIs Client Library for C++
abstract_webserver.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 
00021 /*
00022  * @defgroup PlatformLayerWebServer Platform Layer - Embedded Web Server
00023  *
00024  * The embedded webserver module is provided by the Plaform Layer rather
00025  * than the Trnasport Layer were you might otherwise expect it. This is
00026  * because we are not really embracing it as a core product feature. It is
00027  * only here to support providing interfaces to iteractt with embedded
00028  * HTTP servers and for writing tests.
00029  *
00030  * The request/response abstraction in this module is distinctly different
00031  * (and not compatible with) the HttpRequest interface core to the
00032  * Transport Layer. The transport layer is designed around the needs of
00033  * clients. The embedded web server is for servers. Because the focal point
00034  * of the SDK is strictly for clients, we are keeping the focus and viewpoints
00035  * more stictly separated.
00036  */
00037 
00038 #ifndef APISERVING_CLIENTS_CPP_UTIL_ABSTRACT_WEBSERVER_H_
00039 #define APISERVING_CLIENTS_CPP_UTIL_ABSTRACT_WEBSERVER_H_
00040 
00041 #include <string>
00042 using std::string;
00043 #include <utility>
00044 using std::make_pair;
00045 using std::pair;
00046 #include <vector>
00047 using std::vector;
00048 #include "googleapis/client/util/uri_utils.h"
00049 #include "googleapis/base/callback.h"
00050 #include "googleapis/base/macros.h"
00051 #include "googleapis/base/scoped_ptr.h"
00052 #include "googleapis/strings/stringpiece.h"
00053 #include "googleapis/util/status.h"
00054 namespace googleapis {
00055 
00056 namespace client {
00057 
00058 /*
00059  * Abstract class for responses to WebServerRequests into the
00060  * AbstractWebServer
00061  * @ingroup PlatformLayerWebServer
00062  *
00063  * This is different from the HttpResponse class in the transport layer
00064  * which are client-side responses. These are server side responses.
00065  *
00066  * Responses are owned and created by WebServerRequest.
00067  */
00068 class WebServerResponse {
00069  public:
00070   WebServerResponse() {}
00071   virtual ~WebServerResponse() {}
00072 
00073   /*
00074    * Respond with a text/html content type and body.
00075    *
00076    * @param[in] http_code The HTTP status code to send.
00077    * @param[in] body The payload can be empty.
00078    *
00079    * @return ok or reason for failure.
00080    */
00081   util::Status SendHtml(int http_code, const StringPiece& body) {
00082     return SendReply("text/html", http_code, body);
00083   }
00084 
00085   /*
00086    * Respond with a text/plain content type and body.
00087    *
00088    * @param[in] http_code The HTTP status code to send.
00089    * @param[in] body The payload can be empty.
00090    *
00091    * @return ok or reason for failure.
00092    */
00093   util::Status SendText(int http_code, const StringPiece& body) {
00094     return SendReply("text/plain", http_code, body);
00095   }
00096 
00097   /*
00098    * Respond with a redirect to another url.
00099    *
00100    * @param[in] http_code The HTTP status code to send (e.g. 307).
00101    * @param[in] url The url to redirect to.
00102    *
00103    * @return ok or reason for failure.
00104    */
00105   virtual util::Status SendRedirect(
00106       int http_code, const StringPiece& url);
00107 
00108   /*
00109    * Respond with an specified content type and body.
00110    *
00111    * @param[in] content_type The MIME content type of the body.
00112    * @param[in] http_code The HTTP status code to send.
00113    * @param[in] body The payload can be empty.
00114    *
00115    * @return ok or reason for failure.
00116    */
00117   virtual util::Status SendReply(
00118       const StringPiece& content_type,
00119       int http_code,
00120       const StringPiece& body) = 0;
00121 
00122   /*
00123    * Adds a custom header to the repsonse.
00124    *
00125    * Content-Type, Content-Length and Location headers are automatically added.
00126    * This will not check the header names or values.
00127    *
00128    * @param[in] name The name of header to add.
00129    * @param[in] value The value of the header.
00130    */
00131   virtual util::Status AddHeader(
00132       const StringPiece& name, const StringPiece& value) = 0;
00133 
00134   /*
00135    * Adds a custom cookie to the repsonse.
00136    *
00137    * This will not check the cookie names or values.
00138    *
00139    * @param[in] name The name of header to add.
00140    * @param[in] value The value of the header.
00141    */
00142   virtual util::Status AddCookie(
00143       const StringPiece& name, const StringPiece& value) = 0;
00144 
00145  private:
00146   DISALLOW_COPY_AND_ASSIGN(WebServerResponse);
00147 };
00148 
00149 /*
00150  * Abstract class for invocations into the AbstractWebServer
00151  * @ingroup PlatformLayerWebServer
00152  *
00153  * This is different from the HttpRequest class in the transport layer
00154  * which are client-side requests. These are server side requests.
00155  *
00156  * Requests are created by the AbstractWebServer when it receives an
00157  * invocation.
00158  */
00159 class WebServerRequest {
00160  public:
00161   /*
00162    * Standard constructor.
00163    *
00164    * @param[in] method The HTTP method called (e.g. GET).
00165    * @param[in] url The url that was invoked.
00166    * @param[in] response_storage The repsonse object to bind to the request.
00167    */
00168   WebServerRequest(
00169       const StringPiece& method,
00170       const StringPiece& url,
00171       WebServerResponse* response_storage);
00172 
00173   /*
00174    * Standard destructor.
00175    */
00176   virtual ~WebServerRequest();
00177 
00178   const string& method() const { return method_; }
00179   const ParsedUrl& parsed_url() const { return parsed_url_; }
00180   WebServerResponse* response() const { return response_.get(); }
00181 
00182   virtual bool GetCookieValue(const char* key, string* value) const = 0;
00183   virtual bool GetHeaderValue(const char* key, string* value) const = 0;
00184 
00185  private:
00186   string method_;
00187   ParsedUrl parsed_url_;
00188   scoped_ptr<WebServerResponse> response_;
00189 };
00190 
00191 /*
00192  * A minimal abstract interface for embedded webservers.
00193  * @ingroup PlatformLayerWebServer
00194  *
00195  * This is only an abstract interface. You must supply
00196  * your own implementation and use this class to adapt it. The interface
00197  * is only intended to provide some library code and sample code that integrate
00198  * with an embedded web server without explicitly depending on any particular
00199  * implementation.
00200  *
00201  * Note that this interface does not accomodate POST requests at this time,
00202  * but the library does not need it as a client -- this abstractionis not
00203  * intended to be used for implementing cloud services.
00204  */
00205 class AbstractWebServer {
00206  public:
00207   /*
00208    * Used to register a callback on particular URIs or trees.
00209    *
00210    * @param[in] request for the request being processed.
00211    * @return ok or reason for failure.
00212    */
00213   typedef ResultCallback1< util::Status, WebServerRequest*> PathHandler;
00214 
00215   /*
00216    * Constructs an http server on the given port
00217    *
00218    * @param[in] port Should be non-0.
00219    */
00220   explicit AbstractWebServer(int port);
00221 
00222   /*
00223    * Standard destructor.
00224    */
00225   virtual ~AbstractWebServer();
00226 
00227   /*
00228    * Returns the port bound in the constructor.
00229    */
00230   int port() const { return port_; }
00231 
00232   /*
00233    * Starts the server.
00234    *
00235    * @return ok or reason for error.
00236    */
00237   util::Status Startup();
00238 
00239   /*
00240    * Stops the server.
00241    *
00242    * @return ok or reason for error.
00243    */
00244   void Shutdown();
00245 
00246   /*
00247    * Returns URL into this server for the given path.
00248    *
00249    * @param[in] use_localhost If true use 'localhost' rather than the hostname.
00250    * @param[in] path The path part of the url to build.
00251    */
00252   string MakeEndpointUrl(bool use_localhost, const StringPiece& path) const;
00253 
00254   /*
00255    * Inject handler for path.
00256    *
00257    * @param[in] path The path to intercept with this handler.
00258    * @param[in] handler A repeatable callback. Ownership is passed.
00259    *
00260    * This is called by the default DoHandleUrl method.
00261    */
00262   void AddPathHandler(const string& path, PathHandler* handler);
00263 
00264   /*
00265    * Looks up added PathHandler that matches path.
00266    *
00267    * Searches in the order they were added.
00268    *
00269    * @param[in] request The request to lookup.
00270    * @return path handler or NULL if one could not be found.
00271    */
00272   PathHandler* FindPathHandler(WebServerRequest* request) const;
00273 
00274   /*
00275    * Returns the protocol part of the url used by this webserver (e.g. 'https')
00276    */
00277   virtual string url_protocol() const;
00278 
00279  protected:
00280   virtual util::Status DoStartup() = 0;
00281   virtual void DoShutdown() = 0;
00282 
00283   /*
00284    * Handles inbound request.
00285    *
00286    * The base class method looks up a registered path handler that matches
00287    * the url path prefix. It returns a 404 if one isnt found.
00288    *
00289    * @param[in] request The request from the web server.
00290    */
00291   virtual util::Status DoHandleRequest(WebServerRequest* request);
00292 
00293  private:
00294   int port_;
00295 
00296   typedef pair<string, PathHandler*> Hook;
00297   vector<Hook> hooks_;
00298 
00299   DISALLOW_COPY_AND_ASSIGN(AbstractWebServer);
00300 };
00301 
00302 }  // namespace client
00303 
00304 } // namespace googleapis
00305 #endif  // APISERVING_CLIENTS_CPP_UTIL_ABSTRACT_WEBSERVER_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines