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