Home | History | Annotate | Download | only in provider
      1 // Copyright 2015 The Weave Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_
      6 #define LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include <base/callback.h>
     12 #include <base/time/time.h>
     13 #include <weave/stream.h>
     14 
     15 namespace weave {
     16 namespace provider {
     17 
     18 // This interface should be implemented by the user of libweave and
     19 // provided during device creation in Device::Create(...)
     20 // libweave will use this interface to handle HTTP / HTTPS requests for Privet
     21 // APIs.
     22 //
     23 // This interface consist of 2 parts that need to be implemented by the
     24 // libweave user: HttpServer and HttpServer::Request. HttpServer provides
     25 // interface to control webserver, and is used to initialize Device object.
     26 // Request provides an abstraction for a specific HTTP request and may be a
     27 // short-lived object.
     28 //
     29 // Implementation of AddHttpsRequestHandler(...) method should follow the
     30 // same guidelines as implementation of AddHttpRequestHandler(...) with the
     31 // only difference, it is for HTTPS connection (not HTTP).
     32 //
     33 // Implementation of GetHttpPort() method should return port number on
     34 // which HTTP server will be listening. Normally it is port 80, but this
     35 // allows implementer to choose different port if necessary and tell it to
     36 // libweave.
     37 //
     38 // Implementation of GetHttpsPort() should follow the same guidelines as
     39 // GetHttpPort(). Default HTTPS port is 443, but could be changed and
     40 // communicated to libweave using this method.
     41 //
     42 // Implementation of GetHttpsCertificateFingerprint() method should
     43 // compute fingerprint of the certificate that HTTPS web server will be using.
     44 // Method of computing fingerprint is the following:
     45 //   fingerprint = SHA256 ( DER certificate )
     46 // You can see example implementation in HttpServerImpl::GenerateX509()
     47 // in libweave/examples/provider/event_http_server.cc
     48 //
     49 // Implementation of AddHttpRequestHandler(...) method should add path
     50 // to the list of the exposed entry points for the webserver and store
     51 // path and callback pair somewhere. Once webserver receives an HTTP request,
     52 // it should check if there is a libweave-registered handler corresponding to
     53 // the path in the request. If there is one, implementation should invoke
     54 // the callback associated with this path. If there is no callback associated
     55 // with request path, webserver should return HTTP status code 404.
     56 //
     57 // For example, let's say local IP is "192.168.0.1" and libweave called
     58 //   AddHttpRequestHandler("/privet/info", InfoHandlerCallback);
     59 // If webserver receives "http://192.168.0.1/privet/info" request, HttpServer
     60 // implementation must invoke InfoHandlerCallback.
     61 // If webserver receives "http://192.168.0.1/privet/auth" request, it must
     62 // return HTTP status code 404 response.
     63 //
     64 // As everywhere else, invoking callbacks have some limitations:
     65 //   - callback should not be called before AddHttpRequestHandler() returns
     66 //   - callback should be called on the same thread
     67 //
     68 // Once HttpServer implementation invokes a registered callback, it should
     69 // provide the Request interface implementation to access a request data.
     70 //
     71 // Implementation of GetPath() method should return path of the HTTP
     72 // request. For example, "/privet/info".
     73 //
     74 // Implementation of the GetFirstHeader(...) method should return the first
     75 // header in the request matching name parameter of this method.
     76 // For example, GetFirstHeader("Content-Length") may return "3495".
     77 //
     78 // Implementation of GetData() method should return full request data
     79 // in a binary format wrapped into std::string object.
     80 //
     81 // Implementation of the SendReply(...) method should send request response
     82 // message with specified parameters:
     83 //   status_code - standard HTTP status code, for example 200 to indicate
     84 //     successful response.
     85 //   data - binary data of the response body wrapped into std::string object.
     86 //   mime_type - MIME type of the response, that should be transferred into
     87 //     "Content-Type" HTTP header.
     88 // Implementation of the SendReply(...) method may also add other standard
     89 // HTTP headers, like "Content-Length" or "Transfer-Encoding" depending on
     90 // capabilities of the server and client which made this request.
     91 //
     92 // In case a device has multiple networking interfaces, the device developer
     93 // needs to make a decision where local APIs (Privet) are necessary and where
     94 // they are not needed. For example, it may not make sense to expose local
     95 // APIs on any external-facing network interface (cellular or WAN).
     96 //
     97 // In some cases, there might be more then one network interface where local
     98 // APIs makes sense. For example, a device may have both WiFi and Ethernet
     99 // connections. In such case, webserver should start on both interfaces
    100 // simultaneously, and allow requests from both interfaces to be handled by
    101 // libweave.
    102 //
    103 // From libweave perspective, it always looks like there is only one network
    104 // interface. It is the job of HttpServer implementation to hide network
    105 // complexity from libweave and to bring webserver up on the same port on all
    106 // interfaces.
    107 
    108 class HttpServer {
    109  public:
    110   class Request {
    111    public:
    112     virtual ~Request() {}
    113 
    114     virtual std::string GetPath() const = 0;
    115     virtual std::string GetFirstHeader(const std::string& name) const = 0;
    116     virtual std::string GetData() = 0;
    117 
    118     virtual void SendReply(int status_code,
    119                            const std::string& data,
    120                            const std::string& mime_type) = 0;
    121   };
    122 
    123   // Callback type for AddRequestHandler.
    124   using RequestHandlerCallback =
    125       base::Callback<void(std::unique_ptr<Request> request)>;
    126 
    127   // Adds callback called on new http/https requests with the given path.
    128   virtual void AddHttpRequestHandler(
    129       const std::string& path,
    130       const RequestHandlerCallback& callback) = 0;
    131   virtual void AddHttpsRequestHandler(
    132       const std::string& path,
    133       const RequestHandlerCallback& callback) = 0;
    134 
    135   virtual uint16_t GetHttpPort() const = 0;
    136   virtual uint16_t GetHttpsPort() const = 0;
    137   virtual std::vector<uint8_t> GetHttpsCertificateFingerprint() const = 0;
    138 
    139   // Specifies request timeout, after which the web server automatically aborts
    140   // requests. Should return base::TimeDelta::Max() if there is no timeout.
    141   virtual base::TimeDelta GetRequestTimeout() const = 0;
    142 
    143  protected:
    144   virtual ~HttpServer() {}
    145 };
    146 
    147 }  // namespace provider
    148 }  // namespace weave
    149 
    150 #endif  // LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_
    151