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: ~Request()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: ~HttpServer()144 virtual ~HttpServer() {} 145 }; 146 147 } // namespace provider 148 } // namespace weave 149 150 #endif // LIBWEAVE_INCLUDE_WEAVE_PROVIDER_HTTP_SERVER_H_ 151