userver: userver/server/http/http_response.hpp Source File
Loading...
Searching...
No Matches
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