Seastar
High performance C++ framework for concurrent servers
request.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 //
23 // request.hpp
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 #pragma once
32 
33 #include <seastar/core/iostream.hh>
34 #include <seastar/core/sstring.hh>
35 #include <string>
36 #include <vector>
37 #include <strings.h>
38 #include <seastar/http/common.hh>
39 #include <seastar/http/mime_types.hh>
40 #include <seastar/net/socket_defs.hh>
41 #include <seastar/core/iostream.hh>
42 #include <seastar/util/string_utils.hh>
43 
44 namespace seastar {
45 
46 namespace http {
47 
48 namespace experimental { class connection; }
49 
53 struct request {
54  enum class ctclass
55  : char {
56  other, multipart, app_x_www_urlencoded,
57  };
58 
59  socket_address _client_address;
60  socket_address _server_address;
61  sstring _method;
62  sstring _url;
63  sstring _version;
64  ctclass content_type_class;
65  size_t content_length = 0;
66  mutable size_t _bytes_written = 0;
67  std::unordered_map<sstring, sstring, seastar::internal::case_insensitive_hash, seastar::internal::case_insensitive_cmp> _headers;
68  std::unordered_map<sstring, sstring> query_parameters;
69  httpd::parameters param;
70  sstring content; // server-side deprecated: use content_stream instead
71  /*
72  * The handler should read the contents of this stream till reaching eof (i.e., the end of this request's content). Failing to do so
73  * will force the server to close this connection, and the client will not be able to reuse this connection for the next request.
74  * The stream should not be closed by the handler, the server will close it for the handler.
75  * */
76  input_stream<char>* content_stream;
77  std::unordered_map<sstring, sstring> trailing_headers;
78  std::unordered_map<sstring, sstring> chunk_extensions;
79  sstring protocol_name = "http";
80  noncopyable_function<future<>(output_stream<char>&&)> body_writer; // for client
81 
87  return _client_address;
88  }
89 
95  return _server_address;
96  }
97 
103  sstring get_header(const sstring& name) const {
104  auto res = _headers.find(name);
105  if (res == _headers.end()) {
106  return "";
107  }
108  return res->second;
109  }
110 
116  sstring get_query_param(const sstring& name) const {
117  auto res = query_parameters.find(name);
118  if (res == query_parameters.end()) {
119  return "";
120  }
121  return res->second;
122  }
123 
127  sstring get_protocol_name() const {
128  return protocol_name;
129  }
130 
135  sstring get_url() const {
136  return get_protocol_name() + "://" + get_header("Host") + _url;
137  }
138 
139  bool is_multi_part() const {
140  return content_type_class == ctclass::multipart;
141  }
142 
143  bool is_form_post() const {
144  return content_type_class == ctclass::app_x_www_urlencoded;
145  }
146 
147  bool should_keep_alive() const {
148  if (_version == "0.9") {
149  return false;
150  }
151 
152  // TODO: handle HTTP/2.0 when it releases
153 
154  auto it = _headers.find("Connection");
155  if (_version == "1.0") {
156  return it != _headers.end()
157  && seastar::internal::case_insensitive_cmp()(it->second, "keep-alive");
158  } else { // HTTP/1.1
159  return it == _headers.end() || !seastar::internal::case_insensitive_cmp()(it->second, "close");
160  }
161  }
162 
169  sstring parse_query_param();
170 
175  sstring format_url() const;
176 
182  void set_mime_type(const sstring& mime) {
183  _headers["Content-Type"] = mime;
184  }
185 
190  void set_content_type(const sstring& content_type = "html") {
191  set_mime_type(http::mime_types::extension_to_type(content_type));
192  }
193 
205  void write_body(const sstring& content_type, sstring content);
206 
224  void write_body(const sstring& content_type, noncopyable_function<future<>(output_stream<char>&&)>&& body_writer);
225 
248  void write_body(const sstring& content_type, size_t len, noncopyable_function<future<>(output_stream<char>&&)>&& body_writer);
249 
258 
267  static request make(sstring method, sstring host, sstring path);
268 
277  static request make(httpd::operation_type type, sstring host, sstring path);
278 
279 private:
280  void add_param(const std::string_view& param);
281  sstring request_line() const;
282  future<> write_request_headers(output_stream<char>& out) const;
283  friend class experimental::connection;
284 };
285 
286 } // namespace httpd
287 
288 namespace httpd {
289 using request [[deprecated("Use http::request instead")]] = http::request;
290 }
291 
292 }
Class connection represents an HTTP connection over a given transport.
Definition: client.hh:68
Definition: common.hh:47
Definition: socket_defs.hh:47
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: request.hh:53
sstring format_url() const
sstring get_header(const sstring &name) const
Definition: request.hh:103
void write_body(const sstring &content_type, size_t len, noncopyable_function< future<>(output_stream< char > &&)> &&body_writer)
Use an output stream to write the message body.
void set_mime_type(const sstring &mime)
Definition: request.hh:182
const socket_address & get_client_address() const
Definition: request.hh:86
void set_content_type(const sstring &content_type="html")
Definition: request.hh:190
void write_body(const sstring &content_type, sstring content)
Write a string as the body.
const socket_address & get_server_address() const
Definition: request.hh:94
static request make(sstring method, sstring host, sstring path)
Make simple request.
void set_expects_continue()
Make request send Expect header.
static request make(httpd::operation_type type, sstring host, sstring path)
Make simple request.
void write_body(const sstring &content_type, noncopyable_function< future<>(output_stream< char > &&)> &&body_writer)
Use an output stream to write the message body.
sstring get_url() const
Definition: request.hh:135
sstring get_protocol_name() const
Definition: request.hh:127
sstring get_query_param(const sstring &name) const
Definition: request.hh:116