summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-09-04 16:18:38 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-09-04 16:18:38 -0700
commitea412c05f61e54c7a6749ca0b699e5fcbafa6191 (patch)
tree267416d002f8eb94b8b13e5d3d2d1b414789c2c1
parentd9187a73c3e1f21f0be894e983feb4a7d495b729 (diff)
parent6af5a5377f9730aeee3fc1432445becea47794dd (diff)
downloadceph-ea412c05f61e54c7a6749ca0b699e5fcbafa6191.tar.gz
Merge branch 'wip-6078' into next
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--src/rgw/rgw_common.cc5
-rw-r--r--src/rgw/rgw_common.h1
-rw-r--r--src/rgw/rgw_cors.cc3
-rw-r--r--src/rgw/rgw_cors.h12
-rw-r--r--src/rgw/rgw_cors_s3.cc4
-rw-r--r--src/rgw/rgw_main.cc16
-rw-r--r--src/rgw/rgw_op.cc204
-rw-r--r--src/rgw/rgw_op.h9
-rw-r--r--src/rgw/rgw_rest.cc30
-rw-r--r--src/rgw/rgw_rest.h15
-rw-r--r--src/rgw/rgw_rest_s3.cc53
-rw-r--r--src/rgw/rgw_rest_swift.cc28
12 files changed, 231 insertions, 149 deletions
diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc
index ef0a2604d51..c872314fe4e 100644
--- a/src/rgw/rgw_common.cc
+++ b/src/rgw/rgw_common.cc
@@ -123,8 +123,8 @@ void req_info::rebuild_from(req_info& src)
req_state::req_state(CephContext *_cct, class RGWEnv *e) : cct(_cct), cio(NULL), op(OP_UNKNOWN),
- bucket_cors(NULL), has_acl_header(false),
- os_auth_token(NULL), info(_cct, e)
+ has_acl_header(false),
+ os_auth_token(NULL), info(_cct, e)
{
enable_ops_log = e->conf->enable_ops_log;
enable_usage_log = e->conf->enable_usage_log;
@@ -162,7 +162,6 @@ req_state::req_state(CephContext *_cct, class RGWEnv *e) : cct(_cct), cio(NULL),
req_state::~req_state() {
delete formatter;
delete bucket_acl;
- delete bucket_cors;
delete object_acl;
free((void *)object);
free((void *)bucket_name);
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h
index 405c3d9b3ba..2c7c0c716be 100644
--- a/src/rgw/rgw_common.h
+++ b/src/rgw/rgw_common.h
@@ -821,7 +821,6 @@ struct req_state {
RGWUserInfo user;
RGWAccessControlPolicy *bucket_acl;
RGWAccessControlPolicy *object_acl;
- RGWCORSConfiguration *bucket_cors;
bool system_request;
diff --git a/src/rgw/rgw_cors.cc b/src/rgw/rgw_cors.cc
index 033bfa2f215..4be83605b50 100644
--- a/src/rgw/rgw_cors.cc
+++ b/src/rgw/rgw_cors.cc
@@ -79,7 +79,10 @@ static bool is_string_in_set(set<string>& s, string h) {
<< ", at offset not less than " << flen << dendl;
if (h.compare((h.size() - sl.size()), sl.size(), sl) != 0)
continue;
+ ssplit.pop_front();
}
+ if (!ssplit.empty())
+ continue;
return true;
}
}
diff --git a/src/rgw/rgw_cors.h b/src/rgw/rgw_cors.h
index 415f3f0b869..1e0ec3bc7ec 100644
--- a/src/rgw/rgw_cors.h
+++ b/src/rgw/rgw_cors.h
@@ -25,11 +25,13 @@
#define RGW_CORS_HEAD 0x4
#define RGW_CORS_POST 0x8
#define RGW_CORS_DELETE 0x10
-#define RGW_CORS_ALL (RGW_CORS_GET | \
- RGW_CORS_PUT | \
- RGW_CORS_HEAD | \
- RGW_CORS_POST | \
- RGW_CORS_DELETE)
+#define RGW_CORS_COPY 0x20
+#define RGW_CORS_ALL (RGW_CORS_GET | \
+ RGW_CORS_PUT | \
+ RGW_CORS_HEAD | \
+ RGW_CORS_POST | \
+ RGW_CORS_DELETE | \
+ RGW_CORS_COPY)
#define CORS_MAX_AGE_INVALID ((uint32_t)-1)
diff --git a/src/rgw/rgw_cors_s3.cc b/src/rgw/rgw_cors_s3.cc
index c1448f26b23..01150a9e65b 100644
--- a/src/rgw/rgw_cors_s3.cc
+++ b/src/rgw/rgw_cors_s3.cc
@@ -44,6 +44,8 @@ void RGWCORSRule_S3::to_xml(XMLFormatter& f) {
f.dump_string("AllowedMethod", "HEAD");
if (allowed_methods & RGW_CORS_POST)
f.dump_string("AllowedMethod", "POST");
+ if (allowed_methods & RGW_CORS_COPY)
+ f.dump_string("AllowedMethod", "COPY");
/*AllowedOrigins*/
for(set<string>::iterator it = allowed_origins.begin();
it != allowed_origins.end();
@@ -87,6 +89,8 @@ bool RGWCORSRule_S3::xml_end(const char *el) {
allowed_methods |= RGW_CORS_HEAD;
} else if (strcasecmp(s, "PUT") == 0) {
allowed_methods |= RGW_CORS_PUT;
+ } else if (strcasecmp(s, "COPY") == 0) {
+ allowed_methods |= RGW_CORS_COPY;
} else {
return false;
}
diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc
index 12301ba9c5f..54db609521c 100644
--- a/src/rgw/rgw_main.cc
+++ b/src/rgw/rgw_main.cc
@@ -323,7 +323,7 @@ void RGWProcess::handle_request(RGWRequest *req)
RGWRESTMgr *mgr;
RGWHandler *handler = rest->get_handler(store, s, &client_io, &mgr, &init_error);
if (init_error != 0) {
- abort_early(s, init_error);
+ abort_early(s, NULL, init_error);
goto done;
}
@@ -332,7 +332,7 @@ void RGWProcess::handle_request(RGWRequest *req)
req->log(s, "getting op");
op = handler->get_op(store);
if (!op) {
- abort_early(s, -ERR_METHOD_NOT_ALLOWED);
+ abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED);
goto done;
}
req->op = op;
@@ -341,26 +341,26 @@ void RGWProcess::handle_request(RGWRequest *req)
ret = handler->authorize();
if (ret < 0) {
dout(10) << "failed to authorize request" << dendl;
- abort_early(s, ret);
+ 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, -ERR_USER_SUSPENDED);
+ 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, ret);
+ abort_early(s, op, ret);
goto done;
}
req->log(s, "verifying op mask");
ret = op->verify_op_mask();
if (ret < 0) {
- abort_early(s, ret);
+ abort_early(s, op, ret);
goto done;
}
@@ -370,7 +370,7 @@ void RGWProcess::handle_request(RGWRequest *req)
if (s->system_request) {
dout(2) << "overriding permissions due to system operation" << dendl;
} else {
- abort_early(s, ret);
+ abort_early(s, op, ret);
goto done;
}
}
@@ -378,7 +378,7 @@ void RGWProcess::handle_request(RGWRequest *req)
req->log(s, "verifying op params");
ret = op->verify_params();
if (ret < 0) {
- abort_early(s, ret);
+ abort_early(s, op, ret);
goto done;
}
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc
index d34e18bc4ba..15e51712ca3 100644
--- a/src/rgw/rgw_op.cc
+++ b/src/rgw/rgw_op.cc
@@ -421,6 +421,111 @@ int RGWOp::verify_op_mask()
return 0;
}
+static bool validate_cors_rule_method(RGWCORSRule *rule, const char *req_meth) {
+ uint8_t flags = 0;
+ if (strcmp(req_meth, "GET") == 0) flags = RGW_CORS_GET;
+ else if (strcmp(req_meth, "POST") == 0) flags = RGW_CORS_POST;
+ else if (strcmp(req_meth, "PUT") == 0) flags = RGW_CORS_PUT;
+ else if (strcmp(req_meth, "DELETE") == 0) flags = RGW_CORS_DELETE;
+ else if (strcmp(req_meth, "HEAD") == 0) flags = RGW_CORS_HEAD;
+
+ if ((rule->get_allowed_methods() & flags) == flags) {
+ dout(10) << "Method " << req_meth << " is supported" << dendl;
+ } else {
+ dout(5) << "Method " << req_meth << " is not supported" << dendl;
+ return false;
+ }
+
+ return true;
+}
+
+int RGWOp::read_bucket_cors()
+{
+ bufferlist bl;
+
+ map<string, bufferlist>::iterator aiter = s->bucket_attrs.find(RGW_ATTR_CORS);
+ if (aiter == s->bucket_attrs.end()) {
+ ldout(s->cct, 20) << "no CORS configuration attr found" << dendl;
+ cors_exist = false;
+ return 0; /* no CORS configuration found */
+ }
+
+ cors_exist = true;
+
+ bl = aiter->second;
+
+ bufferlist::iterator iter = bl.begin();
+ try {
+ bucket_cors.decode(iter);
+ } catch (buffer::error& err) {
+ ldout(s->cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
+ return -EIO;
+ }
+ if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 15)) {
+ RGWCORSConfiguration_S3 *s3cors = static_cast<RGWCORSConfiguration_S3 *>(&bucket_cors);
+ ldout(s->cct, 15) << "Read RGWCORSConfiguration";
+ s3cors->to_xml(*_dout);
+ *_dout << dendl;
+ }
+ return 0;
+}
+
+static void get_cors_response_headers(RGWCORSRule *rule, const char *req_hdrs, string& hdrs, string& exp_hdrs, unsigned *max_age) {
+ if (req_hdrs) {
+ list<string> hl;
+ get_str_list(req_hdrs, hl);
+ for(list<string>::iterator it = hl.begin(); it != hl.end(); ++it) {
+ if (!rule->is_header_allowed((*it).c_str(), (*it).length())) {
+ dout(5) << "Header " << (*it) << " is not registered in this rule" << dendl;
+ } else {
+ if (hdrs.length() > 0) hdrs.append(",");
+ hdrs.append((*it));
+ }
+ }
+ }
+ rule->format_exp_headers(exp_hdrs);
+ *max_age = rule->get_max_age();
+}
+
+bool RGWOp::generate_cors_headers(string& origin, string& method, string& headers, string& exp_headers, unsigned *max_age)
+{
+ const char *orig = s->info.env->get("HTTP_ORIGIN");
+ if (!orig) {
+ return false;
+ }
+ origin = orig;
+ int ret = read_bucket_cors();
+ if (ret < 0) {
+ return false;
+ }
+
+ if (!cors_exist) {
+ dout(2) << "No CORS configuration set yet for this bucket" << dendl;
+ return false;
+ }
+
+ RGWCORSRule *rule = bucket_cors.host_name_rule(orig);
+ if (!rule)
+ return false;
+
+ const char *req_meth = s->info.env->get("HTTP_ACCESS_CONTROL_REQUEST_METHOD");
+ if (!req_meth) {
+ req_meth = s->info.method;
+ }
+
+ if (req_meth)
+ method = req_meth;
+
+ if (!validate_cors_rule_method(rule, req_meth)) {
+ return false;
+ }
+
+ const char *req_hdrs = s->info.env->get("HTTP_ACCESS_CONTROL_ALLOW_HEADERS");
+
+ get_cors_response_headers(rule, req_hdrs, headers, exp_headers, max_age);
+
+ return true;
+}
int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket, RGWObjEnt& ent, RGWAccessControlPolicy *bucket_policy, off_t start_ofs, off_t end_ofs)
{
@@ -1835,37 +1940,6 @@ void RGWPutACLs::execute()
}
}
-static int read_bucket_cors(RGWRados *store, struct req_state *s, RGWCORSConfiguration *bucket_cors, bool *exist)
-{
- bufferlist bl;
-
- map<string, bufferlist>::iterator aiter = s->bucket_attrs.find(RGW_ATTR_CORS);
- if (aiter == s->bucket_attrs.end()) {
- ldout(s->cct, 20) << "no CORS configuration attr found" << dendl;
- *exist = false;
- return 0; /* no CORS configuration found */
- }
-
- *exist = true;
-
- bl = aiter->second;
-
- bufferlist::iterator iter = bl.begin();
- try {
- bucket_cors->decode(iter);
- } catch (buffer::error& err) {
- ldout(s->cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
- return -EIO;
- }
- if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 15)) {
- RGWCORSConfiguration_S3 *s3cors = static_cast<RGWCORSConfiguration_S3 *>(bucket_cors);
- ldout(s->cct, 15) << "Read RGWCORSConfiguration";
- s3cors->to_xml(*_dout);
- *_dout << dendl;
- }
- return 0;
-}
-
int RGWGetCORS::verify_permission()
{
if (s->user.user_id.compare(s->bucket_owner.get_id()) != 0)
@@ -1876,9 +1950,7 @@ int RGWGetCORS::verify_permission()
void RGWGetCORS::execute()
{
- bool cors_exist;
-
- ret = read_bucket_cors(store, s, &bucket_cors, &cors_exist);
+ ret = read_bucket_cors();
if (ret < 0)
return ;
@@ -1922,9 +1994,8 @@ int RGWDeleteCORS::verify_permission()
void RGWDeleteCORS::execute()
{
- bool cors_exist;
RGWCORSConfiguration bucket_cors;
- ret = read_bucket_cors(store, s, &bucket_cors, &cors_exist);
+ ret = read_bucket_cors();
if (ret < 0)
return;
@@ -1961,52 +2032,34 @@ void RGWDeleteCORS::execute()
}
void RGWOptionsCORS::get_response_params(string& hdrs, string& exp_hdrs, unsigned *max_age) {
- if (req_hdrs) {
- list<string> hl;
- get_str_list(req_hdrs, hl);
- for(list<string>::iterator it = hl.begin(); it != hl.end(); ++it) {
- if (!rule->is_header_allowed((*it).c_str(), (*it).length())) {
- dout(5) << "Header " << (*it) << " is not registered in this rule" << dendl;
- } else {
- if (hdrs.length() > 0)hdrs.append(",");
- hdrs.append((*it));
- }
- }
- }
- rule->format_exp_headers(exp_hdrs);
- *max_age = rule->get_max_age();
+ get_cors_response_headers(rule, req_hdrs, hdrs, exp_hdrs, max_age);
}
-int RGWOptionsCORS::validate_cors_request() {
- RGWCORSConfiguration *cc = s->bucket_cors;
+int RGWOptionsCORS::validate_cors_request(RGWCORSConfiguration *cc) {
rule = cc->host_name_rule(origin);
if (!rule) {
- dout(10) << "There is no corsrule present for " << origin << dendl;
+ dout(10) << "There is no cors rule present for " << origin << dendl;
return -ENOENT;
}
- uint8_t flags = 0;
- if (strcmp(req_meth, "GET") == 0) flags = RGW_CORS_GET;
- else if (strcmp(req_meth, "POST") == 0) flags = RGW_CORS_POST;
- else if (strcmp(req_meth, "PUT") == 0) flags = RGW_CORS_PUT;
- else if (strcmp(req_meth, "DELETE") == 0) flags = RGW_CORS_DELETE;
- else if (strcmp(req_meth, "HEAD") == 0) flags = RGW_CORS_HEAD;
-
- if ((rule->get_allowed_methods() & flags) == flags) {
- dout(10) << "Method " << req_meth << " is supported" << dendl;
- } else {
- dout(5) << "Method " << req_meth << " is not supported" << dendl;
- req_meth = NULL;
- return -ENOTSUP;
+ if (!validate_cors_rule_method(rule, req_meth)) {
+ return -ENOENT;
}
return 0;
}
void RGWOptionsCORS::execute()
{
- if (!s->bucket_cors) {
- dout(2) << "No CORS configuration set yet for this bucket" << dendl;
- ret = -EACCES;
+ ret = read_bucket_cors();
+ if (ret < 0)
+ return;
+
+ origin = s->info.env->get("HTTP_ORIGIN");
+ if (!origin) {
+ dout(0) <<
+ "Preflight request without mandatory Origin header"
+ << dendl;
+ ret = -EINVAL;
return;
}
req_meth = s->info.env->get("HTTP_ACCESS_CONTROL_REQUEST_METHOD");
@@ -2014,19 +2067,16 @@ void RGWOptionsCORS::execute()
dout(0) <<
"Preflight request without mandatory Access-control-request-method header"
<< dendl;
- ret = -EACCES;
+ ret = -EINVAL;
return;
}
- origin = s->info.env->get("HTTP_ORIGIN");
- if (!origin) {
- dout(0) <<
- "Preflight request without mandatory Origin header"
- << dendl;
- ret = -EACCES;
+ if (!cors_exist) {
+ dout(2) << "No CORS configuration set yet for this bucket" << dendl;
+ ret = -ENOENT;
return;
}
req_hdrs = s->info.env->get("HTTP_ACCESS_CONTROL_ALLOW_HEADERS");
- ret = validate_cors_request();
+ ret = validate_cors_request(&bucket_cors);
if (!rule) {
origin = req_meth = NULL;
return;
diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h
index d158f831cc7..241584bac68 100644
--- a/src/rgw/rgw_op.h
+++ b/src/rgw/rgw_op.h
@@ -34,8 +34,10 @@ protected:
struct req_state *s;
RGWHandler *dialect_handler;
RGWRados *store;
+ RGWCORSConfiguration bucket_cors;
+ bool cors_exist;
public:
- RGWOp() : s(NULL), dialect_handler(NULL), store(NULL) {}
+ RGWOp() : s(NULL), dialect_handler(NULL), store(NULL), cors_exist(false) {}
virtual ~RGWOp() {}
virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
@@ -43,6 +45,9 @@ public:
this->s = s;
this->dialect_handler = dialect_handler;
}
+ int read_bucket_cors();
+ bool generate_cors_headers(string& origin, string& method, string& headers, string& exp_headers, unsigned *max_age);
+
virtual int verify_params() { return 0; }
virtual bool prefetch_data() { return false; }
virtual int verify_permission() = 0;
@@ -586,7 +591,7 @@ public:
}
int verify_permission() {return 0;}
- int validate_cors_request();
+ int validate_cors_request(RGWCORSConfiguration *cc);
void execute();
void get_response_params(string& allowed_hdrs, string& exp_hdrs, unsigned *max_age);
virtual void send_response() = 0;
diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc
index 571e4869642..196bd29e99b 100644
--- a/src/rgw/rgw_rest.cc
+++ b/src/rgw/rgw_rest.cc
@@ -377,6 +377,20 @@ void dump_access_control(struct req_state *s, const char *origin, const char *me
}
}
+void dump_access_control(req_state *s, RGWOp *op)
+{
+ string origin;
+ string method;
+ string header;
+ string exp_header;
+ unsigned max_age = CORS_MAX_AGE_INVALID;
+
+ if (!op->generate_cors_headers(origin, method, header, exp_header, &max_age))
+ return;
+
+ dump_access_control(s, origin.c_str(), method.c_str(), header.c_str(), exp_header.c_str(), max_age);
+}
+
void dump_start(struct req_state *s)
{
if (!s->content_started) {
@@ -386,10 +400,14 @@ void dump_start(struct req_state *s)
}
}
-void end_header(struct req_state *s, const char *content_type)
+void end_header(struct req_state *s, RGWOp *op, const char *content_type)
{
string ctype;
+ if (op) {
+ dump_access_control(s, op);
+ }
+
if (!content_type || s->err.is_err()) {
switch (s->format) {
case RGW_FORMAT_XML:
@@ -424,7 +442,7 @@ void end_header(struct req_state *s, const char *content_type)
rgw_flush_formatter_and_reset(s, s->formatter);
}
-void abort_early(struct req_state *s, int err_no)
+void abort_early(struct req_state *s, RGWOp *op, int err_no)
{
if (!s->formatter) {
s->formatter = new JSONFormatter;
@@ -432,7 +450,7 @@ void abort_early(struct req_state *s, int err_no)
}
set_req_state_err(s, err_no);
dump_errno(s);
- end_header(s);
+ end_header(s, op);
rgw_flush_formatter_and_reset(s, s->formatter);
perfcounter->inc(l_rgw_failed_req);
}
@@ -644,7 +662,7 @@ void RGWRESTFlusher::do_start(int ret)
set_req_state_err(s, ret); /* no going back from here */
dump_errno(s);
dump_start(s);
- end_header(s);
+ end_header(s, op);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -927,7 +945,7 @@ void RGWRESTOp::send_response()
if (!flusher.did_start()) {
set_req_state_err(s, http_ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
}
flusher.flush();
}
@@ -1062,7 +1080,7 @@ int RGWHandler_ObjStore::read_permissions(RGWOp *op_obj)
case OP_COPY: // op itself will read and verify the permissions
return 0;
case OP_OPTIONS:
- only_bucket = false;
+ only_bucket = true;
break;
default:
return -EINVAL;
diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h
index b65efb3de3e..15ac863aa52 100644
--- a/src/rgw/rgw_rest.h
+++ b/src/rgw/rgw_rest.h
@@ -33,15 +33,17 @@ public:
class RGWRESTFlusher : public RGWFormatterFlusher {
struct req_state *s;
+ RGWOp *op;
protected:
virtual void do_flush();
virtual void do_start(int ret);
public:
- RGWRESTFlusher(struct req_state *_s) : RGWFormatterFlusher(_s->formatter), s(_s) {}
- RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL) {}
+ RGWRESTFlusher(struct req_state *_s, RGWOp *_op) : RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {}
+ RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {}
- void init(struct req_state *_s) {
+ void init(struct req_state *_s, RGWOp *_op) {
s = _s;
+ op = _op;
set_formatter(s->formatter);
}
};
@@ -228,7 +230,7 @@ public:
RGWRESTOp() : http_ret(0) {}
virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
RGWOp::init(store, s, dialect_handler);
- flusher.init(s);
+ flusher.init(s, this);
}
virtual void send_response();
virtual int check_caps(RGWUserCaps& caps) { return -EPERM; } /* should to be implemented! */
@@ -310,7 +312,7 @@ public:
extern void set_req_state_err(struct req_state *s, int err_no);
extern void dump_errno(struct req_state *s);
extern void dump_errno(struct req_state *s, int ret);
-extern void end_header(struct req_state *s, const char *content_type = NULL);
+extern void end_header(struct req_state *s, RGWOp *op = NULL, const char *content_type = NULL);
extern void dump_start(struct req_state *s);
extern void list_all_buckets_start(struct req_state *s);
extern void dump_owner(struct req_state *s, string& id, string& name, const char *section = NULL);
@@ -318,7 +320,7 @@ extern void dump_content_length(struct req_state *s, uint64_t len);
extern void dump_etag(struct req_state *s, const char *etag);
extern void dump_epoch_header(struct req_state *s, const char *name, time_t t);
extern void dump_last_modified(struct req_state *s, time_t t);
-extern void abort_early(struct req_state *s, int err);
+extern void abort_early(struct req_state *s, RGWOp *op, int err);
extern void dump_range(struct req_state *s, uint64_t ofs, uint64_t end, uint64_t total_size);
extern void dump_continue(struct req_state *s);
extern void list_all_buckets_end(struct req_state *s);
@@ -331,6 +333,7 @@ extern void dump_pair(struct req_state *s, const char *key, const char *value);
extern bool is_valid_url(const char *url);
extern void dump_access_control(struct req_state *s, const char *origin, const char *meth,
const char *hdr, const char *exp_hdr, uint32_t max_age);
+extern void dump_access_control(req_state *s, RGWOp *op);
#endif
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 71bb418c53c..a9a391fc348 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -166,7 +166,8 @@ done:
if (!content_type)
content_type = "binary/octet-stream";
- end_header(s, content_type);
+
+ end_header(s, this, content_type);
if (metadata_bl.length()) {
s->cio->write(metadata_bl.c_str(), metadata_bl.length());
@@ -189,7 +190,7 @@ void RGWListBuckets_ObjStore_S3::send_response_begin(bool has_buckets)
set_req_state_err(s, ret);
dump_errno(s);
dump_start(s);
- end_header(s, "application/xml");
+ end_header(s, NULL, "application/xml");
if (!ret) {
list_all_buckets_start(s);
@@ -242,7 +243,7 @@ void RGWListBucket_ObjStore_S3::send_response()
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
dump_start(s);
if (ret < 0)
return;
@@ -288,7 +289,7 @@ void RGWListBucket_ObjStore_S3::send_response()
void RGWGetBucketLogging_ObjStore_S3::send_response()
{
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
dump_start(s);
s->formatter->open_object_section_in_ns("BucketLoggingStatus",
@@ -315,7 +316,7 @@ void RGWStatBucket_ObjStore_S3::send_response()
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
dump_start(s);
}
@@ -467,7 +468,7 @@ void RGWDeleteBucket_ObjStore_S3::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
if (s->system_request) {
JSONFormatter f; /* use json formatter for system requests output */
@@ -521,7 +522,7 @@ void RGWPutObj_ObjStore_S3::send_response()
dump_epoch_header(s, "Rgwx-Mtime", mtime);
}
dump_errno(s);
- end_header(s);
+ end_header(s, this);
}
/*
@@ -1206,7 +1207,7 @@ done:
set_req_state_err(s, ret);
dump_errno(s);
dump_content_length(s, s->formatter->get_len());
- end_header(s);
+ end_header(s, this);
if (ret != STATUS_CREATED)
return;
@@ -1224,7 +1225,7 @@ void RGWDeleteObj_ObjStore_S3::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
}
int RGWCopyObj_ObjStore_S3::init_dest_policy()
@@ -1308,7 +1309,7 @@ void RGWCopyObj_ObjStore_S3::send_partial_response(off_t ofs)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "binary/octet-stream");
+ end_header(s, this, "binary/octet-stream");
if (ret == 0) {
s->formatter->open_object_section("CopyObjectResult");
}
@@ -1347,7 +1348,7 @@ void RGWGetACLs_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
dump_start(s);
s->cio->write(acls.c_str(), acls.size());
}
@@ -1376,7 +1377,7 @@ void RGWPutACLs_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
dump_start(s);
}
@@ -1389,7 +1390,7 @@ void RGWGetCORS_ObjStore_S3::send_response()
set_req_state_err(s, ret);
}
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, NULL, "application/xml");
dump_start(s);
if (!ret) {
string cors;
@@ -1464,7 +1465,7 @@ void RGWPutCORS_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, NULL, "application/xml");
dump_start(s);
}
@@ -1476,7 +1477,7 @@ void RGWDeleteCORS_ObjStore_S3::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
}
void RGWOptionsCORS_ObjStore_S3::send_response()
@@ -1485,22 +1486,20 @@ void RGWOptionsCORS_ObjStore_S3::send_response()
uint32_t max_age = CORS_MAX_AGE_INVALID;
/*EACCES means, there is no CORS registered yet for the bucket
*ENOENT means, there is no match of the Origin in the list of CORSRule
- *ENOTSUPP means, the HTTP_METHOD is not supported
*/
if (ret == -ENOENT)
ret = -EACCES;
- if (ret != -EACCES) {
- get_response_params(hdrs, exp_hdrs, &max_age);
- } else {
+ if (ret < 0) {
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
return;
}
+ get_response_params(hdrs, exp_hdrs, &max_age);
dump_errno(s);
dump_access_control(s, origin, req_meth, hdrs.c_str(), exp_hdrs.c_str(), max_age);
- end_header(s);
+ end_header(s, NULL);
}
int RGWInitMultipart_ObjStore_S3::get_params()
@@ -1520,7 +1519,7 @@ void RGWInitMultipart_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
if (ret == 0) {
dump_start(s);
s->formatter->open_object_section_in_ns("InitiateMultipartUploadResult",
@@ -1538,7 +1537,7 @@ void RGWCompleteMultipart_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
if (ret == 0) {
dump_start(s);
s->formatter->open_object_section_in_ns("CompleteMultipartUploadResult",
@@ -1561,7 +1560,7 @@ void RGWAbortMultipart_ObjStore_S3::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
}
void RGWListMultipart_ObjStore_S3::send_response()
@@ -1569,7 +1568,7 @@ void RGWListMultipart_ObjStore_S3::send_response()
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
if (ret == 0) {
dump_start(s);
@@ -1624,7 +1623,7 @@ void RGWListBucketMultiparts_ObjStore_S3::send_response()
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
dump_start(s);
if (ret < 0)
return;
@@ -1695,7 +1694,7 @@ void RGWDeleteMultiObj_ObjStore_S3::begin_response()
}
dump_start(s);
- end_header(s, "application/xml");
+ end_header(s, this, "application/xml");
s->formatter->open_object_section_in_ns("DeleteResult",
"http://s3.amazonaws.com/doc/2006-03-01/");
diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc
index b4f830830f9..651c4635d37 100644
--- a/src/rgw/rgw_rest_swift.cc
+++ b/src/rgw/rgw_rest_swift.cc
@@ -52,7 +52,7 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_begin(bool has_buckets)
set_req_state_err(s, ret);
}
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
if (!ret) {
dump_start(s);
@@ -211,7 +211,7 @@ next:
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
if (ret < 0) {
return;
}
@@ -266,7 +266,7 @@ void RGWStatAccount_ObjStore_SWIFT::send_response()
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
dump_start(s);
}
@@ -280,7 +280,7 @@ void RGWStatBucket_ObjStore_SWIFT::send_response()
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
dump_start(s);
}
@@ -301,7 +301,7 @@ void RGWCreateBucket_ObjStore_SWIFT::send_response()
ret = STATUS_ACCEPTED;
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -313,7 +313,7 @@ void RGWDeleteBucket_ObjStore_SWIFT::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -361,7 +361,7 @@ void RGWPutObj_ObjStore_SWIFT::send_response()
dump_etag(s, etag.c_str());
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -421,7 +421,7 @@ void RGWPutMetadata_ObjStore_SWIFT::send_response()
ret = STATUS_ACCEPTED;
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -433,7 +433,7 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response()
set_req_state_err(s, r);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
rgw_flush_formatter_and_reset(s, s->formatter);
}
@@ -484,7 +484,7 @@ void RGWCopyObj_ObjStore_SWIFT::send_partial_response(off_t ofs)
ret = STATUS_CREATED;
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
/* Send progress information. Note that this diverge from the original swift
* spec. We do this in order to keep connection alive.
@@ -506,7 +506,7 @@ void RGWCopyObj_ObjStore_SWIFT::send_response()
ret = STATUS_CREATED;
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, this);
} else {
s->formatter->close_section();
rgw_flush_formatter(s, s->formatter);
@@ -570,7 +570,7 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl, off_t bl_ofs, o
if (!content_type)
content_type = "binary/octet-stream";
- end_header(s, content_type);
+ end_header(s, this, content_type);
sent_header = true;
@@ -600,12 +600,12 @@ void RGWOptionsCORS_ObjStore_SWIFT::send_response()
} else {
set_req_state_err(s, ret);
dump_errno(s);
- end_header(s);
+ end_header(s, NULL);
return;
}
dump_errno(s);
dump_access_control(s, origin, req_meth, hdrs.c_str(), exp_hdrs.c_str(), max_age);
- end_header(s);
+ end_header(s, NULL);
}
RGWOp *RGWHandler_ObjStore_Service_SWIFT::op_get()