// 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 #include #include #include #include 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 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 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_