From fe6cd9bce5856af2f862a0f0f8bc4c2252cc11be Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 22 Oct 2013 13:53:59 -0700 Subject: [PATCH] rgw: rebase mongoose prototype Signed-off-by: Yehuda Sadeh --- src/rgw/Makefile.am | 6 +- src/rgw/rgw_client_io.h | 16 ++- src/rgw/rgw_common.cc | 6 +- src/rgw/rgw_common.h | 9 +- src/rgw/rgw_env.cc | 35 ++++--- src/rgw/rgw_fcgi.cc | 24 ++++- src/rgw/rgw_fcgi.h | 5 +- src/rgw/rgw_http_errors.h | 46 +++++++++ src/rgw/rgw_main.cc | 195 +++++++++++++++++++++++++++++++++---- src/rgw/rgw_mongoose.cc | 112 +++++++++++++++++++++ src/rgw/rgw_mongoose.h | 35 +++++++ src/rgw/rgw_op.cc | 8 -- src/rgw/rgw_rest.cc | 26 +++-- src/rgw/rgw_rest_client.cc | 10 +- src/rgw/rgw_rest_conn.cc | 2 +- 15 files changed, 471 insertions(+), 64 deletions(-) create mode 100644 src/rgw/rgw_mongoose.cc create mode 100644 src/rgw/rgw_mongoose.h diff --git a/src/rgw/Makefile.am b/src/rgw/Makefile.am index b92c35e08d61f..2cfa20caace2e 100644 --- a/src/rgw/Makefile.am +++ b/src/rgw/Makefile.am @@ -67,6 +67,8 @@ radosgw_SOURCES = \ rgw/rgw_http_client.cc \ rgw/rgw_swift.cc \ rgw/rgw_swift_auth.cc \ + rgw/rgw_mongoose.cc \ + mongoose/mongoose.c \ rgw/rgw_main.cc radosgw_LDADD = $(LIBRGW) $(LIBRGW_DEPS) -lresolv $(CEPH_GLOBAL) bin_PROGRAMS += radosgw @@ -148,5 +150,7 @@ noinst_HEADERS += \ rgw/rgw_usage.h \ rgw/rgw_user.h \ rgw/rgw_bucket.h \ - rgw/rgw_keystone.h + rgw/rgw_keystone.h \ + rgw/rgw_mongoose.h \ + mongoose/mongoose.h diff --git a/src/rgw/rgw_client_io.h b/src/rgw/rgw_client_io.h index 546b16d51f702..4f0168a8cc2e7 100644 --- a/src/rgw/rgw_client_io.h +++ b/src/rgw/rgw_client_io.h @@ -5,6 +5,8 @@ #include "include/types.h" +#include "rgw_common.h" + class RGWClientIO { bool account; @@ -12,6 +14,10 @@ class RGWClientIO { size_t bytes_received; protected: + RGWEnv env; + + virtual void init_env(CephContext *cct) = 0; + virtual int write_data(const char *buf, int len) = 0; virtual int read_data(char *buf, int max) = 0; @@ -19,12 +25,20 @@ public: virtual ~RGWClientIO() {} RGWClientIO() : account(false), bytes_sent(0), bytes_received(0) {} + void init(CephContext *cct) { + init_env(cct); + } + int print(const char *format, ...); int write(const char *buf, int len); virtual void flush() = 0; int read(char *buf, int max, int *actual); - virtual const char **envp() = 0; + virtual int send_status(const char *status, const char *status_name) = 0; + virtual int send_100_continue() = 0; + virtual int complete_header() = 0; + + RGWEnv& get_env() { return env; } void set_account(bool _account) { account = _account; diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index cb87c18b93d71..34c7bf1e2bc45 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -101,6 +101,8 @@ req_info::req_info(CephContext *cct, class RGWEnv *e) : env(e) { if (pos >= 0) { request_params = request_uri.substr(pos + 1); request_uri = request_uri.substr(0, pos); + } else { + request_params = env->get("QUERY_STRING", ""); } host = env->get("HTTP_HOST"); } @@ -184,8 +186,8 @@ void req_info::init_meta_info(bool *found_bad_meta) { x_meta_map.clear(); - map& m = env->get_map(); - map::iterator iter; + map& m = env->get_map(); + map::iterator iter; for (iter = m.begin(); iter != m.end(); ++iter) { const char *prefix; const string& header_name = iter->first; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index a7ef250b7d8d3..fabf8cf62fdaf 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -30,6 +30,7 @@ #include "rgw_acl.h" #include "rgw_cors.h" #include "rgw_quota.h" +#include "rgw_string.h" #include "cls/version/cls_version_types.h" #include "include/rados/librados.hpp" @@ -273,13 +274,15 @@ class XMLArgs class RGWConf; class RGWEnv { - std::map env_map; + std::map env_map; public: RGWConf *conf; RGWEnv(); ~RGWEnv(); + void init(CephContext *cct); void init(CephContext *cct, char **envp); + void set(const char *name, const char *val); const char *get(const char *name, const char *def_val = NULL); int get_int(const char *name, int def_val = 0); bool get_bool(const char *name, bool def_val = 0); @@ -288,8 +291,8 @@ public: bool exists_prefix(const char *prefix); void remove(const char *name); - void set(const char *name, const char *val); - std::map& get_map() { return env_map; } + + std::map& get_map() { return env_map; } }; class RGWConf { diff --git a/src/rgw/rgw_env.cc b/src/rgw/rgw_env.cc index 78ac0d41d7a27..0628dffbde4a7 100644 --- a/src/rgw/rgw_env.cc +++ b/src/rgw/rgw_env.cc @@ -16,6 +16,20 @@ RGWEnv::~RGWEnv() delete conf; } +void RGWEnv::init(CephContext *cct) +{ + conf->init(cct, this); +} + +void RGWEnv::set(const char *name, const char *val) +{ + if (!val) + val = ""; + env_map[name] = val; + + dout(0) << "RGWEnv::set(): " << name << ": " << val << dendl; +} + void RGWEnv::init(CephContext *cct, char **envp) { const char *p; @@ -32,12 +46,12 @@ void RGWEnv::init(CephContext *cct, char **envp) env_map[name] = val; } - conf->init(cct, this); + init(cct); } const char *RGWEnv::get(const char *name, const char *def_val) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); if (iter == env_map.end()) return def_val; @@ -46,7 +60,7 @@ const char *RGWEnv::get(const char *name, const char *def_val) int RGWEnv::get_int(const char *name, int def_val) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); if (iter == env_map.end()) return def_val; @@ -56,7 +70,7 @@ int RGWEnv::get_int(const char *name, int def_val) bool RGWEnv::get_bool(const char *name, bool def_val) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); if (iter == env_map.end()) return def_val; @@ -66,7 +80,7 @@ bool RGWEnv::get_bool(const char *name, bool def_val) size_t RGWEnv::get_size(const char *name, size_t def_val) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); if (iter == env_map.end()) return def_val; @@ -76,7 +90,7 @@ size_t RGWEnv::get_size(const char *name, size_t def_val) bool RGWEnv::exists(const char *name) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); return (iter != env_map.end()); } @@ -85,21 +99,16 @@ bool RGWEnv::exists_prefix(const char *prefix) if (env_map.empty() || prefix == NULL) return false; - map::iterator iter = env_map.lower_bound(prefix); + map::iterator iter = env_map.lower_bound(prefix); if (iter == env_map.end()) return false; return (strncmp(iter->first.c_str(), prefix, strlen(prefix)) == 0); } -void RGWEnv::set(const char *name, const char *val) -{ - env_map[name] = val; -} - void RGWEnv::remove(const char *name) { - map::iterator iter = env_map.find(name); + map::iterator iter = env_map.find(name); if (iter != env_map.end()) env_map.erase(iter); } diff --git a/src/rgw/rgw_fcgi.cc b/src/rgw/rgw_fcgi.cc index 70ed99619754c..e653ee6fc0de7 100644 --- a/src/rgw/rgw_fcgi.cc +++ b/src/rgw/rgw_fcgi.cc @@ -25,7 +25,27 @@ void RGWFCGX::flush() FCGX_FFlush(fcgx->out); } -const char **RGWFCGX::envp() +void RGWFCGX::init_env(CephContext *cct) { - return (const char **)fcgx->envp; + env.init(cct, (char **)fcgx->envp); } + +int RGWFCGX::send_status(const char *status, const char *status_name) +{ + return print("Status: %s\n", status); +} + +int RGWFCGX::send_100_continue() +{ + int r = send_status("100", "Continue"); + if (r >= 0) { + flush(); + } + return r; +} + +int RGWFCGX::complete_header() +{ + return print("\r\n"); +} + diff --git a/src/rgw/rgw_fcgi.h b/src/rgw/rgw_fcgi.h index ccf48f5954da9..16d9fb6ca306f 100644 --- a/src/rgw/rgw_fcgi.h +++ b/src/rgw/rgw_fcgi.h @@ -11,13 +11,16 @@ class RGWFCGX : public RGWClientIO { FCGX_Request *fcgx; protected: + void init_env(CephContext *cct); int write_data(const char *buf, int len); int read_data(char *buf, int len); + int send_status(const char *status, const char *status_name); + int send_100_continue(); + int complete_header(); public: RGWFCGX(FCGX_Request *_fcgx) : fcgx(_fcgx) {} void flush(); - const char **envp(); }; diff --git a/src/rgw/rgw_http_errors.h b/src/rgw/rgw_http_errors.h index ba3e522651f95..0ab19addac068 100644 --- a/src/rgw/rgw_http_errors.h +++ b/src/rgw/rgw_http_errors.h @@ -60,6 +60,52 @@ const static struct rgw_http_errors RGW_HTTP_SWIFT_ERRORS[] = { { ERR_BAD_URL, 412, "Bad URL" }, }; +struct rgw_http_status_code { + int code; + const char *name; +}; + +const static struct rgw_http_status_code http_codes[] = { + { 100, "Continue" }, + { 200, "OK" }, + { 201, "Created" }, + { 202, "Accepted" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 207, "Multi Status" }, + { 208, "Already Reported" }, + { 300, "Multiple Choices" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "User Proxy" }, + { 306, "Switch Proxy" }, + { 307, "Temporary Redirect" }, + { 308, "Permanent Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Timeout" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Long" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested Range Not Satisfiable" }, + { 417, "Expectation Failed" }, + { 422, "Unprocessable Entity" }, + { 500, "Internal Server Error" }, + { 0, NULL }, +}; + #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) static inline const struct rgw_http_errors *search_err(int err_no, const struct rgw_http_errors *errs, int len) diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc index 5fbecf88cab0d..d8d98456106e1 100644 --- a/src/rgw/rgw_main.cc +++ b/src/rgw/rgw_main.cc @@ -51,6 +51,9 @@ #include "rgw_log.h" #include "rgw_tools.h" #include "rgw_resolve.h" +#include "rgw_mongoose.h" + +#include "mongoose/mongoose.h" #include #include @@ -76,7 +79,6 @@ static RGWProcess *pprocess = NULL; struct RGWRequest { - FCGX_Request fcgx; uint64_t id; struct req_state *s; string req_str; @@ -123,51 +125,64 @@ struct RGWRequest } }; + +struct RGWFCGXRequest : public RGWRequest { + FCGX_Request fcgx; +}; + +struct RGWProcessEnv { + RGWRados *store; + RGWREST *rest; + OpsLogSocket *olog; +}; + class RGWProcess { RGWRados *store; OpsLogSocket *olog; - deque m_req_queue; + deque m_req_queue; ThreadPool m_tp; Throttle req_throttle; RGWREST *rest; int sock_fd; - struct RGWWQ : public ThreadPool::WorkQueue { + RGWProcessEnv *process_env; + + struct RGWWQ : public ThreadPool::WorkQueue { RGWProcess *process; RGWWQ(RGWProcess *p, time_t timeout, time_t suicide_timeout, ThreadPool *tp) - : ThreadPool::WorkQueue("RGWWQ", timeout, suicide_timeout, tp), process(p) {} + : ThreadPool::WorkQueue("RGWWQ", timeout, suicide_timeout, tp), process(p) {} - bool _enqueue(RGWRequest *req) { + bool _enqueue(RGWFCGXRequest *req) { process->m_req_queue.push_back(req); perfcounter->inc(l_rgw_qlen); dout(20) << "enqueued request req=" << hex << req << dec << dendl; _dump_queue(); return true; } - void _dequeue(RGWRequest *req) { + void _dequeue(RGWFCGXRequest *req) { assert(0); } bool _empty() { return process->m_req_queue.empty(); } - RGWRequest *_dequeue() { + RGWFCGXRequest *_dequeue() { if (process->m_req_queue.empty()) return NULL; - RGWRequest *req = process->m_req_queue.front(); + RGWFCGXRequest *req = process->m_req_queue.front(); process->m_req_queue.pop_front(); dout(20) << "dequeued request req=" << hex << req << dec << dendl; _dump_queue(); perfcounter->inc(l_rgw_qlen, -1); return req; } - void _process(RGWRequest *req) { + void _process(RGWFCGXRequest *req) { perfcounter->inc(l_rgw_qactive); process->handle_request(req); process->req_throttle.put(1); perfcounter->inc(l_rgw_qactive, -1); } void _dump_queue() { - deque::iterator iter; + deque::iterator iter; if (process->m_req_queue.empty()) { dout(20) << "RGWWQ: empty" << dendl; return; @@ -185,15 +200,15 @@ class RGWProcess { uint64_t max_req_id; public: - RGWProcess(CephContext *cct, RGWRados *rgwstore, OpsLogSocket *_olog, int num_threads, RGWREST *_rest) - : store(rgwstore), olog(_olog), m_tp(cct, "RGWProcess::m_tp", num_threads), + RGWProcess(CephContext *cct, RGWProcessEnv *pe, int num_threads) + : store(pe->store), olog(pe->olog), m_tp(cct, "RGWProcess::m_tp", num_threads), req_throttle(cct, "rgw_ops", num_threads * 2), - rest(_rest), sock_fd(-1), + rest(pe->rest), sock_fd(-1), req_wq(this, g_conf->rgw_op_thread_timeout, g_conf->rgw_op_thread_suicide_timeout, &m_tp), max_req_id(0) {} void run(); - void handle_request(RGWRequest *req); + void handle_request(RGWFCGXRequest *req); void close_fd() { if (sock_fd >= 0) @@ -241,7 +256,7 @@ void RGWProcess::run() m_tp.start(); for (;;) { - RGWRequest *req = new RGWRequest; + RGWFCGXRequest *req = new RGWFCGXRequest; req->id = ++max_req_id; dout(10) << "allocated request req=" << hex << req << dec << dendl; FCGX_InitRequest(&req->fcgx, sock_fd, 0); @@ -295,19 +310,20 @@ static int call_log_intent(RGWRados *store, void *ctx, rgw_obj& obj, RGWIntentEv return rgw_log_intent(store, s, obj, intent); } -void RGWProcess::handle_request(RGWRequest *req) +void RGWProcess::handle_request(RGWFCGXRequest *req) { FCGX_Request *fcgx = &req->fcgx; int ret; - RGWEnv rgw_env; RGWFCGX client_io(fcgx); + client_io.init(g_ceph_context); + req->log_init(); dout(1) << "====== starting new request req=" << hex << req << dec << " =====" << dendl; perfcounter->inc(l_rgw_req); - rgw_env.init(g_ceph_context, fcgx->envp); + RGWEnv& rgw_env = client_io.get_env(); struct req_state *s = req->init_state(g_ceph_context, &rgw_env); s->obj_ctx = store->create_context(s); @@ -414,6 +430,136 @@ done: delete req; } + +static int mongoose_callback(struct mg_event *event) { + RGWProcessEnv *pe = (RGWProcessEnv *)event->user_data; + RGWRados *store = pe->store; + RGWREST *rest = pe->rest; + OpsLogSocket *olog = pe->olog; + + if (event->type != MG_REQUEST_BEGIN) + return 0; + + RGWRequest *req = new RGWRequest; + int ret; + RGWMongoose client_io(event); + + client_io.init(g_ceph_context); + + req->log_init(); + + dout(1) << "====== starting new request req=" << hex << req << dec << " =====" << dendl; + perfcounter->inc(l_rgw_req); + + RGWEnv& rgw_env = client_io.get_env(); + + struct req_state *s = req->init_state(g_ceph_context, &rgw_env); + s->obj_ctx = store->create_context(s); + store->set_intent_cb(s->obj_ctx, call_log_intent); + + s->req_id = store->unique_id(req->id); + + req->log(s, "initializing"); + + RGWOp *op = NULL; + int init_error = 0; + bool should_log = false; + RGWRESTMgr *mgr; + RGWHandler *handler = rest->get_handler(store, s, &client_io, &mgr, &init_error); + if (init_error != 0) { + abort_early(s, NULL, init_error); + goto done; + } + + should_log = mgr->get_logging(); + + req->log(s, "getting op"); + op = handler->get_op(store); + if (!op) { + abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED); + goto done; + } + req->op = op; + + req->log(s, "authorizing"); + ret = handler->authorize(); + if (ret < 0) { + dout(10) << "failed to authorize request" << dendl; + abort_early(s, op, ret); + goto done; + } + + if (s->user.suspended) { + dout(10) << "user is suspended, uid=" << s->user.user_id << dendl; + abort_early(s, op, -ERR_USER_SUSPENDED); + goto done; + } + req->log(s, "reading permissions"); + ret = handler->read_permissions(op); + if (ret < 0) { + abort_early(s, op, ret); + goto done; + } + + req->log(s, "init op"); + ret = op->init_processing(); + if (ret < 0) { + abort_early(s, op, ret); + goto done; + } + + req->log(s, "verifying op mask"); + ret = op->verify_op_mask(); + if (ret < 0) { + abort_early(s, op, ret); + goto done; + } + + req->log(s, "verifying op permissions"); + ret = op->verify_permission(); + if (ret < 0) { + if (s->system_request) { + dout(2) << "overriding permissions due to system operation" << dendl; + } else { + abort_early(s, op, ret); + goto done; + } + } + + req->log(s, "verifying op params"); + ret = op->verify_params(); + if (ret < 0) { + abort_early(s, op, ret); + goto done; + } + + if (s->expect_cont) + dump_continue(s); + + req->log(s, "executing"); + op->execute(); + op->complete(); +done: + if (should_log) { + rgw_log_op(store, s, (op ? op->name() : "unknown"), olog); + } + + int http_ret = s->err.http_ret; + + req->log_format(s, "http status=%d", http_ret); + + if (handler) + handler->put_op(op); + rest->put_handler(handler); + store->destroy_context(s->obj_ctx); + + dout(1) << "====== req done req=" << hex << req << dec << " http_status=" << http_ret << " ======" << dendl; + delete req; + +// Mark as processed + return 1; +} + #ifdef HAVE_CURL_MULTI_WAIT static void check_curl() { @@ -580,7 +726,15 @@ int main(int argc, const char **argv) olog->init(g_conf->rgw_ops_log_socket_path); } - pprocess = new RGWProcess(g_ceph_context, store, olog, g_conf->rgw_thread_pool_size, &rest); + struct mg_context *ctx; + const char *options[] = {"listening_ports", "8080", NULL}; + + RGWProcessEnv pe = { store, &rest, olog }; + + ctx = mg_start((const char **)&options, &mongoose_callback, &pe); + assert(ctx); + + RGWProcess *pprocess = new RGWProcess(g_ceph_context, &pe, g_conf->rgw_thread_pool_size); init_async_signal_handler(); register_async_signal_handler(SIGHUP, sighup_handler); @@ -591,6 +745,9 @@ int main(int argc, const char **argv) sighandler_alrm = signal(SIGALRM, godown_alarm); pprocess->run(); + + mg_stop(ctx); + derr << "shutting down" << dendl; unregister_async_signal_handler(SIGHUP, sighup_handler); diff --git a/src/rgw/rgw_mongoose.cc b/src/rgw/rgw_mongoose.cc new file mode 100644 index 0000000000000..cbbc19226f870 --- /dev/null +++ b/src/rgw/rgw_mongoose.cc @@ -0,0 +1,112 @@ + +#include + +#include "mongoose/mongoose.h" +#include "rgw_mongoose.h" + + +#define dout_subsys ceph_subsys_rgw + +int RGWMongoose::write_data(const char *buf, int len) +{ + if (!sent_header) { + header_data.append(buf, len); + return 0; + } + dout(0) << buf << dendl; + return mg_write(event->conn, buf, len); +} + +RGWMongoose::RGWMongoose(mg_event *_event) : event(_event), sent_header(false) { +} + +int RGWMongoose::read_data(char *buf, int len) +{ + return mg_read(event->conn, buf, len); +} + +void RGWMongoose::flush() +{ +} + +void RGWMongoose::init_env(CephContext *cct) +{ + env.init(cct); + struct mg_request_info *info = event->request_info; + if (!info) + return; + + for (int i = 0; i < info->num_headers; i++) { + struct mg_request_info::mg_header *header = &info->http_headers[i]; + + if (strcasecmp(header->name, "content-length") == 0) { + env.set("CONTENT_LENGTH", header->value); + continue; + } + + if (strcasecmp(header->name, "content-type") == 0) { + env.set("CONTENT_TYPE", header->value); + continue; + } + + int len = strlen(header->name) + 5; /* HTTP_ prepended */ + char buf[len + 1]; + memcpy(buf, "HTTP_", 5); + const char *src = header->name; + char *dest = &buf[5]; + for (; *src; src++, dest++) { + char c = *src; + switch (c) { + case '-': + c = '_'; + break; + default: + c = toupper(c); + break; + } + *dest = c; + } + *dest = '\0'; + + env.set(buf, header->value); + } + + env.set("REQUEST_METHOD", info->request_method); + env.set("REQUEST_URI", info->uri); + env.set("QUERY_STRING", info->query_string); + env.set("REMOTE_USER", info->remote_user); + env.set("SCRIPT_URI", info->uri); /* FIXME */ +} + +int RGWMongoose::send_status(const char *status, const char *status_name) +{ + char buf[128]; + + if (!status_name) + status_name = ""; + + snprintf(buf, sizeof(buf), "HTTP/1.1 %s %s\n", status, status_name); + + bufferlist bl; + bl.append(buf); + bl.append(header_data); + header_data = bl; + + return 0; +} + +int RGWMongoose::send_100_continue() +{ + char buf[] = "HTTP/1.1 100 CONTINUE\r\n\r\n"; + + return mg_write(event->conn, buf, sizeof(buf) - 1); +} + +int RGWMongoose::complete_header() +{ + header_data.append("\r\n"); + + sent_header = true; + + return write_data(header_data.c_str(), header_data.length()); +} diff --git a/src/rgw/rgw_mongoose.h b/src/rgw/rgw_mongoose.h new file mode 100644 index 0000000000000..33787d0e61327 --- /dev/null +++ b/src/rgw/rgw_mongoose.h @@ -0,0 +1,35 @@ +#ifndef CEPH_RGW_MONGOOSE_H +#define CEPH_RGW_MONGOOSE_H + +#include "rgw_client_io.h" + + +struct mg_event; +struct mg_connection; + + +class RGWMongoose : public RGWClientIO +{ + mg_event *event; + + bufferlist header_data; + + bool sent_header; + +protected: + void init_env(CephContext *cct); + + int write_data(const char *buf, int len); + int read_data(char *buf, int len); + + int send_status(const char *status, const char *status_name); + int send_100_continue(); + int complete_header(); + +public: + RGWMongoose(mg_event *_event); + void flush(); +}; + + +#endif diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index c750276596f83..ad924c1b9f92e 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2606,14 +2606,6 @@ int RGWHandler::init(RGWRados *_store, struct req_state *_s, RGWClientIO *cio) store = _store; s = _s; - if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) { - const char *p; - const char **envp = cio->envp(); - for (int i=0; (p = envp[i]); ++i) { - ldout(s->cct, 20) << p << dendl; - } - } - return 0; } diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 30cb0d9b66e5e..f05728ec9fdb4 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -13,6 +13,7 @@ #include "rgw_rest_s3.h" #include "rgw_swift_auth.h" #include "rgw_cors_s3.h" +#include "rgw_http_errors.h" #include "rgw_client_io.h" #include "rgw_resolve.h" @@ -59,6 +60,7 @@ struct generic_attr generic_attrs[] = { map rgw_to_http_attrs; static map generic_attrs_map; +map http_status_names; /* * make attrs look_like_this @@ -155,13 +157,17 @@ void rgw_rest_init(CephContext *cct) generic_attrs_map[http_header] = rgw_attr; } + + for (const struct rgw_http_status_code *h = http_codes; h->code; h++) { + http_status_names[h->code] = h->name; + } } -static void dump_status(struct req_state *s, const char *status) +static void dump_status(struct req_state *s, const char *status, const char *status_name) { - int r = s->cio->print("Status: %s\n", status); + int r = s->cio->send_status(status, status_name); if (r < 0) { - ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl; + ldout(s->cct, 0) << "ERROR: s->cio->send_status() returned err=" << r << dendl; } } @@ -218,14 +224,14 @@ void dump_errno(struct req_state *s) { char buf[32]; snprintf(buf, sizeof(buf), "%d", s->err.http_ret); - dump_status(s, buf); + dump_status(s, buf, http_status_names[s->err.http_ret]); } void dump_errno(struct req_state *s, int err) { char buf[32]; snprintf(buf, sizeof(buf), "%d", err); - dump_status(s, buf); + dump_status(s, buf, http_status_names[s->err.http_ret]); } void dump_content_length(struct req_state *s, uint64_t len) @@ -434,10 +440,15 @@ void end_header(struct req_state *s, RGWOp *op, const char *content_type) s->formatter->close_section(); dump_content_length(s, s->formatter->get_len()); } - int r = s->cio->print("Content-type: %s\r\n\r\n", content_type); + int r = s->cio->print("Content-type: %s\r\n", content_type); if (r < 0) { ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl; } + r = s->cio->complete_header(); + if (r < 0) { + ldout(s->cct, 0) << "ERROR: s->cio->complete_header() returned err=" << r << dendl; + } + s->cio->set_account(true); rgw_flush_formatter_and_reset(s, s->formatter); } @@ -457,8 +468,7 @@ void abort_early(struct req_state *s, RGWOp *op, int err_no) void dump_continue(struct req_state *s) { - dump_status(s, "100"); - s->cio->flush(); + s->cio->send_100_continue(); } void dump_range(struct req_state *s, uint64_t ofs, uint64_t end, uint64_t total) diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc index 7f4e2b6582dc1..256db77aba771 100644 --- a/src/rgw/rgw_rest_client.cc +++ b/src/rgw/rgw_rest_client.cc @@ -171,7 +171,7 @@ void RGWRESTSimpleRequest::get_params_str(map& extra_args, strin int RGWRESTSimpleRequest::sign_request(RGWAccessKey& key, RGWEnv& env, req_info& info) { - map& m = env.get_map(); + map& m = env.get_map(); map::iterator i; for (i = m.begin(); i != m.end(); ++i) { @@ -218,7 +218,7 @@ int RGWRESTSimpleRequest::forward_request(RGWAccessKey& key, req_info& info, siz return ret; } - map& m = new_env.get_map(); + map& m = new_env.get_map(); map::iterator iter; for (iter = m.begin(); iter != m.end(); ++iter) { headers.push_back(make_pair(iter->first, iter->second)); @@ -364,7 +364,7 @@ static void grants_by_type_add_perm(map& grants_by_type, int perm, } } -static void add_grants_headers(map& grants, map& attrs, map& meta_map) +static void add_grants_headers(map& grants, map& attrs, map& meta_map) { struct grant_type_to_header *t; @@ -405,7 +405,7 @@ int RGWRESTStreamWriteRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uin new_info.request_uri = new_info.script_uri; new_info.effective_uri = new_info.effective_uri; - map& m = new_env.get_map(); + map& m = new_env.get_map(); map::iterator bliter; /* merge send headers */ @@ -582,7 +582,7 @@ int RGWRESTStreamReadRequest::get_obj(RGWAccessKey& key, map& ex return ret; } - map& m = new_env.get_map(); + map& m = new_env.get_map(); map::iterator iter; for (iter = m.begin(); iter != m.end(); ++iter) { headers.push_back(make_pair(iter->first, iter->second)); diff --git a/src/rgw/rgw_rest_conn.cc b/src/rgw/rgw_rest_conn.cc index 35a8ac258e635..32bf0eaacd390 100644 --- a/src/rgw/rgw_rest_conn.cc +++ b/src/rgw/rgw_rest_conn.cc @@ -92,7 +92,7 @@ int RGWRESTConn::get_obj(const string& uid, req_info *info /* optional */, rgw_o *req = new RGWRESTStreamReadRequest(cct, url, cb, NULL, ¶ms); map extra_headers; if (info) { - map& orig_map = info->env->get_map(); + map& orig_map = info->env->get_map(); /* add original headers that start with HTTP_X_AMZ_ */ #define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_" -- 2.39.5