userver: userver/server/http/http_response.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_response.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/server/http/http_response.hpp
4/// @brief @copybrief server::http::HttpResponse
5
6#include <chrono>
7#include <string>
8#include <unordered_map>
9
10#include <userver/concurrent/queue.hpp>
11#include <userver/engine/single_consumer_event.hpp>
12#include <userver/http/content_type.hpp>
13#include <userver/http/header_map.hpp>
14#include <userver/server/http/http_response_cookie.hpp>
15#include <userver/server/request/response_base.hpp>
16#include <userver/utils/impl/projecting_view.hpp>
17#include <userver/utils/str_icase.hpp>
18
19#include "http_status.hpp"
20
21USERVER_NAMESPACE_BEGIN
22
23namespace server::http {
24
25namespace impl {
26
27void OutputHeader(std::string& header, std::string_view key,
28 std::string_view val);
29
30}
31
32class HttpRequestImpl;
33
34/// @brief HTTP Response data
35class HttpResponse final : public request::ResponseBase {
36 public:
37 using HeadersMap = USERVER_NAMESPACE::http::headers::HeaderMap;
38
39 using HeadersMapKeys = decltype(utils::impl::MakeKeysView(HeadersMap()));
40
41 using CookiesMap = Cookie::CookiesMap;
42
43 using CookiesMapKeys = decltype(utils::impl::MakeKeysView(CookiesMap()));
44
45 /// @cond
46 HttpResponse(const HttpRequestImpl& request,
47 request::ResponseDataAccounter& data_accounter);
48 ~HttpResponse() override;
49
50 void SetSendFailed(
51 std::chrono::steady_clock::time_point failure_time) override;
52 /// @endcond
53
54 /// @brief Add a new response header or rewrite an existing one.
55 /// @returns true if the header was set. Returns false if headers
56 /// were already sent for stream'ed response and the new header was not set.
57 bool SetHeader(std::string name, std::string value);
58
59 /// @brief Add a new response header or rewrite an existing one.
60 /// @returns true if the header was set. Returns false if headers
61 /// were already sent for stream'ed response and the new header was not set.
62 bool SetHeader(std::string_view name, std::string value);
63
64 /// @overload
66 const USERVER_NAMESPACE::http::headers::PredefinedHeader& header,
67 std::string value);
68
69 /// @brief Add or rewrite the Content-Type header.
70 void SetContentType(const USERVER_NAMESPACE::http::ContentType& type);
71
72 /// @brief Add or rewrite the Content-Encoding header.
73 void SetContentEncoding(std::string encoding);
74
75 /// @brief Set the HTTP response status code.
76 /// @returns true if the status was set. Returns false if headers
77 /// were already sent for stream'ed response and the new status was not set.
78 bool SetStatus(HttpStatus status);
79
80 /// @brief Remove all headers from response.
81 /// @returns true if the headers were cleared. Returns false if headers
82 /// were already sent for stream'ed response and the headers were not cleared.
84
85 /// @brief Sets a cookie if it was not set before.
86 void SetCookie(Cookie cookie);
87
88 /// @brief Remove all cookies from response.
90
91 /// @return HTTP response status
92 HttpStatus GetStatus() const { return status_; }
93
94 /// @return List of HTTP headers names.
96
97 /// @return Value of the header with case insensitive name header_name, or an
98 /// empty string if no such header.
99 const std::string& GetHeader(std::string_view header_name) const;
100 /// @overload
101 const std::string& GetHeader(
102 const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name)
103 const;
104
105 /// @return true if header with case insensitive name header_name exists,
106 /// false otherwise.
107 bool HasHeader(std::string_view header_name) const;
108 /// @overload
109 bool HasHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader&
110 header_name) const;
111
112 /// @return List of cookies names.
114
115 /// @return Value of the cookie with case sensitive name cookie_name, or an
116 /// empty string if no such cookie exists.
117 const Cookie& GetCookie(std::string_view cookie_name) const;
118
119 /// @cond
120 // TODO: server internals. remove from public interface
121 void SendResponse(engine::io::RwBase& socket) override;
122 /// @endcond
123
124 void SetStatusServiceUnavailable() override {
125 SetStatus(HttpStatus::kServiceUnavailable);
126 }
127 void SetStatusOk() override { SetStatus(HttpStatus::kOk); }
128 void SetStatusNotFound() override { SetStatus(HttpStatus::kNotFound); }
129
130 bool WaitForHeadersEnd() override;
131 void SetHeadersEnd() override;
132
133 using Queue = concurrent::StringStreamQueue;
134
135 void SetStreamBody();
136 bool IsBodyStreamed() const override;
137 // Can be called only once
138 Queue::Producer GetBodyProducer();
139
140 private:
141 // Returns total size of the response
142 std::size_t SetBodyStreamed(engine::io::RwBase& socket, std::string& header);
143
144 // Returns total size of the response
145 std::size_t SetBodyNotStreamed(engine::io::RwBase& socket,
146 std::string& header);
147
148 const HttpRequestImpl& request_;
149 HttpStatus status_ = HttpStatus::kOk;
150 HeadersMap headers_;
151 CookiesMap cookies_;
152
153 engine::SingleConsumerEvent headers_end_;
154 std::optional<Queue::Consumer> body_stream_;
155 std::optional<Queue::Producer> body_stream_producer_;
156};
157
158void SetThrottleReason(http::HttpResponse& http_response,
159 std::string log_reason, std::string http_header_reason);
160
161} // namespace server::http
162
163USERVER_NAMESPACE_END