]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_asio_client.cc
82d5d43f8b8d141b0916eb1f527fbd73e29fdce2
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include <boost/algorithm/string/predicate.hpp>
5 #include <boost/asio/write.hpp>
7 #include "rgw_asio_client.h"
8 #include "rgw_perf_counters.h"
10 #define dout_context g_ceph_context
11 #define dout_subsys ceph_subsys_rgw
13 using namespace rgw::asio
;
15 ClientIO::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
),
25 ClientIO::~ClientIO() = default;
27 int ClientIO::init_env(CephContext
*cct
)
31 perfcounter
->inc(l_rgw_qlen
);
32 perfcounter
->inc(l_rgw_qactive
);
34 const auto& request
= parser
.get();
35 const auto& headers
= request
;
36 for (auto header
= headers
.begin(); header
!= headers
.end(); ++header
) {
37 const auto& field
= header
->name(); // enum type for known headers
38 const auto& name
= header
->name_string();
39 const auto& value
= header
->value();
41 if (field
== beast::http::field::content_length
) {
42 env
.set("CONTENT_LENGTH", value
.to_string());
45 if (field
== beast::http::field::content_type
) {
46 env
.set("CONTENT_TYPE", value
.to_string());
50 static const std::string_view HTTP_
{"HTTP_"};
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
) {
57 } else if (*src
== '_') {
60 *dest
= std::toupper(*src
);
65 env
.set(buf
, value
.to_string());
68 int major
= request
.version() / 10;
69 int minor
= request
.version() % 10;
70 env
.set("HTTP_VERSION", std::to_string(major
) + '.' + std::to_string(minor
));
72 env
.set("REQUEST_METHOD", request
.method_string().to_string());
74 // split uri from query
75 auto uri
= request
.target();
76 auto pos
= uri
.find('?');
77 if (pos
!= uri
.npos
) {
78 auto query
= uri
.substr(pos
+ 1);
79 env
.set("QUERY_STRING", query
.to_string());
80 uri
= uri
.substr(0, pos
);
82 env
.set("SCRIPT_URI", uri
.to_string());
84 env
.set("REQUEST_URI", request
.target().to_string());
87 snprintf(port_buf
, sizeof(port_buf
), "%d", local_endpoint
.port());
88 env
.set("SERVER_PORT", port_buf
);
90 env
.set("SERVER_PORT_SECURE", port_buf
);
92 env
.set("REMOTE_ADDR", remote_endpoint
.address().to_string());
93 // TODO: set REMOTE_USER if authenticated
97 size_t ClientIO::complete_request()
99 perfcounter
->inc(l_rgw_qlen
, -1);
100 perfcounter
->inc(l_rgw_qactive
, -1);
104 void ClientIO::flush()
109 size_t ClientIO::send_status(int status
, const char* status_name
)
111 static constexpr size_t STATUS_BUF_SIZE
= 128;
113 char statusbuf
[STATUS_BUF_SIZE
];
114 const auto statuslen
= snprintf(statusbuf
, sizeof(statusbuf
),
115 "HTTP/1.1 %d %s\r\n", status
, status_name
);
117 return txbuf
.sputn(statusbuf
, statuslen
);
120 size_t ClientIO::send_100_continue()
122 const char HTTTP_100_CONTINUE
[] = "HTTP/1.1 100 CONTINUE\r\n\r\n";
123 const size_t sent
= txbuf
.sputn(HTTTP_100_CONTINUE
,
124 sizeof(HTTTP_100_CONTINUE
) - 1);
129 static constexpr size_t TIME_BUF_SIZE
= 128;
130 static size_t dump_date_header(char (×tr
)[TIME_BUF_SIZE
])
132 const time_t gtime
= time(nullptr);
134 struct tm
const * const tmp
= gmtime_r(>ime
, &result
);
135 if (tmp
== nullptr) {
138 return strftime(timestr
, sizeof(timestr
),
139 "Date: %a, %d %b %Y %H:%M:%S %Z\r\n", tmp
);
142 size_t ClientIO::complete_header()
146 char timestr
[TIME_BUF_SIZE
];
147 if (dump_date_header(timestr
)) {
148 sent
+= txbuf
.sputn(timestr
, strlen(timestr
));
151 if (parser
.keep_alive()) {
152 constexpr char CONN_KEEP_ALIVE
[] = "Connection: Keep-Alive\r\n";
153 sent
+= txbuf
.sputn(CONN_KEEP_ALIVE
, sizeof(CONN_KEEP_ALIVE
) - 1);
155 constexpr char CONN_KEEP_CLOSE
[] = "Connection: close\r\n";
156 sent
+= txbuf
.sputn(CONN_KEEP_CLOSE
, sizeof(CONN_KEEP_CLOSE
) - 1);
159 constexpr char HEADER_END
[] = "\r\n";
160 sent
+= txbuf
.sputn(HEADER_END
, sizeof(HEADER_END
) - 1);
166 size_t ClientIO::send_header(const std::string_view
& name
,
167 const std::string_view
& value
)
169 static constexpr char HEADER_SEP
[] = ": ";
170 static constexpr char HEADER_END
[] = "\r\n";
174 sent
+= txbuf
.sputn(name
.data(), name
.length());
175 sent
+= txbuf
.sputn(HEADER_SEP
, sizeof(HEADER_SEP
) - 1);
176 sent
+= txbuf
.sputn(value
.data(), value
.length());
177 sent
+= txbuf
.sputn(HEADER_END
, sizeof(HEADER_END
) - 1);
182 size_t ClientIO::send_content_length(uint64_t len
)
184 static constexpr size_t CONLEN_BUF_SIZE
= 128;
186 char sizebuf
[CONLEN_BUF_SIZE
];
187 const auto sizelen
= snprintf(sizebuf
, sizeof(sizebuf
),
188 "Content-Length: %" PRIu64
"\r\n", len
);
190 return txbuf
.sputn(sizebuf
, sizelen
);