]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_asio_client.cc
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 boost::string_ref 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
) {
58 *dest
= std::toupper(*src
);
63 env
.set(buf
, value
.to_string());
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
));
70 env
.set("REQUEST_METHOD", request
.method_string().to_string());
72 // split uri from query
73 auto uri
= request
.target();
74 auto pos
= uri
.find('?');
75 if (pos
!= uri
.npos
) {
76 auto query
= uri
.substr(pos
+ 1);
77 env
.set("QUERY_STRING", query
.to_string());
78 uri
= uri
.substr(0, pos
);
80 env
.set("SCRIPT_URI", uri
.to_string());
82 env
.set("REQUEST_URI", request
.target().to_string());
85 snprintf(port_buf
, sizeof(port_buf
), "%d", local_endpoint
.port());
86 env
.set("SERVER_PORT", port_buf
);
88 env
.set("SERVER_PORT_SECURE", port_buf
);
90 env
.set("REMOTE_ADDR", remote_endpoint
.address().to_string());
91 // TODO: set REMOTE_USER if authenticated
95 size_t ClientIO::complete_request()
97 perfcounter
->inc(l_rgw_qlen
, -1);
98 perfcounter
->inc(l_rgw_qactive
, -1);
102 void ClientIO::flush()
107 size_t ClientIO::send_status(int status
, const char* status_name
)
109 static constexpr size_t STATUS_BUF_SIZE
= 128;
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
);
115 return txbuf
.sputn(statusbuf
, statuslen
);
118 size_t ClientIO::send_100_continue()
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);
127 static constexpr size_t TIME_BUF_SIZE
= 128;
128 static size_t dump_date_header(char (×tr
)[TIME_BUF_SIZE
])
130 const time_t gtime
= time(nullptr);
132 struct tm
const * const tmp
= gmtime_r(>ime
, &result
);
133 if (tmp
== nullptr) {
136 return strftime(timestr
, sizeof(timestr
),
137 "Date: %a, %d %b %Y %H:%M:%S %Z\r\n", tmp
);
140 size_t ClientIO::complete_header()
144 char timestr
[TIME_BUF_SIZE
];
145 if (dump_date_header(timestr
)) {
146 sent
+= txbuf
.sputn(timestr
, strlen(timestr
));
149 if (parser
.keep_alive()) {
150 constexpr char CONN_KEEP_ALIVE
[] = "Connection: Keep-Alive\r\n";
151 sent
+= txbuf
.sputn(CONN_KEEP_ALIVE
, sizeof(CONN_KEEP_ALIVE
) - 1);
153 constexpr char CONN_KEEP_CLOSE
[] = "Connection: close\r\n";
154 sent
+= txbuf
.sputn(CONN_KEEP_CLOSE
, sizeof(CONN_KEEP_CLOSE
) - 1);
157 constexpr char HEADER_END
[] = "\r\n";
158 sent
+= txbuf
.sputn(HEADER_END
, sizeof(HEADER_END
) - 1);
164 size_t ClientIO::send_header(const boost::string_ref
& name
,
165 const boost::string_ref
& value
)
167 static constexpr char HEADER_SEP
[] = ": ";
168 static constexpr char HEADER_END
[] = "\r\n";
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);
180 size_t ClientIO::send_content_length(uint64_t len
)
182 static constexpr size_t CONLEN_BUF_SIZE
= 128;
184 char sizebuf
[CONLEN_BUF_SIZE
];
185 const auto sizelen
= snprintf(sizebuf
, sizeof(sizebuf
),
186 "Content-Length: %" PRIu64
"\r\n", len
);
188 return txbuf
.sputn(sizebuf
, sizelen
);