userver: userver/server/handlers/http_handler_base.hpp Source File
Loading...
Searching...
No Matches
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 <optional>
7#include <string>
8#include <unordered_set>
9#include <vector>
10
11#include <userver/dynamic_config/source.hpp>
12#include <userver/logging/level.hpp>
13#include <userver/utils/statistics/entry.hpp>
14#include <userver/utils/token_bucket.hpp>
15
16#include <userver/server/handlers/auth/auth_checker_base.hpp>
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#include <userver/tracing/span.hpp>
25
26USERVER_NAMESPACE_BEGIN
27
28namespace tracing {
30} // namespace tracing
31
32/// @brief Most common \ref userver_http_handlers "userver HTTP handlers"
33namespace server::handlers {
34
35class HttpHandlerStatistics;
36class HttpRequestStatistics;
37class HttpHandlerMethodStatistics;
38class HttpHandlerStatisticsScope;
39
40// clang-format off
41
42/// @ingroup userver_components userver_http_handlers userver_base_classes
43///
44/// @brief Base class for all the
45/// \ref userver_http_handlers "Userver HTTP Handlers".
46///
47/// ## Static options:
48/// Inherits all the options from server::handlers::HandlerBase and adds the
49/// following ones:
50///
51/// Name | Description | Default value
52/// ---- | ----------- | -------------
53/// log-level | overrides log level for this handle | <no override>
54/// status-codes-log-level | map of "status": log_level items to override span log level for specific status codes | {}
55///
56/// ## Example usage:
57///
58/// @snippet samples/hello_service/hello_service.cpp Hello service sample - component
59
60// clang-format on
61
63 public:
64 HttpHandlerBase(const components::ComponentConfig& config,
65 const components::ComponentContext& component_context,
66 bool is_monitor = false);
67
68 ~HttpHandlerBase() override;
69
71 request::RequestContext& context) const override;
72
73 void ReportMalformedRequest(request::RequestBase& request) const final;
74
75 virtual const std::string& HandlerName() const;
76
77 const std::vector<http::HttpMethod>& GetAllowedMethods() const;
78
79 /// @cond
80 // For internal use only.
81 HttpHandlerStatistics& GetHandlerStatistics() const;
82
83 // For internal use only.
84 HttpRequestStatistics& GetRequestStatistics() const;
85 /// @endcond
86
87 /// Override it if you need a custom logging level for messages about finish
88 /// of request handling for some http statuses.
90 http::HttpStatus status) const;
91
92 virtual FormattedErrorData GetFormattedExternalErrorBody(
93 const CustomHandlerException& exc) const;
94
95 std::string GetResponseDataForLoggingChecked(
96 const http::HttpRequest& request, request::RequestContext& context,
97 const std::string& response_data) const;
98
99 static yaml_config::Schema GetStaticConfigSchema();
100
101 protected:
102 [[noreturn]] void ThrowUnsupportedHttpMethod(
103 const http::HttpRequest& request) const;
104
105 /// The core method for HTTP request handling.
106 /// `request` arg contains HTTP headers, full body, etc.
107 /// The method should return response body.
108 /// @note It is used only if IsStreamed() returned `false`.
109 virtual std::string HandleRequestThrow(
110 const http::HttpRequest& request, request::RequestContext& context) const;
111
112 virtual void OnRequestCompleteThrow(
113 const http::HttpRequest& /*request*/,
114 request::RequestContext& /*context*/) const {}
115
116 /// The core method for HTTP request handling.
117 /// `request` arg contains HTTP headers, full body, etc.
118 /// The response body is passed in parts to `ResponseBodyStream`.
119 /// Stream transmission is useful when:
120 /// 1) The body size is unknown beforehand.
121 /// 2) The client may take advantage of early body transmission
122 /// (e.g. a Web Browser may start rendering the HTML page
123 /// or downloading dependant resources).
124 /// 3) The body size is huge and we want to have only a part of it
125 /// in memory.
126 /// @note It is used only if IsStreamed() returned `true`.
127 virtual void HandleStreamRequest(const server::http::HttpRequest&,
128 server::request::RequestContext&,
129 server::http::ResponseBodyStream&) const;
130
131 /// If IsStreamed() returns `true`, call HandleStreamRequest()
132 /// for request handling, HandleRequestThrow() is not called.
133 /// If it returns `false`, HandleRequestThrow() is called instead,
134 /// and HandleStreamRequest() is not called.
135 /// @note The default implementation returns the cached value of
136 /// "response-body-streamed" value from static config.
137 virtual bool IsStreamed() const { return is_body_streamed_; }
138
139 /// Override it to show per HTTP-method statistics besides statistics for all
140 /// methods
141 virtual bool IsMethodStatisticIncluded() const { return false; }
142
143 /// Override it if you want to disable auth checks in handler by some
144 /// condition
145 virtual bool NeedCheckAuth() const { return true; }
146
147 /// Override it if you need a custom request body logging.
148 virtual std::string GetRequestBodyForLogging(
149 const http::HttpRequest& request, request::RequestContext& context,
150 const std::string& request_body) const;
151
152 /// Override it if you need a custom response data logging.
153 virtual std::string GetResponseDataForLogging(
154 const http::HttpRequest& request, request::RequestContext& context,
155 const std::string& response_data) const;
156
157 /// For internal use. You don't need to override it. This method is overridden
158 /// in format-specific base handlers.
159 virtual void ParseRequestData(const http::HttpRequest&,
160 request::RequestContext&) const {}
161
162 virtual std::string GetMetaType(const http::HttpRequest&) const;
163
164 private:
165 void HandleRequestStream(const http::HttpRequest& http_request,
166 request::RequestContext& context) const;
167
168 std::string GetRequestBodyForLoggingChecked(
169 const http::HttpRequest& request, request::RequestContext& context,
170 const std::string& request_body) const;
171
172 tracing::Span MakeSpan(const http::HttpRequest& http_request,
173 const std::string& meta_type) const;
174
175 void CheckAuth(const http::HttpRequest& http_request,
176 request::RequestContext& context,
177 const dynamic_config::Snapshot& initial_config) const;
178
179 void CheckRatelimit(const http::HttpRequest& http_request) const;
180
181 void DecompressRequestBody(http::HttpRequest& http_request) const;
182
183 template <typename HttpStatistics>
184 void FormatStatistics(utils::statistics::Writer result,
185 const HttpStatistics& stats);
186
187 void SetResponseAcceptEncoding(http::HttpResponse& response) const;
188 void SetResponseServerHostname(http::HttpResponse& response) const;
189
190 const dynamic_config::Source config_source_;
191 const std::vector<http::HttpMethod> allowed_methods_;
192 const std::string handler_name_;
193 utils::statistics::Entry statistics_holder_;
194 const tracing::TracingManagerBase& tracing_manager_;
195 std::unordered_map<int, logging::Level> log_level_for_status_codes_;
196
197 std::unique_ptr<HttpHandlerStatistics> handler_statistics_;
198 std::unique_ptr<HttpRequestStatistics> request_statistics_;
199 std::vector<auth::AuthCheckerBasePtr> auth_checkers_;
200
201 std::optional<logging::Level> log_level_;
202 bool set_response_server_hostname_;
203 mutable utils::TokenBucket rate_limit_;
204 bool is_body_streamed_;
205};
206
207} // namespace server::handlers
208
209USERVER_NAMESPACE_END