Line data Source code
1 : #pragma once 2 : 3 : #include <functional> 4 : #include <string> 5 : 6 : #include "envoy/buffer/buffer.h" 7 : #include "envoy/common/pure.h" 8 : #include "envoy/http/codes.h" 9 : #include "envoy/http/filter.h" 10 : #include "envoy/http/header_map.h" 11 : #include "envoy/http/query_params.h" 12 : #include "envoy/network/listen_socket.h" 13 : #include "envoy/server/config_tracker.h" 14 : 15 : #include "absl/strings/string_view.h" 16 : 17 : namespace Envoy { 18 : namespace Server { 19 : 20 : class AdminStream { 21 : public: 22 98 : virtual ~AdminStream() = default; 23 : 24 : /** 25 : * @param end_stream set to false for streaming response. Default is true, which will 26 : * end the response when the initial handler completes. 27 : */ 28 : virtual void setEndStreamOnComplete(bool end_stream) PURE; 29 : 30 : /** 31 : * @param cb callback to be added to the list of callbacks invoked by onDestroy() when stream 32 : * is closed. 33 : */ 34 : virtual void addOnDestroyCallback(std::function<void()> cb) PURE; 35 : 36 : /** 37 : * @return Http::StreamDecoderFilterCallbacks& to be used by the handler to get HTTP request data 38 : * for streaming. 39 : */ 40 : virtual Http::StreamDecoderFilterCallbacks& getDecoderFilterCallbacks() const PURE; 41 : 42 : /** 43 : * @return const Buffer::Instance* the fully buffered admin request if applicable. 44 : */ 45 : virtual const Buffer::Instance* getRequestBody() const PURE; 46 : 47 : /** 48 : * @return Http::HeaderMap& to be used by handler to parse header information sent with the 49 : * request. 50 : */ 51 : virtual const Http::RequestHeaderMap& getRequestHeaders() const PURE; 52 : 53 : /** 54 : * Return the HTTP/1 stream encoder options if applicable. If the stream is not HTTP/1 returns 55 : * absl::nullopt. 56 : */ 57 : virtual Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() PURE; 58 : 59 : /** 60 : * Construct query-param map for the stream, using the URL-specified params, 61 : * or the request data if that is url-form-encoded. 62 : * 63 : * @param The query name/value map. 64 : */ 65 : virtual Http::Utility::QueryParamsMulti queryParams() const PURE; 66 : }; 67 : 68 : /** 69 : * This macro is used to add handlers to the Admin HTTP Endpoint. It builds 70 : * a callback that executes X when the specified admin handler is hit. This macro can be 71 : * used to add static handlers as in source/server/admin/admin.cc and also dynamic handlers as 72 : * done in the RouteConfigProviderManagerImpl constructor in source/common/router/rds_impl.cc. 73 : */ 74 : #define MAKE_ADMIN_HANDLER(X) \ 75 2 : [this](Http::ResponseHeaderMap& response_headers, Buffer::Instance& data, \ 76 100 : Server::AdminStream& admin_stream) -> Http::Code { \ 77 98 : return X(response_headers, data, admin_stream); \ 78 98 : } 79 : 80 : /** 81 : * Global admin HTTP endpoint for the server, holding a map from URL prefixes to 82 : * handlers. When an HTTP request arrives at the admin port, the URL is linearly 83 : * prefixed-matched against an ordered list of handlers. When a match is found, 84 : * the handler is used to generate a Request. 85 : * 86 : * Requests are capable of streaming out content to the client, however, most 87 : * requests are delivered all at once. The implementation supplies adapters for 88 : * simplifying the creation of streaming requests based on a simple callback 89 : * that takes a URL and generates response headers and response body. 90 : * 91 : * A Taxonomy of the major types involved may help clarify: 92 : * Request a class holding state for streaming admin content to clients. 93 : * These are re-created for each request. 94 : * Handler a class that holds context for a family of admin requests, 95 : * supplying one-shot callbacks for non-streamed responses, and 96 : * for generating Request objects directly for streamed responses. 97 : * These have the same lifetime as Admin objects. 98 : * Admin Holds the ordered list of handlers to be prefix-matched. 99 : */ 100 : class Admin { 101 : public: 102 270 : virtual ~Admin() = default; 103 : 104 : // Describes a parameter for an endpoint. This structure is used when 105 : // admin-html has not been disabled to populate an HTML form to enable a 106 : // visitor to the admin console to intuitively specify query-parameters for 107 : // each endpoint. The parameter descriptions also appear in the /help 108 : // endpoint, independent of how Envoy is compiled. 109 : struct ParamDescriptor { 110 : enum class Type { Boolean, String, Enum }; 111 : Type type_; 112 : std::string id_; // HTML form ID and query-param name (JS var name rules). 113 : std::string help_; // Rendered into home-page HTML and /help text. 114 : std::vector<absl::string_view> enum_choices_{}; 115 : }; 116 : using ParamDescriptorVec = std::vector<ParamDescriptor>; 117 : 118 : // Represents a request for admin endpoints, enabling streamed responses. 119 : class Request { 120 : public: 121 98 : virtual ~Request() = default; 122 : 123 : /** 124 : * Initiates a handler. The URL can be supplied to the constructor if needed. 125 : * 126 : * @param response_headers successful text responses don't need to modify this, 127 : * but if we want to respond with (e.g.) JSON or HTML we can can set 128 : * those here. 129 : * @return the HTTP status of the response. 130 : */ 131 : virtual Http::Code start(Http::ResponseHeaderMap& response_headers) PURE; 132 : 133 : /** 134 : * Adds the next chunk of data to the response. Note that nextChunk can 135 : * return 'true' but not add any data to the response, in which case a chunk 136 : * is not sent, and a subsequent call to nextChunk can be made later, 137 : * possibly after a post() or low-watermark callback on the http filter. 138 : * 139 : * It is not necessary for the caller to drain the response after each call; 140 : * it can leave the data in response if it's necessary to buffer the entire 141 : * response prior to sending it to the network. It is preferable to stream 142 : * the data out, draining the response buffer on each call, but not 143 : * required. 144 : * 145 : * @param response a buffer in which to write the chunk 146 : * @return whether or not any chunks follow this one. 147 : */ 148 : virtual bool nextChunk(Buffer::Instance& response) PURE; 149 : }; 150 : using RequestPtr = std::unique_ptr<Request>; 151 : 152 : /** 153 : * Lambda to generate a Request. 154 : */ 155 : using GenRequestFn = std::function<RequestPtr(AdminStream&)>; 156 : 157 : /** 158 : * Individual admin handler including prefix, help text, and callback. 159 : */ 160 : struct UrlHandler { 161 : const std::string prefix_; 162 : const std::string help_text_; 163 : const GenRequestFn handler_; 164 : const bool removable_; 165 : const bool mutates_server_state_; 166 : const ParamDescriptorVec params_{}; 167 : }; 168 : 169 : /** 170 : * Callback for admin URL handlers. 171 : * @param path_and_query supplies the path and query of the request URL. 172 : * @param response_headers enables setting of http headers (e.g., content-type, cache-control) in 173 : * the handler. 174 : * @param response supplies the buffer to fill in with the response body. 175 : * @param admin_stream supplies the filter which invoked the handler, enables the handler to use 176 : * its data. 177 : * @return Http::Code the response code. 178 : */ 179 : using HandlerCb = 180 : std::function<Http::Code(Http::ResponseHeaderMap& response_headers, 181 : Buffer::Instance& response, AdminStream& admin_stream)>; 182 : 183 : /** 184 : * Add a legacy admin handler where the entire response is written in 185 : * one chunk. 186 : * 187 : * @param prefix supplies the URL prefix to handle. 188 : * @param help_text supplies the help text for the handler. 189 : * @param callback supplies the callback to invoke when the prefix matches. 190 : * @param removable if true allows the handler to be removed via removeHandler. 191 : * @param mutates_server_state indicates whether callback will mutate server state. 192 : * @param params command parameter descriptors. 193 : * @return bool true if the handler was added, false if it was not added. 194 : */ 195 : virtual bool addHandler(const std::string& prefix, const std::string& help_text, 196 : HandlerCb callback, bool removable, bool mutates_server_state, 197 : const ParamDescriptorVec& params = {}) PURE; 198 : 199 : /** 200 : * Adds a an chunked admin handler. 201 : * 202 : * @param prefix supplies the URL prefix to handle. 203 : * @param help_text supplies the help text for the handler. 204 : * @param gen_request supplies the callback to generate a Request. 205 : * @param removable if true allows the handler to be removed via removeHandler. 206 : * @param mutates_server_state indicates whether callback will mutate server state. 207 : * @param params command parameter descriptors. 208 : * @return bool true if the handler was added, false if it was not added. 209 : */ 210 : virtual bool addStreamingHandler(const std::string& prefix, const std::string& help_text, 211 : GenRequestFn gen_request, bool removable, 212 : bool mutates_server_state, 213 : const ParamDescriptorVec& params = {}) PURE; 214 : 215 : /** 216 : * Remove an admin handler if it is removable. 217 : * @param prefix supplies the URL prefix of the handler to delete. 218 : * @return bool true if the handler was removed, false if it was not removed. 219 : */ 220 : virtual bool removeHandler(const std::string& prefix) PURE; 221 : 222 : /** 223 : * Obtain socket the admin endpoint is bound to. 224 : * @return Network::Socket& socket reference. 225 : */ 226 : virtual const Network::Socket& socket() PURE; 227 : 228 : /** 229 : * @return ConfigTracker& tracker for /config_dump endpoint. 230 : */ 231 : virtual ConfigTracker& getConfigTracker() PURE; 232 : 233 : /** 234 : * Expose this Admin console as an HTTP server. 235 : * @param access_logs access_logs list of file loggers to write the HTTP request log to. 236 : * @param address network address to bind and listen on. 237 : * @param socket_options socket options to apply to the listening socket. 238 : */ 239 : virtual void startHttpListener(std::list<AccessLog::InstanceSharedPtr> access_logs, 240 : Network::Address::InstanceConstSharedPtr address, 241 : Network::Socket::OptionsSharedPtr socket_options) PURE; 242 : 243 : /** 244 : * Executes an admin request with the specified query params. Note: this must 245 : * be called from Envoy's main thread. 246 : * 247 : * @param path_and_query the path and query of the admin URL. 248 : * @param method the HTTP method (POST or GET). 249 : * @param response_headers populated the response headers from executing the request, 250 : * most notably content-type. 251 : * @param body populated with the response-body from the admin request. 252 : * @return Http::Code The HTTP response code from the admin request. 253 : */ 254 : virtual Http::Code request(absl::string_view path_and_query, absl::string_view method, 255 : Http::ResponseHeaderMap& response_headers, std::string& body) PURE; 256 : 257 : /** 258 : * Add this Admin's listener to the provided handler, if the listener exists. 259 : * Throws an exception if the listener does not exist. 260 : * @param handler the handler that will receive this Admin's listener. 261 : */ 262 : virtual void addListenerToHandler(Network::ConnectionHandler* handler) PURE; 263 : 264 : /** 265 : * @return the number of worker threads to run in the server. 266 : */ 267 : virtual uint32_t concurrency() const PURE; 268 : 269 : /** 270 : * Makes a request for streamed static text. The version that takes the 271 : * Buffer::Instance& transfers the content from the passed-in buffer. 272 : * 273 : * @param response_text the text to populate response with 274 : * @param code the Http::Code for the response 275 : * @return the request 276 : */ 277 : static RequestPtr makeStaticTextRequest(absl::string_view response_text, Http::Code code); 278 : static RequestPtr makeStaticTextRequest(Buffer::Instance& response_text, Http::Code code); 279 : 280 : /** 281 : * Closes the listening socket for the admin. 282 : */ 283 : virtual void closeSocket() PURE; 284 : }; 285 : 286 : } // namespace Server 287 : } // namespace Envoy