C++程序  |  151行  |  6.42 KB

// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_
#define LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_

#include <string>
#include <vector>

#include <base/callback.h>
#include <base/time/time.h>
#include <weave/stream.h>

namespace weave {
namespace provider {

// This interface should be implemented by the user of libweave and
// provided during device creation in Device::Create(...)
// libweave will use this interface to handle HTTP / HTTPS requests for Privet
// APIs.
//
// This interface consist of 2 parts that need to be implemented by the
// libweave user: HttpServer and HttpServer::Request. HttpServer provides
// interface to control webserver, and is used to initialize Device object.
// Request provides an abstraction for a specific HTTP request and may be a
// short-lived object.
//
// Implementation of AddHttpsRequestHandler(...) method should follow the
// same guidelines as implementation of AddHttpRequestHandler(...) with the
// only difference, it is for HTTPS connection (not HTTP).
//
// Implementation of GetHttpPort() method should return port number on
// which HTTP server will be listening. Normally it is port 80, but this
// allows implementer to choose different port if necessary and tell it to
// libweave.
//
// Implementation of GetHttpsPort() should follow the same guidelines as
// GetHttpPort(). Default HTTPS port is 443, but could be changed and
// communicated to libweave using this method.
//
// Implementation of GetHttpsCertificateFingerprint() method should
// compute fingerprint of the certificate that HTTPS web server will be using.
// Method of computing fingerprint is the following:
//   fingerprint = SHA256 ( DER certificate )
// You can see example implementation in HttpServerImpl::GenerateX509()
// in libweave/examples/provider/event_http_server.cc
//
// Implementation of AddHttpRequestHandler(...) method should add path
// to the list of the exposed entry points for the webserver and store
// path and callback pair somewhere. Once webserver receives an HTTP request,
// it should check if there is a libweave-registered handler corresponding to
// the path in the request. If there is one, implementation should invoke
// the callback associated with this path. If there is no callback associated
// with request path, webserver should return HTTP status code 404.
//
// For example, let's say local IP is "192.168.0.1" and libweave called
//   AddHttpRequestHandler("/privet/info", InfoHandlerCallback);
// If webserver receives "http://192.168.0.1/privet/info" request, HttpServer
// implementation must invoke InfoHandlerCallback.
// If webserver receives "http://192.168.0.1/privet/auth" request, it must
// return HTTP status code 404 response.
//
// As everywhere else, invoking callbacks have some limitations:
//   - callback should not be called before AddHttpRequestHandler() returns
//   - callback should be called on the same thread
//
// Once HttpServer implementation invokes a registered callback, it should
// provide the Request interface implementation to access a request data.
//
// Implementation of GetPath() method should return path of the HTTP
// request. For example, "/privet/info".
//
// Implementation of the GetFirstHeader(...) method should return the first
// header in the request matching name parameter of this method.
// For example, GetFirstHeader("Content-Length") may return "3495".
//
// Implementation of GetData() method should return full request data
// in a binary format wrapped into std::string object.
//
// Implementation of the SendReply(...) method should send request response
// message with specified parameters:
//   status_code - standard HTTP status code, for example 200 to indicate
//     successful response.
//   data - binary data of the response body wrapped into std::string object.
//   mime_type - MIME type of the response, that should be transferred into
//     "Content-Type" HTTP header.
// Implementation of the SendReply(...) method may also add other standard
// HTTP headers, like "Content-Length" or "Transfer-Encoding" depending on
// capabilities of the server and client which made this request.
//
// In case a device has multiple networking interfaces, the device developer
// needs to make a decision where local APIs (Privet) are necessary and where
// they are not needed. For example, it may not make sense to expose local
// APIs on any external-facing network interface (cellular or WAN).
//
// In some cases, there might be more then one network interface where local
// APIs makes sense. For example, a device may have both WiFi and Ethernet
// connections. In such case, webserver should start on both interfaces
// simultaneously, and allow requests from both interfaces to be handled by
// libweave.
//
// From libweave perspective, it always looks like there is only one network
// interface. It is the job of HttpServer implementation to hide network
// complexity from libweave and to bring webserver up on the same port on all
// interfaces.

class HttpServer {
 public:
  class Request {
   public:
    virtual ~Request() {}

    virtual std::string GetPath() const = 0;
    virtual std::string GetFirstHeader(const std::string& name) const = 0;
    virtual std::string GetData() = 0;

    virtual void SendReply(int status_code,
                           const std::string& data,
                           const std::string& mime_type) = 0;
  };

  // Callback type for AddRequestHandler.
  using RequestHandlerCallback =
      base::Callback<void(std::unique_ptr<Request> request)>;

  // Adds callback called on new http/https requests with the given path.
  virtual void AddHttpRequestHandler(
      const std::string& path,
      const RequestHandlerCallback& callback) = 0;
  virtual void AddHttpsRequestHandler(
      const std::string& path,
      const RequestHandlerCallback& callback) = 0;

  virtual uint16_t GetHttpPort() const = 0;
  virtual uint16_t GetHttpsPort() const = 0;
  virtual std::vector<uint8_t> GetHttpsCertificateFingerprint() const = 0;

  // Specifies request timeout, after which the web server automatically aborts
  // requests. Should return base::TimeDelta::Max() if there is no timeout.
  virtual base::TimeDelta GetRequestTimeout() const = 0;

 protected:
  virtual ~HttpServer() {}
};

}  // namespace provider
}  // namespace weave

#endif  // LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_