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