]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_asio_client.cc
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_asio_client.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#include <boost/algorithm/string/predicate.hpp>
5#include <boost/asio/write.hpp>
7c673cae
FG
6
7#include "rgw_asio_client.h"
11fdf7f2 8#include "rgw_perf_counters.h"
7c673cae
FG
9
10#define dout_context g_ceph_context
11#define dout_subsys ceph_subsys_rgw
12
7c673cae
FG
13using namespace rgw::asio;
14
f64942e4
AA
15ClientIO::ClientIO(parser_type& parser, bool is_ssl,
16 const endpoint_type& local_endpoint,
17 const endpoint_type& remote_endpoint)
18 : parser(parser), is_ssl(is_ssl),
19 local_endpoint(local_endpoint),
20 remote_endpoint(remote_endpoint),
21 txbuf(*this)
7c673cae
FG
22{
23}
24
25ClientIO::~ClientIO() = default;
26
3a9019d9 27int ClientIO::init_env(CephContext *cct)
7c673cae
FG
28{
29 env.init(cct);
30
11fdf7f2
TL
31 perfcounter->inc(l_rgw_qlen);
32 perfcounter->inc(l_rgw_qactive);
33
7c673cae 34 const auto& request = parser.get();
b32b8144 35 const auto& headers = request;
7c673cae 36 for (auto header = headers.begin(); header != headers.end(); ++header) {
b32b8144
FG
37 const auto& field = header->name(); // enum type for known headers
38 const auto& name = header->name_string();
7c673cae
FG
39 const auto& value = header->value();
40
b32b8144
FG
41 if (field == beast::http::field::content_length) {
42 env.set("CONTENT_LENGTH", value.to_string());
7c673cae
FG
43 continue;
44 }
b32b8144
FG
45 if (field == beast::http::field::content_type) {
46 env.set("CONTENT_TYPE", value.to_string());
7c673cae
FG
47 continue;
48 }
7c673cae
FG
49
50 static const boost::string_ref HTTP_{"HTTP_"};
51
52 char buf[name.size() + HTTP_.size() + 1];
53 auto dest = std::copy(std::begin(HTTP_), std::end(HTTP_), buf);
54 for (auto src = name.begin(); src != name.end(); ++src, ++dest) {
55 if (*src == '-') {
56 *dest = '_';
57 } else {
58 *dest = std::toupper(*src);
59 }
60 }
61 *dest = '\0';
62
b32b8144 63 env.set(buf, value.to_string());
7c673cae
FG
64 }
65
b32b8144
FG
66 int major = request.version() / 10;
67 int minor = request.version() % 10;
68 env.set("HTTP_VERSION", std::to_string(major) + '.' + std::to_string(minor));
69
70 env.set("REQUEST_METHOD", request.method_string().to_string());
7c673cae
FG
71
72 // split uri from query
9f95a23c
TL
73 auto uri = request.target();
74 auto pos = uri.find('?');
75 if (pos != uri.npos) {
76 auto query = uri.substr(pos + 1);
b32b8144 77 env.set("QUERY_STRING", query.to_string());
9f95a23c 78 uri = uri.substr(0, pos);
b32b8144 79 }
9f95a23c
TL
80 env.set("SCRIPT_URI", uri.to_string());
81
82 env.set("REQUEST_URI", request.target().to_string());
7c673cae
FG
83
84 char port_buf[16];
f64942e4 85 snprintf(port_buf, sizeof(port_buf), "%d", local_endpoint.port());
7c673cae 86 env.set("SERVER_PORT", port_buf);
f64942e4
AA
87 if (is_ssl) {
88 env.set("SERVER_PORT_SECURE", port_buf);
89 }
90 env.set("REMOTE_ADDR", remote_endpoint.address().to_string());
7c673cae 91 // TODO: set REMOTE_USER if authenticated
3a9019d9 92 return 0;
7c673cae
FG
93}
94
7c673cae
FG
95size_t ClientIO::complete_request()
96{
11fdf7f2
TL
97 perfcounter->inc(l_rgw_qlen, -1);
98 perfcounter->inc(l_rgw_qactive, -1);
7c673cae
FG
99 return 0;
100}
101
102void ClientIO::flush()
103{
104 txbuf.pubsync();
105}
106
107size_t ClientIO::send_status(int status, const char* status_name)
108{
109 static constexpr size_t STATUS_BUF_SIZE = 128;
110
111 char statusbuf[STATUS_BUF_SIZE];
112 const auto statuslen = snprintf(statusbuf, sizeof(statusbuf),
113 "HTTP/1.1 %d %s\r\n", status, status_name);
114
115 return txbuf.sputn(statusbuf, statuslen);
116}
117
118size_t ClientIO::send_100_continue()
119{
120 const char HTTTP_100_CONTINUE[] = "HTTP/1.1 100 CONTINUE\r\n\r\n";
121 const size_t sent = txbuf.sputn(HTTTP_100_CONTINUE,
122 sizeof(HTTTP_100_CONTINUE) - 1);
123 flush();
124 return sent;
125}
126
127static constexpr size_t TIME_BUF_SIZE = 128;
128static size_t dump_date_header(char (&timestr)[TIME_BUF_SIZE])
129{
130 const time_t gtime = time(nullptr);
131 struct tm result;
132 struct tm const * const tmp = gmtime_r(&gtime, &result);
133 if (tmp == nullptr) {
134 return 0;
135 }
136 return strftime(timestr, sizeof(timestr),
137 "Date: %a, %d %b %Y %H:%M:%S %Z\r\n", tmp);
138}
139
140size_t ClientIO::complete_header()
141{
142 size_t sent = 0;
143
144 char timestr[TIME_BUF_SIZE];
145 if (dump_date_header(timestr)) {
146 sent += txbuf.sputn(timestr, strlen(timestr));
147 }
148
b32b8144 149 if (parser.keep_alive()) {
7c673cae
FG
150 constexpr char CONN_KEEP_ALIVE[] = "Connection: Keep-Alive\r\n";
151 sent += txbuf.sputn(CONN_KEEP_ALIVE, sizeof(CONN_KEEP_ALIVE) - 1);
b32b8144 152 } else {
7c673cae
FG
153 constexpr char CONN_KEEP_CLOSE[] = "Connection: close\r\n";
154 sent += txbuf.sputn(CONN_KEEP_CLOSE, sizeof(CONN_KEEP_CLOSE) - 1);
155 }
156
157 constexpr char HEADER_END[] = "\r\n";
158 sent += txbuf.sputn(HEADER_END, sizeof(HEADER_END) - 1);
159
160 flush();
161 return sent;
162}
163
164size_t ClientIO::send_header(const boost::string_ref& name,
165 const boost::string_ref& value)
166{
167 static constexpr char HEADER_SEP[] = ": ";
168 static constexpr char HEADER_END[] = "\r\n";
169
170 size_t sent = 0;
171
172 sent += txbuf.sputn(name.data(), name.length());
173 sent += txbuf.sputn(HEADER_SEP, sizeof(HEADER_SEP) - 1);
174 sent += txbuf.sputn(value.data(), value.length());
175 sent += txbuf.sputn(HEADER_END, sizeof(HEADER_END) - 1);
176
177 return sent;
178}
179
180size_t ClientIO::send_content_length(uint64_t len)
181{
182 static constexpr size_t CONLEN_BUF_SIZE = 128;
183
184 char sizebuf[CONLEN_BUF_SIZE];
185 const auto sizelen = snprintf(sizebuf, sizeof(sizebuf),
186 "Content-Length: %" PRIu64 "\r\n", len);
187
188 return txbuf.sputn(sizebuf, sizelen);
189}