Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
client.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 (C) 2022 Scylladb, Ltd.
20 */
21
22#pragma once
23
24#ifndef SEASTAR_MODULE
25#include <boost/intrusive/list.hpp>
26#endif
27#include <seastar/net/api.hh>
28#include <seastar/http/reply.hh>
29#include <seastar/core/condition-variable.hh>
30#include <seastar/core/iostream.hh>
31#include <seastar/util/modules.hh>
32
33namespace bi = boost::intrusive;
34
35namespace seastar {
36
37SEASTAR_MODULE_EXPORT_BEGIN
38
39namespace tls { class certificate_credentials; }
40
41namespace http {
42
43namespace experimental { class client; }
44struct request;
45struct reply;
46
47namespace internal {
48
51public:
54 client_ref(client_ref&& o) noexcept : _c(std::exchange(o._c, nullptr)) {}
55 client_ref(const client_ref&) = delete;
56};
57
58}
59
60namespace experimental {
61
68class connection : public enable_shared_from_this<connection> {
69 friend class client;
70 using hook_t = bi::list_member_hook<bi::link_mode<bi::auto_unlink>>;
71 using reply_ptr = std::unique_ptr<reply>;
72
74 input_stream<char> _read_buf;
75 output_stream<char> _write_buf;
76 hook_t _hook;
77 future<> _closed;
79 // Client sends HTTP-1.1 version and assumes the server is 1.1-compatible
80 // too and thus the connection will be persistent by default. If the server
81 // responds with older version, this flag will be dropped (see recv_reply())
82 bool _persistent = true;
83
84public:
92
109
119
127
128private:
129 future<reply_ptr> do_make_request(request& rq);
130 void setup_request(request& rq);
131 future<> send_request_head(const request& rq);
132 future<reply_ptr> maybe_wait_for_continue(const request& req);
133 future<> write_body(const request& rq);
134 future<reply_ptr> recv_reply();
135
136 void shutdown() noexcept;
137};
138
148public:
156 virtual ~connection_factory() {}
157};
158
170class client {
171public:
174
175private:
176 friend class http::internal::client_ref;
177 using connections_list_t = bi::list<connection, bi::member_hook<connection, typename connection::hook_t, &connection::_hook>, bi::constant_time_size<false>>;
178 static constexpr unsigned default_max_connections = 100;
179
180 std::unique_ptr<connection_factory> _new_connections;
181 unsigned _nr_connections = 0;
182 unsigned _max_connections;
183 unsigned long _total_new_connections = 0;
184 const retry_requests _retry;
185 condition_variable _wait_con;
186 connections_list_t _pool;
187
189
190 future<connection_ptr> get_connection(abort_source* as);
191 future<connection_ptr> make_connection(abort_source* as);
192 future<> put_connection(connection_ptr con);
193 future<> shrink_connections();
194
195 template <std::invocable<connection&> Fn>
196 auto with_connection(Fn&& fn, abort_source*);
197
198 template <typename Fn>
199 requires std::invocable<Fn, connection&>
200 auto with_new_connection(Fn&& fn, abort_source*);
201
202 future<> do_make_request(request& req, reply_handler& handle, abort_source*, std::optional<reply::status_type> expected);
203 future<> do_make_request(connection& con, request& req, reply_handler& handle, abort_source*, std::optional<reply::status_type> expected);
204
205public:
215 explicit client(socket_address addr);
216
229
268 explicit client(std::unique_ptr<connection_factory> f, unsigned max_connections = default_max_connections, retry_requests retry = retry_requests::no);
269
286 future<> make_request(request&& req, reply_handler&& handle, std::optional<reply::status_type>&& expected = std::nullopt);
287
298 future<> make_request(request&& req, reply_handler&& handle, abort_source& as, std::optional<reply::status_type>&& expected = std::nullopt);
299
307 future<> make_request(request& req, reply_handler& handle, std::optional<reply::status_type> expected = std::nullopt);
308
316 future<> make_request(request& req, reply_handler& handle, abort_source& as, std::optional<reply::status_type> expected = std::nullopt);
317
327
334
339 unsigned connections_nr() const noexcept {
340 return _nr_connections;
341 }
342
347 unsigned idle_connections_nr() const noexcept {
348 return _pool.size();
349 }
350
358 unsigned long total_new_connections_nr() const noexcept {
359 return _total_new_connections;
360 }
361};
362
363} // experimental namespace
364
365} // http namespace
366
367SEASTAR_MODULE_EXPORT_END
368} // seastar namespace
Definition: abort_source.hh:58
Type-safe boolean.
Definition: bool_class.hh:58
Conditional variable.
Definition: condition-variable.hh:73
Definition: api.hh:183
Definition: shared_ptr.hh:493
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
Class client wraps communications using HTTP protocol.
Definition: client.hh:170
client(std::unique_ptr< connection_factory > f, unsigned max_connections=default_max_connections, retry_requests retry=retry_requests::no)
Construct a client with connection factory.
future make_request(request &&req, reply_handler &&handle, abort_source &as, std::optional< reply::status_type > &&expected=std::nullopt)
Send the request and handle the response (abortable)
future make_request(request &&req, reply_handler &&handle, std::optional< reply::status_type > &&expected=std::nullopt)
Send the request and handle the response.
unsigned idle_connections_nr() const noexcept
Returns the number of idle connections.
Definition: client.hh:347
future make_request(request &req, reply_handler &handle, std::optional< reply::status_type > expected=std::nullopt)
Send the request and handle the response, same as make_request()
unsigned long total_new_connections_nr() const noexcept
Returns the total number of connection factory invocations made so far.
Definition: client.hh:358
unsigned connections_nr() const noexcept
Returns the total number of connections.
Definition: client.hh:339
future make_request(request &req, reply_handler &handle, abort_source &as, std::optional< reply::status_type > expected=std::nullopt)
Send the request and handle the response (abortable), same as make_request()
future close()
Closes the client.
future set_maximum_connections(unsigned nr)
Updates the maximum number of connections a client may have.
client(socket_address addr, shared_ptr< tls::certificate_credentials > creds, sstring host={})
Construct a secure client.
client(socket_address addr)
Construct a simple client.
Factory that provides transport for client.
Definition: client.hh:147
virtual future< connected_socket > make(abort_source *)=0
Make a connected_socket.
Class connection represents an HTTP connection over a given transport.
Definition: client.hh:68
input_stream< char > in(reply &rep)
Get a reference on the connection input stream.
future close()
Closes the connection.
connection(connected_socket &&fd, internal::client_ref cr)
Create an http connection.
future< reply > make_request(request rq)
Send the request and wait for response.
Definition: client.hh:49
Definition: shared_ptr.hh:507
Definition: socket_defs.hh:47
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: reply.hh:61
Definition: request.hh:52