]>
Commit | Line | Data |
---|---|---|
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 |
13 | using namespace rgw::asio; |
14 | ||
f64942e4 AA |
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), | |
21 | txbuf(*this) | |
7c673cae FG |
22 | { |
23 | } | |
24 | ||
25 | ClientIO::~ClientIO() = default; | |
26 | ||
3a9019d9 | 27 | int 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 |
95 | size_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 | ||
102 | void ClientIO::flush() | |
103 | { | |
104 | txbuf.pubsync(); | |
105 | } | |
106 | ||
107 | size_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 | ||
118 | size_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 | ||
127 | static constexpr size_t TIME_BUF_SIZE = 128; | |
128 | static size_t dump_date_header(char (×tr)[TIME_BUF_SIZE]) | |
129 | { | |
130 | const time_t gtime = time(nullptr); | |
131 | struct tm result; | |
132 | struct tm const * const tmp = gmtime_r(>ime, &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 | ||
140 | size_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 | ||
164 | size_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 | ||
180 | size_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 | } |