1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
7 #include <boost/utility/string_ref.hpp>
9 #include "rgw_frontend.h"
10 #include "rgw_client_io_filters.h"
12 #define dout_subsys ceph_subsys_rgw
14 static int civetweb_callback(struct mg_connection
* conn
)
16 const struct mg_request_info
* const req_info
= mg_get_request_info(conn
);
17 return static_cast<RGWCivetWebFrontend
*>(req_info
->user_data
)->process(conn
);
20 int RGWCivetWebFrontend::process(struct mg_connection
* const conn
)
22 /* Hold a read lock over access to env.store for reconfiguration. */
23 RWLock::RLocker
lock(env
.mutex
);
25 RGWCivetWeb
cw_client(conn
);
26 auto real_client_io
= rgw::io::add_reordering(
27 rgw::io::add_buffering(dout_context
,
28 rgw::io::add_chunking(
29 rgw::io::add_conlen_controlling(
31 RGWRestfulIO
client_io(dout_context
, &real_client_io
);
33 RGWRequest
req(env
.store
->get_new_req_id());
35 int ret
= process_request(env
.store
, env
.rest
, &req
, env
.uri_prefix
,
36 *env
.auth_registry
, &client_io
, env
.olog
, &http_ret
);
38 /* We don't really care about return code. */
39 dout(20) << "process_request() returned " << ret
<< dendl
;
43 /* Mark as processed. */
50 int RGWCivetWebFrontend::run()
52 auto& conf_map
= conf
->get_config_map();
54 set_conf_default(conf_map
, "num_threads",
55 std::to_string(g_conf
->rgw_thread_pool_size
));
56 set_conf_default(conf_map
, "decode_url", "no");
57 set_conf_default(conf_map
, "enable_keep_alive", "yes");
58 set_conf_default(conf_map
, "validate_http_method", "no");
59 set_conf_default(conf_map
, "canonicalize_url_path", "no");
60 set_conf_default(conf_map
, "enable_auth_domain_check", "no");
62 std::string listening_ports
;
63 // support multiple port= entries
64 auto range
= conf_map
.equal_range("port");
65 for (auto p
= range
.first
; p
!= range
.second
; ++p
) {
66 std::string port_str
= p
->second
;
67 // support port= entries with multiple values
68 std::replace(port_str
.begin(), port_str
.end(), '+', ',');
69 if (!listening_ports
.empty()) {
70 listening_ports
.append(1, ',');
72 listening_ports
.append(port_str
);
74 if (listening_ports
.empty()) {
75 listening_ports
= "80";
77 conf_map
.emplace("listening_ports", std::move(listening_ports
));
79 /* Set run_as_user. This will cause civetweb to invoke setuid() and setgid()
80 * based on pw_uid and pw_gid obtained from pw_name. */
81 std::string uid_string
= g_ceph_context
->get_set_uid_string();
82 if (! uid_string
.empty()) {
83 conf_map
.emplace("run_as_user", std::move(uid_string
));
86 /* Prepare options for CivetWeb. */
87 const std::set
<boost::string_ref
> rgw_opts
= { "port", "prefix" };
89 std::vector
<const char*> options
;
91 for (const auto& pair
: conf_map
) {
92 if (! rgw_opts
.count(pair
.first
)) {
93 /* CivetWeb doesn't understand configurables of the glue layer between
94 * it and RadosGW. We need to strip them out. Otherwise CivetWeb would
95 * signalise an error. */
96 options
.push_back(pair
.first
.c_str());
97 options
.push_back(pair
.second
.c_str());
99 dout(20) << "civetweb config: " << pair
.first
100 << ": " << pair
.second
<< dendl
;
104 options
.push_back(nullptr);
105 /* Initialize the CivetWeb right now. */
106 struct mg_callbacks cb
;
107 memset((void *)&cb
, 0, sizeof(cb
));
108 cb
.begin_request
= civetweb_callback
;
109 cb
.log_message
= rgw_civetweb_log_callback
;
110 cb
.log_access
= rgw_civetweb_log_access_callback
;
111 ctx
= mg_start(&cb
, this, options
.data());
113 return ! ctx
? -EIO
: 0;
114 } /* RGWCivetWebFrontend::run */