Seastar
High performance C++ framework for concurrent servers
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 
44 namespace seastar {
45 
46 SEASTAR_MODULE_EXPORT_BEGIN
47 
48 namespace httpd {
49 
50 class connection;
51 class routes;
52 
53 }
54 
55 namespace http {
56 
60 struct reply {
64  enum class status_type {
65  continue_ = 100,
66  switching_protocols = 101,
67  ok = 200,
68  created = 201,
69  accepted = 202,
71  no_content = 204,
72  reset_content = 205,
73  partial_content = 206,
74  multiple_choices = 300,
75  moved_permanently = 301,
76  moved_temporarily = 302,
77  see_other = 303,
78  not_modified = 304,
79  use_proxy = 305,
80  temporary_redirect = 307,
81  bad_request = 400,
82  unauthorized = 401,
83  payment_required = 402,
84  forbidden = 403,
85  not_found = 404,
86  method_not_allowed = 405,
87  not_acceptable = 406,
88  request_timeout = 408,
89  conflict = 409,
90  gone = 410,
91  length_required = 411,
92  payload_too_large = 413,
93  uri_too_long = 414,
95  expectation_failed = 417,
96  unprocessable_entity = 422,
97  upgrade_required = 426,
98  too_many_requests = 429,
99  internal_server_error = 500,
100  not_implemented = 501,
101  bad_gateway = 502,
102  service_unavailable = 503,
103  gateway_timeout = 504,
105  insufficient_storage = 507
106  } _status;
107 
111  std::unordered_map<sstring, sstring, seastar::internal::case_insensitive_hash, seastar::internal::case_insensitive_cmp> _headers;
112 
113  sstring _version;
117  sstring _content;
118  size_t content_length = 0; // valid when received via client connection
119 
120  sstring _response_line;
121  std::unordered_map<sstring, sstring> trailing_headers;
122  std::unordered_map<sstring, sstring> chunk_extensions;
123 
124  reply()
125  : _status(status_type::ok) {
126  }
127 
128  reply& add_header(const sstring& h, const sstring& value) {
129  _headers[h] = value;
130  return *this;
131  }
132 
138  sstring get_header(const sstring& name) const {
139  auto res = _headers.find(name);
140  if (res == _headers.end()) {
141  return "";
142  }
143  return res->second;
144  }
145 
146  reply& set_version(const sstring& version) {
147  _version = version;
148  return *this;
149  }
150 
151  reply& set_status(status_type status, sstring content = "") {
152  _status = status;
153  if (content != "") {
154  _content = std::move(content);
155  }
156  return *this;
157  }
158 
164  reply& set_mime_type(const sstring& mime) {
165  _headers["Content-Type"] = mime;
166  return *this;
167  }
168 
173  reply& set_content_type(const sstring& content_type = "html") {
174  set_mime_type(http::mime_types::extension_to_type(content_type));
175  return *this;
176  }
177 
178  reply& done(const sstring& content_type) {
179  return set_content_type(content_type).done();
180  }
185  reply& done() {
186  _response_line = response_line();
187  return *this;
188  }
189  sstring response_line();
190 
207  void write_body(const sstring& content_type, noncopyable_function<future<>(output_stream<char>&&)>&& body_writer);
208 
218  void write_body(const sstring& content_type, sstring content);
219 
220 private:
221  future<> write_reply_to_connection(httpd::connection& con);
222  future<> write_reply_headers(httpd::connection& connection);
223 
225  friend class httpd::routes;
226  friend class httpd::connection;
227 };
228 
229 std::ostream& operator<<(std::ostream& os, reply::status_type st);
230 
231 } // namespace http
232 
233 namespace httpd {
234 using reply [[deprecated("Use http::reply instead")]] = http::reply;
235 }
236 
237 SEASTAR_MODULE_EXPORT_END
238 }
239 
240 #if FMT_VERSION >= 90000
241 template <> struct fmt::formatter<seastar::http::reply::status_type> : fmt::ostream_formatter {};
242 #endif
Definition: httpd.hh:74
Definition: routes.hh:81
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: reply.hh:60
void write_body(const sstring &content_type, noncopyable_function< future<>(output_stream< char > &&)> &&body_writer)
use an output stream to write the message body
std::unordered_map< sstring, sstring, seastar::internal::case_insensitive_hash, seastar::internal::case_insensitive_cmp > _headers
Definition: reply.hh:111
sstring get_header(const sstring &name) const
Definition: reply.hh:138
status_type
Definition: reply.hh:64
@ temporary_redirect
temporary_redirect
@ unprocessable_entity
unprocessable_entity
@ moved_temporarily
moved_temporarily
@ upgrade_required
upgrade_required
@ nonauthoritative_information
nonauthoritative_information
@ service_unavailable
service_unavailable
@ moved_permanently
moved_permanently
@ payload_too_large
payload_too_large
@ insufficient_storage
insufficient_storage
@ expectation_failed
expectation_failed
@ too_many_requests
too_many_requests
@ unsupported_media_type
unsupported_media_type
@ switching_protocols
switching_protocols
@ internal_server_error
internal_server_error
@ method_not_allowed
method_not_allowed
@ payment_required
payment_required
@ http_version_not_supported
http_version_not_supported
reply & done()
Definition: reply.hh:185
reply & set_mime_type(const sstring &mime)
Definition: reply.hh:164
reply & set_content_type(const sstring &content_type="html")
Definition: reply.hh:173
sstring _content
Definition: reply.hh:117
void write_body(const sstring &content_type, sstring content)
Write a string as the reply.