Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
reply.hh
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright 2015 Cloudius Systems
20 */
21
22// This file was modified from boost http example
23//
24// reply.hpp
25// ~~~~~~~~~
26//
27// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
28//
29// Distributed under the Boost Software License, Version 1.0. (See accompanying
30// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
31//
32#pragma once
33
34#ifndef SEASTAR_MODULE
35#include <unordered_map>
36#endif
37#include <seastar/core/sstring.hh>
38#include <seastar/http/mime_types.hh>
39#include <seastar/core/iostream.hh>
40#include <seastar/util/noncopyable_function.hh>
41#include <seastar/util/modules.hh>
42#include <seastar/util/string_utils.hh>
43#include <seastar/util/iostream.hh>
44
45namespace seastar {
46
47SEASTAR_MODULE_EXPORT_BEGIN
48
49namespace httpd {
50
51class connection;
52class routes;
53
54}
55
56namespace http {
57
61struct reply {
65 enum class status_type {
66 continue_ = 100,
67 switching_protocols = 101,
68 ok = 200,
69 created = 201,
70 accepted = 202,
71 nonauthoritative_information = 203,
72 no_content = 204,
73 reset_content = 205,
74 partial_content = 206,
75 multiple_choices = 300,
76 moved_permanently = 301,
77 moved_temporarily = 302,
78 see_other = 303,
79 not_modified = 304,
80 use_proxy = 305,
81 temporary_redirect = 307,
82 bad_request = 400,
83 unauthorized = 401,
84 payment_required = 402,
85 forbidden = 403,
86 not_found = 404,
87 method_not_allowed = 405,
88 not_acceptable = 406,
89 request_timeout = 408,
90 conflict = 409,
91 gone = 410,
92 length_required = 411,
93 payload_too_large = 413,
94 uri_too_long = 414,
95 unsupported_media_type = 415,
96 expectation_failed = 417,
97 page_expired = 419,
98 unprocessable_entity = 422,
99 upgrade_required = 426,
100 too_many_requests = 429,
101 login_timeout = 440,
102 internal_server_error = 500,
103 not_implemented = 501,
104 bad_gateway = 502,
105 service_unavailable = 503,
106 gateway_timeout = 504,
107 http_version_not_supported = 505,
108 insufficient_storage = 507,
109 bandwidth_limit_exceeded = 509,
110 network_read_timeout = 598,
111 network_connect_timeout = 599,
112 } _status;
113
124 enum class status_class : uint8_t {
125 informational = 1,
126 success = 2,
127 redirection = 3,
128 client_error = 4,
129 server_error = 5,
130 unclassified
131 };
132
138 static constexpr status_class classify_status(status_type http_status) {
139 auto sc = static_cast<std::underlying_type_t<status_type>>(http_status) / 100;
140 if (sc < 1 || sc > 5) [[unlikely]] {
141 return status_class::unclassified;
142 }
143 return static_cast<status_class>(sc);
144 }
145
149 std::unordered_map<sstring, sstring, seastar::internal::case_insensitive_hash, seastar::internal::case_insensitive_cmp> _headers;
150
151 sstring _version;
155 sstring _content;
156 size_t content_length = 0; // valid when received via client connection
157
158 sstring _response_line;
159 std::unordered_map<sstring, sstring> trailing_headers;
160 std::unordered_map<sstring, sstring> chunk_extensions;
161
162 reply()
163 : _status(status_type::ok) {
164 }
165
166 reply& add_header(const sstring& h, const sstring& value) {
167 _headers[h] = value;
168 return *this;
169 }
170
176 sstring get_header(const sstring& name) const {
177 auto res = _headers.find(name);
178 if (res == _headers.end()) {
179 return "";
180 }
181 return res->second;
182 }
183
184 reply& set_version(const sstring& version) {
185 _version = version;
186 return *this;
187 }
188
189 reply& set_status(status_type status, sstring content = "") {
190 _status = status;
191 if (content != "") {
192 _content = std::move(content);
193 }
194 return *this;
195 }
196
202 reply& set_mime_type(const sstring& mime) {
203 _headers["Content-Type"] = mime;
204 return *this;
205 }
206
211 reply& set_content_type(const sstring& content_type = "html") {
212 set_mime_type(http::mime_types::extension_to_type(content_type));
213 return *this;
214 }
215
216 reply& done(const sstring& content_type) {
217 return set_content_type(content_type).done();
218 }
224 _response_line = response_line();
225 return *this;
226 }
227 sstring response_line() const;
228
245 void write_body(const sstring& content_type, noncopyable_function<future<>(output_stream<char>&&)>&& body_writer);
246
253 template <typename W>
254 requires std::is_invocable_r_v<future<>, W, output_stream<char>&>
255 void write_body(const sstring& content_type, W&& body_writer) {
256 write_body(content_type, [body_writer = std::move(body_writer)] (output_stream<char>&& out) mutable -> future<> {
257 return util::write_to_stream_and_close(std::move(out), std::move(body_writer));
258 });
259 }
260
270 void write_body(const sstring& content_type, sstring content);
271
272private:
273 future<> write_reply_to_connection(httpd::connection& con);
274 future<> write_reply_headers(httpd::connection& connection);
275
277 friend class httpd::routes;
278 friend class httpd::connection;
279};
280
281std::ostream& operator<<(std::ostream& os, reply::status_type st);
282
283} // namespace http
284
285namespace httpd {
286using reply [[deprecated("Use http::reply instead")]] = http::reply;
287}
288
289SEASTAR_MODULE_EXPORT_END
290}
291
292#if FMT_VERSION >= 90000
293template <> struct fmt::formatter<seastar::http::reply::status_type> : fmt::ostream_formatter {};
294#endif
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
Definition: httpd.hh:69
Definition: routes.hh:81
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: reply.hh:61
void write_body(const sstring &content_type, noncopyable_function< future<>(output_stream< char > &&)> &&body_writer)
use an output stream to write the message body
static constexpr status_class classify_status(status_type http_status)
Definition: reply.hh:138
std::unordered_map< sstring, sstring, seastar::internal::case_insensitive_hash, seastar::internal::case_insensitive_cmp > _headers
Definition: reply.hh:149
status_class
Definition: reply.hh:124
reply & set_mime_type(const sstring &mime)
Definition: reply.hh:202
sstring get_header(const sstring &name) const
Definition: reply.hh:176
status_type
Definition: reply.hh:65
reply & done()
Definition: reply.hh:223
sstring _content
Definition: reply.hh:155
reply & set_content_type(const sstring &content_type="html")
Definition: reply.hh:211
void write_body(const sstring &content_type, W &&body_writer)
use and output stream to write the message body
Definition: reply.hh:255
void write_body(const sstring &content_type, sstring content)
Write a string as the reply.