]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/http/reply.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / seastar / src / http / reply.cc
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 //
23 // response.cpp
24 // ~~~~~~~~~
25 //
26 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
27 //
28 // Distributed under the Boost Software License, Version 1.0. (See accompanying
29 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
30 //
31 #include <seastar/http/reply.hh>
32 #include <seastar/core/print.hh>
33 #include <seastar/http/httpd.hh>
34 #include <seastar/http/common.hh>
35 #include <seastar/http/response_parser.hh>
36 #include <seastar/core/loop.hh>
37
38 namespace seastar {
39
40 namespace http {
41
42 namespace status_strings {
43
44 const sstring continue_ = "100 Continue";
45 const sstring switching_protocols = "101 Switching Protocols";
46 const sstring ok = "200 OK";
47 const sstring created = "201 Created";
48 const sstring accepted = "202 Accepted";
49 const sstring nonauthoritative_information = "203 Non-Authoritative Information";
50 const sstring no_content = "204 No Content";
51 const sstring reset_content = "205 Reset Content";
52 const sstring partial_content = "206 Partial Content";
53 const sstring multiple_choices = "300 Multiple Choices";
54 const sstring moved_permanently = "301 Moved Permanently";
55 const sstring moved_temporarily = "302 Moved Temporarily";
56 const sstring see_other = "303 See Other";
57 const sstring not_modified = "304 Not Modified";
58 const sstring use_proxy = "305 Use Proxy";
59 const sstring temporary_redirect = "307 Temporary Redirect";
60 const sstring bad_request = "400 Bad Request";
61 const sstring unauthorized = "401 Unauthorized";
62 const sstring payment_required = "402 Payment Required";
63 const sstring forbidden = "403 Forbidden";
64 const sstring not_found = "404 Not Found";
65 const sstring method_not_allowed = "405 Method Not Allowed";
66 const sstring not_acceptable = "406 Not Acceptable";
67 const sstring request_timeout = "408 Request Timeout";
68 const sstring conflict = "409 Conflict";
69 const sstring gone = "410 Gone";
70 const sstring length_required = "411 Length Required";
71 const sstring payload_too_large = "413 Payload Too Large";
72 const sstring uri_too_long = "414 URI Too Long";
73 const sstring unsupported_media_type = "415 Unsupported Media Type";
74 const sstring expectation_failed = "417 Expectation Failed";
75 const sstring unprocessable_entity = "422 Unprocessable Entity";
76 const sstring upgrade_required = "426 Upgrade Required";
77 const sstring too_many_requests = "429 Too Many Requests";
78 const sstring internal_server_error = "500 Internal Server Error";
79 const sstring not_implemented = "501 Not Implemented";
80 const sstring bad_gateway = "502 Bad Gateway";
81 const sstring service_unavailable = "503 Service Unavailable";
82 const sstring gateway_timeout = "504 Gateway Timeout";
83 const sstring http_version_not_supported = "505 HTTP Version Not Supported";
84 const sstring insufficient_storage = "507 Insufficient Storage";
85
86 static const sstring& to_string(reply::status_type status) {
87 switch (status) {
88 case reply::status_type::continue_:
89 return continue_;
90 case reply::status_type::switching_protocols:
91 return switching_protocols;
92 case reply::status_type::ok:
93 return ok;
94 case reply::status_type::created:
95 return created;
96 case reply::status_type::accepted:
97 return accepted;
98 case reply::status_type::nonauthoritative_information:
99 return nonauthoritative_information;
100 case reply::status_type::no_content:
101 return no_content;
102 case reply::status_type::reset_content:
103 return reset_content;
104 case reply::status_type::partial_content:
105 return partial_content;
106 case reply::status_type::multiple_choices:
107 return multiple_choices;
108 case reply::status_type::moved_permanently:
109 return moved_permanently;
110 case reply::status_type::moved_temporarily:
111 return moved_temporarily;
112 case reply::status_type::see_other:
113 return see_other;
114 case reply::status_type::not_modified:
115 return not_modified;
116 case reply::status_type::use_proxy:
117 return use_proxy;
118 case reply::status_type::temporary_redirect:
119 return temporary_redirect;
120 case reply::status_type::bad_request:
121 return bad_request;
122 case reply::status_type::unauthorized:
123 return unauthorized;
124 case reply::status_type::payment_required:
125 return payment_required;
126 case reply::status_type::forbidden:
127 return forbidden;
128 case reply::status_type::not_found:
129 return not_found;
130 case reply::status_type::method_not_allowed:
131 return method_not_allowed;
132 case reply::status_type::not_acceptable:
133 return not_acceptable;
134 case reply::status_type::request_timeout:
135 return request_timeout;
136 case reply::status_type::conflict:
137 return conflict;
138 case reply::status_type::gone:
139 return gone;
140 case reply::status_type::length_required:
141 return length_required;
142 case reply::status_type::payload_too_large:
143 return payload_too_large;
144 case reply::status_type::uri_too_long:
145 return uri_too_long;
146 case reply::status_type::unsupported_media_type:
147 return unsupported_media_type;
148 case reply::status_type::expectation_failed:
149 return expectation_failed;
150 case reply::status_type::unprocessable_entity:
151 return unprocessable_entity;
152 case reply::status_type::upgrade_required:
153 return upgrade_required;
154 case reply::status_type::too_many_requests:
155 return too_many_requests;
156 case reply::status_type::internal_server_error:
157 return internal_server_error;
158 case reply::status_type::not_implemented:
159 return not_implemented;
160 case reply::status_type::bad_gateway:
161 return bad_gateway;
162 case reply::status_type::service_unavailable:
163 return service_unavailable;
164 case reply::status_type::gateway_timeout:
165 return gateway_timeout;
166 case reply::status_type::http_version_not_supported:
167 return http_version_not_supported;
168 case reply::status_type::insufficient_storage:
169 return insufficient_storage;
170 default:
171 return internal_server_error;
172 }
173 }
174 } // namespace status_strings
175
176 std::ostream& operator<<(std::ostream& os, reply::status_type st) {
177 return os << status_strings::to_string(st);
178 }
179
180 reply::reply(http_response&& resp)
181 : _status(static_cast<status_type>(resp._status_code))
182 , _headers(std::move(resp._headers))
183 , _version(std::move(resp._version))
184 {
185 sstring length_header = get_header("Content-Length");
186 content_length = strtol(length_header.c_str(), nullptr, 10);
187 }
188
189 sstring reply::response_line() {
190 return "HTTP/" + _version + " " + status_strings::to_string(_status) + "\r\n";
191 }
192
193 void reply::write_body(const sstring& content_type, noncopyable_function<future<>(output_stream<char>&&)>&& body_writer) {
194 set_content_type(content_type);
195 _body_writer = std::move(body_writer);
196 }
197
198 void reply::write_body(const sstring& content_type, sstring content) {
199 _content = std::move(content);
200 done(content_type);
201 }
202
203 future<> reply::write_reply_to_connection(httpd::connection& con) {
204 add_header("Transfer-Encoding", "chunked");
205 return con.out().write(response_line()).then([this, &con] () mutable {
206 return write_reply_headers(con);
207 }).then([&con] () mutable {
208 return con.out().write("\r\n", 2);
209 }).then([this, &con] () mutable {
210 return _body_writer(http::internal::make_http_chunked_output_stream(con.out()));
211 });
212
213 }
214
215 future<> reply::write_reply_headers(httpd::connection& con) {
216 return do_for_each(_headers, [&con](auto& h) {
217 return con.out().write(h.first + ": " + h.second + "\r\n");
218 });
219 }
220
221 }
222 } // namespace server