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(USERVER_NAMESPACE::http::headers::HeadersString& header,
28 std::string_view key, std::string_view val);
29
30} // namespace impl
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(const HttpRequestImpl& request,
49 request::ResponseDataAccounter& data_accounter,
50 std::chrono::steady_clock::time_point now,
51 utils::StrCaseHash hasher);
52 ~HttpResponse() override;
53
54 void SetSendFailed(
55 std::chrono::steady_clock::time_point failure_time) override;
56 /// @endcond
57
58 /// @brief Add a new response header or rewrite an existing one.
59 /// @returns true if the header was set. Returns false if headers
60 /// were already sent for stream'ed response and the new header was not set.
61 bool SetHeader(std::string name, std::string value);
62
63 /// @brief Add a new response header or rewrite an existing one.
64 /// @returns true if the header was set. Returns false if headers
65 /// were already sent for stream'ed response and the new header was not set.
66 bool SetHeader(std::string_view name, std::string value);
67
68 /// @overload
70 const USERVER_NAMESPACE::http::headers::PredefinedHeader& header,
71 std::string value);
72
73 /// @brief Add or rewrite the Content-Type header.
74 void SetContentType(const USERVER_NAMESPACE::http::ContentType& type);
75
76 /// @brief Add or rewrite the Content-Encoding header.
77 void SetContentEncoding(std::string encoding);
78
79 /// @brief Set the HTTP response status code.
80 /// @returns true if the status was set. Returns false if headers
81 /// were already sent for stream'ed response and the new status was not set.
82 bool SetStatus(HttpStatus status);
83
84 /// @brief Remove all headers from response.
85 /// @returns true if the headers were cleared. Returns false if headers
86 /// were already sent for stream'ed response and the headers were not cleared.
88
89 /// @brief Sets a cookie if it was not set before.
90 void SetCookie(Cookie cookie);
91
92 /// @brief Remove all cookies from response.
94
95 /// @return HTTP response status
96 HttpStatus GetStatus() const { return status_; }
97
98 /// @return List of HTTP headers names.
100
101 /// @return Value of the header with case insensitive name header_name, or an
102 /// empty string if no such header.
103 const std::string& GetHeader(std::string_view header_name) const;
104 /// @overload
105 const std::string& GetHeader(
106 const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name)
107 const;
108
109 /// @return true if header with case insensitive name header_name exists,
110 /// false otherwise.
111 bool HasHeader(std::string_view header_name) const;
112 /// @overload
113 bool HasHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader&
114 header_name) const;
115
116 /// @return List of cookies names.
118
119 /// @return Value of the cookie with case sensitive name cookie_name, or an
120 /// empty string if no such cookie exists.
121 const Cookie& GetCookie(std::string_view cookie_name) const;
122
123 /// @cond
124 // TODO: server internals. remove from public interface
125 void SendResponse(engine::io::RwBase& socket) override;
126 /// @endcond
127
128 void SetStatusServiceUnavailable() override {
129 SetStatus(HttpStatus::kServiceUnavailable);
130 }
131 void SetStatusOk() override { SetStatus(HttpStatus::kOk); }
132 void SetStatusNotFound() override { SetStatus(HttpStatus::kNotFound); }
133
134 bool WaitForHeadersEnd() override;
135 void SetHeadersEnd() override;
136
137 using Queue = concurrent::StringStreamQueue;
138
139 void SetStreamBody();
140 bool IsBodyStreamed() const override;
141 // Can be called only once
142 Queue::Producer GetBodyProducer();
143
144 private:
145 // Returns total size of the response
146 std::size_t SetBodyStreamed(
147 engine::io::RwBase& socket,
148 USERVER_NAMESPACE::http::headers::HeadersString& header);
149
150 // Returns total size of the response
151 std::size_t SetBodyNotStreamed(
152 engine::io::RwBase& socket,
153 USERVER_NAMESPACE::http::headers::HeadersString& header);
154
155 const HttpRequestImpl& request_;
156 HttpStatus status_ = HttpStatus::kOk;
157 HeadersMap headers_;
158 CookiesMap cookies_;
159
160 engine::SingleConsumerEvent headers_end_{
161 engine::SingleConsumerEvent::NoAutoReset()};
162 std::optional<Queue::Consumer> body_stream_;
163 std::optional<Queue::Producer> body_stream_producer_;
164};
165
166void SetThrottleReason(http::HttpResponse& http_response,
167 std::string log_reason, std::string http_header_reason);
168
169} // namespace server::http
170
171USERVER_NAMESPACE_END