blob: 52084586ad546d693a4fd23629dc8121fcd1702b [file]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
#ifndef __PROCESS_HELP_HPP__
#define __PROCESS_HELP_HPP__
#include <string>
#include <process/future.hpp>
#include <process/http.hpp>
#include <process/process.hpp>
#include <stout/foreach.hpp>
#include <stout/json.hpp>
#include <stout/option.hpp>
#include <stout/preprocessor.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>
namespace process {
// Constructs a Markdown based help "page" for a route with the
// following template:
//
// ### USAGE ###
// usage
//
// ### TL;DR; ###
// tldr
//
// ### DESCRIPTION ###
// description
//
// ### AUTHENTICATION ###
// authentication requirements
//
// ### AUTHORIZATION ###
// authorization requirements and granularity
//
// references
//
// See the 'USAGE', 'TLDR', 'DESCRIPTION', 'AUTHENTICATION', and
// 'REFERENCES' helpers below to more easily construct your help pages.
std::string HELP(
const std::string& tldr,
const Option<std::string>& description = None(),
const Option<std::string>& authentication = None(),
const Option<std::string>& authorization = None(),
const Option<std::string>& references = None());
// Helper for single-line usage that puts it in a blockquote as code
// and adds a newline.
inline std::string USAGE(const std::string& usage)
{
return "> " + usage + "\n";
}
// Helper for single-line TL;DR; that adds a newline.
inline std::string TLDR(const std::string& tldr)
{
return tldr + "\n";
}
template <typename... T>
inline std::string DESCRIPTION(T&&... args)
{
return strings::join("\n", std::forward<T>(args)..., "\n");
}
// Helper for description of Authentication requirements.
inline std::string AUTHENTICATION(bool required)
{
if (required) {
return "This endpoint requires authentication iff HTTP authentication is\n"
"enabled.\n";
}
return "This endpoint does not require authentication.\n";
}
// Helper for description of Authorization requirements.
template <typename... T>
inline std::string AUTHORIZATION(T&&... args)
{
return strings::join("\n", std::forward<T>(args)..., "\n");
}
template <typename... T>
inline std::string REFERENCES(T&&... args)
{
return strings::join("\n", std::forward<T>(args)..., "\n");
}
// Help process for serving /help, /help/id, and /help/id/name (see
// Help::help below for more information).
class Help : public Process<Help>
{
public:
Help(const Option<std::string>& delegate);
// Adds 'help' for the route 'name' of the process with the
// specified 'id' (i.e., 'http://ip:port/id/name'). It's expected
// that 'help' is written using Markdown. When serving help to a
// browser the Markdown will be rendered into HTML while a tool like
// 'curl' or 'http' will just be given the Markdown directly (thus
// making it easy to get help without opening a browser).
// NOTE: There is no need to dispatch this directly; this gets
// automagically dispatched by 'ProcessBase::route'.
void add(const std::string& id,
const std::string& name,
const Option<std::string>& help);
// Remove a previously installed 'help' string for '/id/name'.
bool remove(const std::string& id, const std::string& name);
// Remove all previously installed 'help' strings for '/id/*'.
bool remove(const std::string& id);
// Allow the global json function to dump this object to its
// canonical JSON representation.
friend void json(JSON::ObjectWriter* writer, const Help& help);
protected:
void initialize() override;
private:
// Handles the following:
//
// (1) http://ip:port/help
// (2) http://ip:port/help/id
// (3) http://ip:port/help/id/name
//
// Where 'id' and 'name' are replaced with a process ID and route
// name respectively. (1) provides a "table of contents" for all
// available processes while (2) provides a "table of contents" for
// all endpoints associated with a particular process and (3)
// provides the help associated with a particular endpoint of a
// process.
Future<http::Response> help(const http::Request& request);
// Helper function to get usage path by process id and endpoint name.
std::string getUsagePath(const std::string& id, const std::string& name);
// Delegate process name to receive root HTTP requests.
const Option<std::string> delegate;
std::map<std::string, std::map<std::string, std::string>> helps;
};
} // namespace process {
#endif // __PROCESS_HELP_HPP__