userver: userver/server/handlers/http_handler_base.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
http_handler_base.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/server/handlers/http_handler_base.hpp
4/// @brief @copybrief server::handlers::HttpHandlerBase
5
6#include <memory>
7#include <optional>
8#include <string>
9#include <unordered_set>
10#include <vector>
11
12#include <userver/dynamic_config/source.hpp>
13#include <userver/logging/level.hpp>
14#include <userver/utils/statistics/entry.hpp>
15#include <userver/utils/token_bucket.hpp>
16
17#include <userver/server/handlers/exceptions.hpp>
18#include <userver/server/handlers/formatted_error_data.hpp>
19#include <userver/server/handlers/handler_base.hpp>
20#include <userver/server/http/http_request.hpp>
21#include <userver/server/http/http_response.hpp>
22#include <userver/server/http/http_response_body_stream_fwd.hpp>
23#include <userver/server/request/request_base.hpp>
24// Not needed here, but a lot of code depends on it being included transitively
25#include <userver/tracing/span.hpp>
26
27USERVER_NAMESPACE_BEGIN
28
29namespace server::middlewares {
31class HandlerAdapter;
32class Auth;
33} // namespace server::middlewares
34
35/// @brief Most common \ref userver_http_handlers "userver HTTP handlers"
36namespace server::handlers {
37
38class HttpHandlerStatistics;
39class HttpRequestStatistics;
40class HttpHandlerMethodStatistics;
41class HttpHandlerStatisticsScope;
42
43// clang-format off
44
45/// @ingroup userver_components userver_http_handlers userver_base_classes
46///
47/// @brief Base class for all the
48/// \ref userver_http_handlers "Userver HTTP Handlers".
49///
50/// ## Static options:
51/// Inherits all the options from server::handlers::HandlerBase and adds the
52/// following ones:
53///
54/// Name | Description | Default value
55/// ---- | ----------- | -------------
56/// log-level | overrides log level for this handle | <no override>
57/// status-codes-log-level | map of "status": log_level items to override span log level for specific status codes | {}
58/// middleware-pipeline-builder | name of a component to build a middleware pipeline for this particular handler | default-handler-middleware-pipeline-builder
59///
60/// ## Example usage:
61///
62/// @snippet samples/hello_service/hello_service.cpp Hello service sample - component
63
64// clang-format on
65
67 public:
68 HttpHandlerBase(const components::ComponentConfig& config,
69 const components::ComponentContext& component_context,
70 bool is_monitor = false);
71
72 ~HttpHandlerBase() override;
73
75 request::RequestContext& context) const override;
76
77 void ReportMalformedRequest(request::RequestBase& request) const final;
78
79 virtual const std::string& HandlerName() const;
80
81 const std::vector<http::HttpMethod>& GetAllowedMethods() const;
82
83 /// @cond
84 // For internal use only.
85 HttpHandlerStatistics& GetHandlerStatistics() const;
86
87 // For internal use only.
88 HttpRequestStatistics& GetRequestStatistics() const;
89 /// @endcond
90
91 /// Override it if you need a custom logging level for messages about finish
92 /// of request handling for some http statuses.
94 http::HttpStatus status) const;
95
96 virtual FormattedErrorData GetFormattedExternalErrorBody(
97 const CustomHandlerException& exc) const;
98
99 std::string GetResponseDataForLoggingChecked(
100 const http::HttpRequest& request, request::RequestContext& context,
101 const std::string& response_data) const;
102
103 /// Takes the exception and formats it into response, as specified by
104 /// exception.
105 void HandleCustomHandlerException(const http::HttpRequest& request,
106 const CustomHandlerException& ex) const;
107
108 /// Takes the exception and formats it into response as an internal server
109 /// error.
110 void HandleUnknownException(const http::HttpRequest& request,
111 const std::exception& ex) const;
112
113 /// Helper function to log an unknown exception
114 void LogUnknownException(const std::exception& ex) const;
115
116 /// Returns the default log level for the handler
117 const std::optional<logging::Level>& GetLogLevel() const;
118
119 static yaml_config::Schema GetStaticConfigSchema();
120
121 protected:
122 [[noreturn]] void ThrowUnsupportedHttpMethod(
123 const http::HttpRequest& request) const;
124
125 /// The core method for HTTP request handling.
126 /// `request` arg contains HTTP headers, full body, etc.
127 /// The method should return response body.
128 /// @note It is used only if IsStreamed() returned `false`.
129 virtual std::string HandleRequestThrow(
130 const http::HttpRequest& request, request::RequestContext& context) const;
131
132 virtual void OnRequestCompleteThrow(
133 const http::HttpRequest& /*request*/,
134 request::RequestContext& /*context*/) const {}
135
136 /// The core method for HTTP request handling.
137 /// `request` arg contains HTTP headers, full body, etc.
138 /// The response body is passed in parts to `ResponseBodyStream`.
139 /// Stream transmission is useful when:
140 /// 1) The body size is unknown beforehand.
141 /// 2) The client may take advantage of early body transmission
142 /// (e.g. a Web Browser may start rendering the HTML page
143 /// or downloading dependant resources).
144 /// 3) The body size is huge and we want to have only a part of it
145 /// in memory.
146 /// @note It is used only if IsStreamed() returned `true`.
147 virtual void HandleStreamRequest(const server::http::HttpRequest&,
148 server::request::RequestContext&,
149 server::http::ResponseBodyStream&) const;
150
151 /// If IsStreamed() returns `true`, call HandleStreamRequest()
152 /// for request handling, HandleRequestThrow() is not called.
153 /// If it returns `false`, HandleRequestThrow() is called instead,
154 /// and HandleStreamRequest() is not called.
155 /// @note The default implementation returns the cached value of
156 /// "response-body-streamed" value from static config.
157 virtual bool IsStreamed() const { return is_body_streamed_; }
158
159 /// Override it to show per HTTP-method statistics besides statistics for all
160 /// methods
161 virtual bool IsMethodStatisticIncluded() const { return false; }
162
163 /// Override it if you want to disable auth checks in handler by some
164 /// condition
165 virtual bool NeedCheckAuth() const { return true; }
166
167 /// Override it if you need a custom request body logging.
168 virtual std::string GetRequestBodyForLogging(
169 const http::HttpRequest& request, request::RequestContext& context,
170 const std::string& request_body) const;
171
172 /// Override it if you need a custom response data logging.
173 virtual std::string GetResponseDataForLogging(
174 const http::HttpRequest& request, request::RequestContext& context,
175 const std::string& response_data) const;
176
177 /// For internal use. You don't need to override it. This method is overridden
178 /// in format-specific base handlers.
179 virtual void ParseRequestData(const http::HttpRequest&,
180 request::RequestContext&) const {}
181
182 virtual std::string GetMetaType(const http::HttpRequest&) const;
183
184 private:
185 friend class middlewares::HandlerAdapter;
186 friend class middlewares::Auth;
187
188 void HandleHttpRequest(http::HttpRequest& request,
189 request::RequestContext& context) const;
190
191 void HandleRequestStream(const http::HttpRequest& http_request,
192 request::RequestContext& context) const;
193
194 std::string GetRequestBodyForLoggingChecked(
195 const http::HttpRequest& request, request::RequestContext& context,
196 const std::string& request_body) const;
197
198 template <typename HttpStatistics>
199 void FormatStatistics(utils::statistics::Writer result,
200 const HttpStatistics& stats);
201
202 void SetResponseServerHostname(http::HttpResponse& response) const;
203
204 void BuildMiddlewarePipeline(const components::ComponentConfig&,
205 const components::ComponentContext&);
206
207 const dynamic_config::Source config_source_;
208 const std::vector<http::HttpMethod> allowed_methods_;
209 const std::string handler_name_;
210 utils::statistics::Entry statistics_holder_;
211 std::optional<logging::Level> log_level_;
212 std::unordered_map<int, logging::Level> log_level_for_status_codes_;
213
214 std::unique_ptr<HttpHandlerStatistics> handler_statistics_;
215 std::unique_ptr<HttpRequestStatistics> request_statistics_;
216
217 bool set_response_server_hostname_;
218 bool is_body_streamed_;
219
220 std::unique_ptr<middlewares::HttpMiddlewareBase> first_middleware_;
221};
222
223} // namespace server::handlers
224
225USERVER_NAMESPACE_END