userver: userver/clients/http/plugin.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
plugin.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/clients/http/plugin.hpp
4/// @brief @copybrief clients::http::Plugin
5
6#include <chrono>
7#include <string>
8#include <system_error>
9#include <vector>
10
11#include <userver/utils/not_null.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace tracing {
16class Span;
17}
18
19namespace clients::http {
20
21class RequestState;
22class Response;
23
24/// @brief Auxiliary entity that allows editing request to a client
25/// from plugins
26class PluginRequest final {
27public:
28 /// @cond
29 explicit PluginRequest(RequestState& state);
30 /// @endcond
31
32 void SetHeader(std::string_view name, std::string_view value);
33
34 void AddQueryParams(std::string_view params);
35
36 void SetTimeout(std::chrono::milliseconds ms);
37
38 const std::string& GetOriginalUrl() const;
39
40private:
41 RequestState& state_;
42};
43
44/// @brief Base class for HTTP Client plugins
45class Plugin {
46public:
47 explicit Plugin(std::string name);
48
49 virtual ~Plugin() = default;
50
51 /// @brief Get plugin name
52 const std::string& GetName() const;
53
54 /// @brief The hook is called just after the "external" Span is created.
55 /// You might want to add custom tags from the hook.
56 /// The hook is called only once before any network interaction and is NOT called before each retry.
57 /// The hook is executed in the context of the parent task which created the request.
58 virtual void HookCreateSpan(PluginRequest& request, tracing::Span& span) = 0;
59
60 /// @brief The hook is called before actual HTTP request sending and before
61 /// DNS name resolution.
62 /// This hook is called on each retry.
63 ///
64 /// @warning The hook is called in libev thread, not in coroutine context! Do
65 /// not do any heavy work here, offload it to other hooks.
66 virtual void HookPerformRequest(PluginRequest& request) = 0;
67
68 /// @brief The hook is called after the HTTP response is received. It does not
69 /// include timeout, network or other error.
70 ///
71 /// @warning The hook is called in libev thread, not in coroutine context! Do
72 /// not do any heavy work here, offload it to other hooks.
73 virtual void HookOnCompleted(PluginRequest& request, Response& response) = 0;
74
75 /// @brief The hook is called on timeout and other errors. The hook is not called
76 /// for error HTTP responses, use HookOnCompleted instead.
77 ///
78 /// @warning The hook is called in libev thread, not in coroutine context! Do
79 /// not do any heavy work here, offload it to other hooks.
80 virtual void HookOnError(PluginRequest& request, std::error_code ec) = 0;
81
82 /// @brief The hook is called before every call attempt except the first one.
83 /// @return whether the retry is allowed.
84 virtual bool HookOnRetry(PluginRequest& request) = 0;
85
86private:
87 const std::string name_;
88};
89
90namespace impl {
91
92class PluginPipeline final {
93public:
94 PluginPipeline(const std::vector<utils::NotNull<Plugin*>>& plugins);
95
96 void HookPerformRequest(RequestState& request);
97
98 void HookCreateSpan(RequestState& request, tracing::Span& span);
99
100 void HookOnCompleted(RequestState& request, Response& response);
101
102 void HookOnError(RequestState& request, std::error_code ec);
103
104 bool HookOnRetry(RequestState& request);
105
106private:
107 const std::vector<utils::NotNull<Plugin*>> plugins_;
108};
109
110} // namespace impl
111
112} // namespace clients::http
113
114USERVER_NAMESPACE_END