From b640ded886b7ac1996f9adbe150a6f5af48d67fc Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Mon, 2 Nov 2015 19:43:36 -0500 Subject: [PATCH] polymorphic error codes. make set_req_state_err a method of req_state get rid of params.perr; it's never used rgw - polymorphic error object. polymorphic error object: this way sts, which has additional error fields, and its own xml format for how errors should be produced, can overload the base rgw_err class. STL fixup: use real mappings for error mappings, not a linear search. insubstantiate error mappings exactly once in src/rgw/rgw_common.cc, instead of multiple copies from every source file that includes src/rgw/rgw_http_errors.h. remove dump_errno(s, err) - it was never used, and the code looked bogus. move rgw_http_error_to_errno from header to rgw_rest_client.cc, the only place it's used. move rgw_http_status_code and http_codes to rgw_rest.cc, the only place it's used. base class (rgw_err) implements s3 errors; swift & sts errors use the base class and overlay their own additional error codes to the ones recognized by the base class. For a while, I was trying to just have a "generic" abort_early() that used dump_more. Now, I have an op aware form that works the old way. I would like the http routines to known less about "op" structures, which is why I'm making this distinction. Splitting up generic and s3 flavors of some things: rgw_rest_init() - split into s3 and generic forms. end_header: s3 vs generic forms: generic form uses dump_more. abort_early: s3 vs generic forms: generic form uses dump_more, error_content. And fixing some mistakes from the merge: Fixup: should not have deleted dump_errno() local storage forms. Fixup:RGWRESTFlusher - take a dump_more to make it generic. Fixup: need RGWRESTOp::send_response() Move swift_err up; use it in bulkdelete_respond I Think I don't need s->prot_flags when using swift_err. Signed-off-by: Marcus Watts --- src/rgw/librgw.cc | 6 +- src/rgw/rgw_common.cc | 143 ++++++++++++++++++++-- src/rgw/rgw_common.h | 19 ++- src/rgw/rgw_cr_rados.cc | 1 - src/rgw/rgw_http_errors.h | 139 +-------------------- src/rgw/rgw_log.cc | 14 +-- src/rgw/rgw_op.cc | 15 ++- src/rgw/rgw_op.h | 3 + src/rgw/rgw_process.cc | 5 +- src/rgw/rgw_rados.cc | 14 +-- src/rgw/rgw_rados.h | 12 +- src/rgw/rgw_rest.cc | 208 +++++++++++++++++--------------- src/rgw/rgw_rest.h | 20 ++- src/rgw/rgw_rest_config.cc | 2 +- src/rgw/rgw_rest_log.cc | 21 ++-- src/rgw/rgw_rest_metadata.cc | 2 +- src/rgw/rgw_rest_opstate.cc | 2 +- src/rgw/rgw_rest_realm.cc | 10 +- src/rgw/rgw_rest_replica_log.cc | 4 +- src/rgw/rgw_rest_s3.cc | 101 ++++++++-------- src/rgw/rgw_rest_s3.h | 7 +- src/rgw/rgw_rest_swift.cc | 117 ++++++++++-------- src/rgw/rgw_rest_swift.h | 1 + src/rgw/rgw_swift_auth.cc | 2 +- src/rgw/rgw_tools.cc | 2 - 25 files changed, 455 insertions(+), 415 deletions(-) diff --git a/src/rgw/librgw.cc b/src/rgw/librgw.cc index f7bb502fa00..befceea3858 100644 --- a/src/rgw/librgw.cc +++ b/src/rgw/librgw.cc @@ -312,7 +312,7 @@ namespace rgw { (op ? op->name() : "unknown"), olog); } - int http_ret = s->err.http_ret; + int http_ret = s->err->http_ret; req->log_format(s, "http status=%d", http_ret); @@ -321,7 +321,7 @@ namespace rgw { << http_ret << " ======" << dendl; - return (ret < 0 ? ret : s->err.ret); + return (ret < 0 ? ret : s->err->ret); } /* process_request */ int RGWLibProcess::start_request(RGWLibContinuedReq* req) @@ -414,7 +414,7 @@ namespace rgw { req->exec_start(); done: - return (ret < 0 ? ret : s->err.ret); + return (ret < 0 ? ret : s->err->ret); } int RGWLibProcess::finish_request(RGWLibContinuedReq* req) diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index fbff872ee21..71e42487802 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -15,6 +15,7 @@ #include "rgw_acl.h" #include "rgw_string.h" #include "rgw_rados.h" +#include "rgw_http_errors.h" #include "common/ceph_crypto.h" #include "common/armor.h" @@ -41,6 +42,75 @@ PerfCounters *perfcounter = NULL; const uint32_t RGWBucketInfo::NUM_SHARDS_BLIND_BUCKET(UINT32_MAX); +rgw_http_errors rgw_http_s3_errors({ + { 0, {200, "" }}, + { STATUS_CREATED, {201, "Created" }}, + { STATUS_ACCEPTED, {202, "Accepted" }}, + { STATUS_NO_CONTENT, {204, "NoContent" }}, + { STATUS_PARTIAL_CONTENT, {206, "" }}, + { ERR_PERMANENT_REDIRECT, {301, "PermanentRedirect" }}, + { ERR_WEBSITE_REDIRECT, {301, "WebsiteRedirect" }}, + { STATUS_REDIRECT, {303, "" }}, + { ERR_NOT_MODIFIED, {304, "NotModified" }}, + { EINVAL, {400, "InvalidArgument" }}, + { ERR_INVALID_REQUEST, {400, "InvalidRequest" }}, + { ERR_INVALID_DIGEST, {400, "InvalidDigest" }}, + { ERR_BAD_DIGEST, {400, "BadDigest" }}, + { ERR_INVALID_BUCKET_NAME, {400, "InvalidBucketName" }}, + { ERR_INVALID_OBJECT_NAME, {400, "InvalidObjectName" }}, + { ERR_UNRESOLVABLE_EMAIL, {400, "UnresolvableGrantByEmailAddress" }}, + { ERR_INVALID_PART, {400, "InvalidPart" }}, + { ERR_INVALID_PART_ORDER, {400, "InvalidPartOrder" }}, + { ERR_REQUEST_TIMEOUT, {400, "RequestTimeout" }}, + { ERR_TOO_LARGE, {400, "EntityTooLarge" }}, + { ERR_TOO_SMALL, {400, "EntityTooSmall" }}, + { ERR_TOO_MANY_BUCKETS, {400, "TooManyBuckets" }}, + { ERR_MALFORMED_XML, {400, "MalformedXML" }}, + { ERR_AMZ_CONTENT_SHA256_MISMATCH, {400, "XAmzContentSHA256Mismatch" }}, + { ERR_LENGTH_REQUIRED, {411, "MissingContentLength" }}, + { EACCES, {403, "AccessDenied" }}, + { EPERM, {403, "AccessDenied" }}, + { ERR_SIGNATURE_NO_MATCH, {403, "SignatureDoesNotMatch" }}, + { ERR_INVALID_ACCESS_KEY, {403, "InvalidAccessKeyId" }}, + { ERR_USER_SUSPENDED, {403, "UserSuspended" }}, + { ERR_REQUEST_TIME_SKEWED, {403, "RequestTimeTooSkewed" }}, + { ERR_QUOTA_EXCEEDED, {403, "QuotaExceeded" }}, + { ENOENT, {404, "NoSuchKey" }}, + { ERR_NO_SUCH_BUCKET, {404, "NoSuchBucket" }}, + { ERR_NO_SUCH_WEBSITE_CONFIGURATION, {404, "NoSuchWebsiteConfiguration" }}, + { ERR_NO_SUCH_UPLOAD, {404, "NoSuchUpload" }}, + { ERR_NOT_FOUND, {404, "Not Found"}}, + { ERR_NO_SUCH_LC, {404, "NoSuchLifecycleConfiguration"}}, + { ERR_METHOD_NOT_ALLOWED, {405, "MethodNotAllowed" }}, + { ETIMEDOUT, {408, "RequestTimeout" }}, + { EEXIST, {409, "BucketAlreadyExists" }}, + { ERR_USER_EXIST, {409, "UserAlreadyExists" }}, + { ERR_EMAIL_EXIST, {409, "EmailExists" }}, + { ERR_KEY_EXIST, {409, "KeyExists"}}, + { ERR_INVALID_SECRET_KEY, {400, "InvalidSecretKey"}}, + { ERR_INVALID_KEY_TYPE, {400, "InvalidKeyType"}}, + { ERR_INVALID_CAP, {400, "InvalidCapability"}}, + { ERR_INVALID_TENANT_NAME, {400, "InvalidTenantName" }}, + { ENOTEMPTY, {409, "BucketNotEmpty" }}, + { ERR_PRECONDITION_FAILED, {412, "PreconditionFailed" }}, + { ERANGE, {416, "InvalidRange" }}, + { ERR_UNPROCESSABLE_ENTITY, {422, "UnprocessableEntity" }}, + { ERR_LOCKED, {423, "Locked" }}, + { ERR_INTERNAL_ERROR, {500, "InternalError" }}, + { ERR_NOT_IMPLEMENTED, {501, "NotImplemented" }}, + { ERR_SERVICE_UNAVAILABLE, {503, "ServiceUnavailable"}}, +}); + +rgw_http_errors rgw_http_swift_errors({ + { EACCES, {403, "AccessDenied" }}, + { EPERM, {401, "AccessDenied" }}, + { ERR_USER_SUSPENDED, {401, "UserSuspended" }}, + { ERR_INVALID_UTF8, {412, "Invalid UTF8" }}, + { ERR_BAD_URL, {412, "Bad URL" }}, + { ERR_NOT_SLO_MANIFEST, {400, "Not an SLO manifest" }}, + { ERR_QUOTA_EXCEEDED, {413, "QuotaExceeded" }}, +}); + int rgw_perf_start(CephContext *cct) { PerfCountersBuilder plb(cct, cct->_conf->name.to_str(), l_rgw_first, l_rgw_last); @@ -79,17 +149,11 @@ void rgw_perf_stop(CephContext *cct) using namespace ceph::crypto; rgw_err:: -rgw_err() +rgw_err(req_state *s) : s(*s) { clear(); } -rgw_err:: -rgw_err(int http, const std::string& s3) - : http_ret(http), ret(0), s3_code(s3) -{ -} - void rgw_err:: clear() { @@ -184,7 +248,7 @@ void req_info::rebuild_from(req_info& src) req_state::req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u) - : cct(_cct), cio(NULL), op(OP_UNKNOWN), user(u), has_acl_header(false), + : cct(_cct), cio(NULL), op(OP_UNKNOWN), err(0), user(u), has_acl_header(false), info(_cct, e) { enable_ops_log = e->conf.enable_ops_log; @@ -220,10 +284,42 @@ req_state::req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u) req_state::~req_state() { delete formatter; + delete err; delete bucket_acl; delete object_acl; } +void set_req_state_err(struct rgw_err& err, /* out */ + int err_no, /* in */ + const int prot_flags) /* in */ +{ + if (err_no < 0) + err_no = -err_no; + + err.ret = -err_no; + err.is_website_redirect |= (prot_flags & RGW_REST_WEBSITE) + && err_no == ERR_WEBSITE_REDIRECT && err.is_clear(); + if (err.set_rgw_err(err_no)) + return; + dout(0) << "WARNING: set_req_state_err err_no=" << err_no + << " resorting to 500" << dendl; + + err.http_ret = 500; + err.s3_code = "UnknownError"; +} + +void req_state::set_req_state_err(int err_no) +{ + if (!err) err = new rgw_err(this); + ::set_req_state_err(*err, err_no, prot_flags); +} + +void req_state::set_req_state_err(int err_no, const string &err_msg) +{ + set_req_state_err(err_no); + err->message = err_msg; +} + struct str_len { const char *str; int len; @@ -299,6 +395,37 @@ std::ostream& operator<<(std::ostream& oss, const rgw_err &err) return oss; } +void rgw_err::dump() const +{ + if (s.format != RGW_FORMAT_HTML) + s.formatter->open_object_section("Error"); + if (!s3_code.empty()) + s.formatter->dump_string("Code", s3_code); + if (!message.empty()) + s.formatter->dump_string("Message", message); + if (!s.bucket_name.empty()) // TODO: connect to expose_bucket + s.formatter->dump_string("BucketName", s.bucket_name); + if (!s.trans_id.empty()) // TODO: connect to expose_bucket or another toggle + s.formatter->dump_string("RequestId", s.trans_id); + s.formatter->dump_string("HostId", s.host_id); + if (s.format != RGW_FORMAT_HTML) + s.formatter->close_section(); +} + +bool rgw_err::set_rgw_err(int err_no) +{ + rgw_http_errors::const_iterator r; + + r = rgw_http_s3_errors.find(err_no); + if (r != rgw_http_s3_errors.end()) { + if (!is_website_redirect) + http_ret = r->second.first; + s3_code = r->second.second; + return true; + } + return false; +} + string rgw_string_unquote(const string& s) { if (s[0] != '"' || s.size() < 2) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 5ad7637b44c..37e25a0840c 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -202,6 +202,8 @@ using ceph::crypto::MD5; #define UINT32_MAX (0xffffffffu) #endif +struct req_state; + typedef void *RGWAccessHandle; @@ -262,13 +264,17 @@ enum RGWObjCategory { /** Store error returns for output at a different point in the program */ struct rgw_err { - rgw_err(); - rgw_err(int http, const std::string &s3); + rgw_err(req_state *s); + virtual ~rgw_err() { }; void clear(); bool is_clear() const; bool is_err() const; friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err); + virtual void dump() const; + virtual bool set_rgw_err(int); + req_state &s; + bool is_website_redirect; int http_ret; int ret; std::string s3_code; @@ -1338,8 +1344,6 @@ struct RGWStorageStats void dump(Formatter *f) const; }; -struct req_state; - class RGWEnv; /* Namespaced forward declarations. */ @@ -1701,7 +1705,7 @@ struct req_state { const char *length; int64_t content_length; map generic_attrs; - struct rgw_err err; + rgw_err *err; bool expect_cont; bool header_ended; uint64_t obj_size; @@ -1805,7 +1809,12 @@ struct req_state { req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u); ~req_state(); + + void set_req_state_err(int err_no); + void set_req_state_err(int err_no, const string &err_msg); + bool is_err() const { return err && err->is_err(); } }; +void set_req_state_err(struct rgw_err&, int, const int); /** Store basic data on bucket */ struct RGWBucketEnt { diff --git a/src/rgw/rgw_cr_rados.cc b/src/rgw/rgw_cr_rados.cc index 353deaa67ec..0e0be84c82c 100644 --- a/src/rgw/rgw_cr_rados.cc +++ b/src/rgw/rgw_cr_rados.cc @@ -541,7 +541,6 @@ int RGWAsyncFetchRemoteObj::_send_request() &key.instance, /* string *version_id, */ NULL, /* string *ptag, */ NULL, /* string *petag, */ - NULL, /* struct rgw_err *err, */ NULL, /* void (*progress_cb)(off_t, void *), */ NULL); /* void *progress_data*); */ diff --git a/src/rgw/rgw_http_errors.h b/src/rgw/rgw_http_errors.h index a0423bb48fd..e2aec310c88 100644 --- a/src/rgw/rgw_http_errors.h +++ b/src/rgw/rgw_http_errors.h @@ -6,144 +6,11 @@ #include "rgw_common.h" -struct rgw_http_errors { - int err_no; - int http_ret; - const char *s3_code; -}; +typedef const std::map> rgw_http_errors; -const static struct rgw_http_errors RGW_HTTP_ERRORS[] = { - { 0, 200, "" }, - { STATUS_CREATED, 201, "Created" }, - { STATUS_ACCEPTED, 202, "Accepted" }, - { STATUS_NO_CONTENT, 204, "NoContent" }, - { STATUS_PARTIAL_CONTENT, 206, "" }, - { ERR_PERMANENT_REDIRECT, 301, "PermanentRedirect" }, - { ERR_WEBSITE_REDIRECT, 301, "WebsiteRedirect" }, - { STATUS_REDIRECT, 303, "" }, - { ERR_NOT_MODIFIED, 304, "NotModified" }, - { EINVAL, 400, "InvalidArgument" }, - { ERR_INVALID_REQUEST, 400, "InvalidRequest" }, - { ERR_INVALID_DIGEST, 400, "InvalidDigest" }, - { ERR_BAD_DIGEST, 400, "BadDigest" }, - { ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" }, - { ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" }, - { ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" }, - { ERR_INVALID_PART, 400, "InvalidPart" }, - { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" }, - { ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" }, - { ERR_TOO_LARGE, 400, "EntityTooLarge" }, - { ERR_TOO_SMALL, 400, "EntityTooSmall" }, - { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" }, - { ERR_MALFORMED_XML, 400, "MalformedXML" }, - { ERR_AMZ_CONTENT_SHA256_MISMATCH, 400, "XAmzContentSHA256Mismatch" }, - { ERR_MALFORMED_DOC, 400, "MalformedPolicyDocument" }, - { ERR_LENGTH_REQUIRED, 411, "MissingContentLength" }, - { EACCES, 403, "AccessDenied" }, - { EPERM, 403, "AccessDenied" }, - { ERR_SIGNATURE_NO_MATCH, 403, "SignatureDoesNotMatch" }, - { ERR_INVALID_ACCESS_KEY, 403, "InvalidAccessKeyId" }, - { ERR_USER_SUSPENDED, 403, "UserSuspended" }, - { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" }, - { ERR_QUOTA_EXCEEDED, 403, "QuotaExceeded" }, - { ENOENT, 404, "NoSuchKey" }, - { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" }, - { ERR_NO_SUCH_WEBSITE_CONFIGURATION, 404, "NoSuchWebsiteConfiguration" }, - { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" }, - { ERR_NOT_FOUND, 404, "Not Found"}, - { ERR_NO_SUCH_LC, 404, "NoSuchLifecycleConfiguration"}, - { ERR_NO_ROLE_FOUND, 404, "NoSuchEntity"}, - { ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" }, - { ETIMEDOUT, 408, "RequestTimeout" }, - { EEXIST, 409, "BucketAlreadyExists" }, - { ERR_USER_EXIST, 409, "UserAlreadyExists" }, - { ERR_EMAIL_EXIST, 409, "EmailExists" }, - { ERR_KEY_EXIST, 409, "KeyExists"}, - { ERR_ROLE_EXISTS, 409, "EntityAlreadyExists"}, - { ERR_DELETE_CONFLICT, 409, "DeleteConflict"}, - { ERR_INVALID_SECRET_KEY, 400, "InvalidSecretKey"}, - { ERR_INVALID_KEY_TYPE, 400, "InvalidKeyType"}, - { ERR_INVALID_CAP, 400, "InvalidCapability"}, - { ERR_INVALID_TENANT_NAME, 400, "InvalidTenantName" }, - { ENOTEMPTY, 409, "BucketNotEmpty" }, - { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" }, - { ERANGE, 416, "InvalidRange" }, - { ERR_UNPROCESSABLE_ENTITY, 422, "UnprocessableEntity" }, - { ERR_LOCKED, 423, "Locked" }, - { ERR_INTERNAL_ERROR, 500, "InternalError" }, - { ERR_NOT_IMPLEMENTED, 501, "NotImplemented" }, - { ERR_SERVICE_UNAVAILABLE, 503, "ServiceUnavailable"} -}; - -const static struct rgw_http_errors RGW_HTTP_SWIFT_ERRORS[] = { - { EACCES, 403, "AccessDenied" }, - { EPERM, 401, "AccessDenied" }, - { ERR_USER_SUSPENDED, 401, "UserSuspended" }, - { ERR_INVALID_UTF8, 412, "Invalid UTF8" }, - { ERR_BAD_URL, 412, "Bad URL" }, - { ERR_NOT_SLO_MANIFEST, 400, "Not an SLO manifest" }, - { ERR_QUOTA_EXCEEDED, 413, "QuotaExceeded" } -}; - -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" }, - { 301, "Moved Permanently" }, - { 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" }, - { 501, "Not Implemented" }, - { 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) -{ - for (int i = 0; i < len; ++i, ++errs) { - if (err_no == errs->err_no) - return errs; - } - return NULL; -} +extern rgw_http_errors rgw_http_s3_errors; +extern rgw_http_errors rgw_http_swift_errors; static inline int rgw_http_error_to_errno(int http_err) { diff --git a/src/rgw/rgw_log.cc b/src/rgw/rgw_log.cc index 153ddb060d7..6fc90372b6e 100644 --- a/src/rgw/rgw_log.cc +++ b/src/rgw/rgw_log.cc @@ -203,8 +203,8 @@ static void log_usage(struct req_state *s, const string& op_name) user = s->user->user_id; } - bool error = s->err.is_err(); - if (error && s->err.http_ret == 404) { + bool error = s->err->is_err(); + if (error && s->err->http_ret == 404) { bucket_name = "-"; /* bucket not found, use the invalid '-' as bucket name */ } @@ -218,7 +218,7 @@ static void log_usage(struct req_state *s, const string& op_name) rgw_usage_data data(bytes_sent, bytes_received); data.ops = 1; - if (!error) + if (!s->is_err()) data.successful_ops = 1; entry.add(op_name, data); @@ -316,7 +316,7 @@ int rgw_log_op(RGWRados *store, RGWREST* const rest, struct req_state *s, ldout(s->cct, 5) << "nothing to log for operation" << dendl; return -EINVAL; } - if (s->err.ret == -ERR_NO_SUCH_BUCKET) { + if (s->err->ret == -ERR_NO_SUCH_BUCKET) { if (!s->cct->_conf->rgw_log_nonexistent_bucket) { ldout(s->cct, 5) << "bucket " << s->bucket << " doesn't exist, not logging" << dendl; return 0; @@ -374,14 +374,14 @@ int rgw_log_op(RGWRados *store, RGWREST* const rest, struct req_state *s, entry.total_time = ceph_clock_now() - s->time; entry.bytes_sent = bytes_sent; entry.bytes_received = bytes_received; - if (s->err.http_ret) { + if (s->err->http_ret) { char buf[16]; - snprintf(buf, sizeof(buf), "%d", s->err.http_ret); + snprintf(buf, sizeof(buf), "%d", s->err->http_ret); entry.http_status = buf; } else entry.http_status = "200"; // default - entry.error_code = s->err.s3_code; + entry.error_code = s->err->s3_code; entry.bucket_id = bucket_id; bufferlist bl; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 844b1dad5b0..7278283ddb1 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -9,6 +9,8 @@ #include #include +#include +#include #include "common/Clock.h" #include "common/armor.h" @@ -241,7 +243,6 @@ static int get_obj_attrs(RGWRados *store, struct req_state *s, rgw_obj& obj, map RGWRados::Object::Read read_op(&op_target); read_op.params.attrs = &attrs; - read_op.params.perr = &s->err; return read_op.prepare(); } @@ -792,6 +793,15 @@ bool RGWOp::generate_cors_headers(string& origin, string& method, string& header return true; } +/** + * Return a callable that can invoke dump_access_control(). + */ + +boost::function RGWOp::dump_access_control_f() +{ + return boost::bind(dump_access_control, s, this); +} + int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket, const rgw_bucket_dir_entry& ent, RGWAccessControlPolicy * const bucket_policy, @@ -825,7 +835,6 @@ int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket, read_op.conds.if_match = ent.meta.etag.c_str(); read_op.params.attrs = &attrs; read_op.params.obj_size = &obj_size; - read_op.params.perr = &s->err; op_ret = read_op.prepare(); if (op_ret < 0) @@ -1385,7 +1394,6 @@ void RGWGetObj::execute() read_op.params.attrs = &attrs; read_op.params.lastmod = &lastmod; read_op.params.obj_size = &s->obj_size; - read_op.params.perr = &s->err; op_ret = read_op.prepare(); if (op_ret < 0) @@ -4097,7 +4105,6 @@ void RGWCopyObj::execute() (version_id.empty() ? NULL : &version_id), &s->req_id, /* use req_id as tag */ &etag, - &s->err, copy_obj_progress_cb, (void *)this ); } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 1fcf4c30120..827ae1c6c1a 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -22,6 +22,7 @@ #include #include +#include #include "common/armor.h" #include "common/mime.h" @@ -172,6 +173,8 @@ public: virtual uint32_t op_mask() { return 0; } virtual int error_handler(int err_no, string *error_content); + + boost::function dump_access_control_f(); }; class RGWGetObj : public RGWOp { diff --git a/src/rgw/rgw_process.cc b/src/rgw/rgw_process.cc index 6fbf2fdb594..333ee1ef3fd 100644 --- a/src/rgw/rgw_process.cc +++ b/src/rgw/rgw_process.cc @@ -151,6 +151,7 @@ int process_request(RGWRados* const store, auth_registry, frontend_prefix, client_io, &mgr, &init_error); + if (!s->err) s->err = new rgw_err(s); if (init_error != 0) { abort_early(s, NULL, init_error, NULL); goto done; @@ -216,7 +217,7 @@ done: rgw_log_op(store, rest, s, (op ? op->name() : "unknown"), olog); } - int http_ret = s->err.http_ret; + int http_ret = s->err->http_ret; int op_ret = 0; if (op) { op_ret = op->get_ret(); @@ -235,5 +236,5 @@ done: << " ======" << dendl; - return (ret < 0 ? ret : s->err.ret); + return (ret < 0 ? ret : s->err->ret); } /* process_request */ diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 562b067beb2..f3fb6dc2ea3 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -6271,7 +6271,6 @@ int RGWRados::swift_versioning_copy(RGWObjectCtx& obj_ctx, NULL, /* string *version_id */ NULL, /* string *ptag */ NULL, /* string *petag */ - NULL, /* struct rgw_err *err */ NULL, /* void (*progress_cb)(off_t, void *) */ NULL); /* void *progress_data */ if (r == -ECANCELED || r == -ENOENT) { @@ -6361,7 +6360,6 @@ int RGWRados::swift_versioning_restore(RGWObjectCtx& obj_ctx, nullptr, /* string *version_id */ nullptr, /* string *ptag */ nullptr, /* string *petag */ - nullptr, /* struct rgw_err *err */ nullptr, /* void (*progress_cb)(off_t, void *) */ nullptr); /* void *progress_data */ if (ret == -ECANCELED || ret == -ENOENT) { @@ -7006,7 +7004,7 @@ int RGWRados::rewrite_obj(RGWBucketInfo& dest_bucket_info, rgw_obj& obj) } return copy_obj_data(rctx, dest_bucket_info, read_op, obj_size - 1, obj, obj, max_chunk_size, NULL, mtime, attrset, - RGW_OBJ_CATEGORY_MAIN, 0, real_time(), NULL, NULL, NULL, NULL); + RGW_OBJ_CATEGORY_MAIN, 0, real_time(), NULL, NULL, NULL); } struct obj_time_weight { @@ -7225,7 +7223,6 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx, string *version_id, string *ptag, ceph::buffer::list *petag, - struct rgw_err *err, void (*progress_cb)(off_t, void *), void *progress_data) { @@ -7523,7 +7520,6 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, string *version_id, string *ptag, ceph::buffer::list *petag, - struct rgw_err *err, void (*progress_cb)(off_t, void *), void *progress_data) { @@ -7553,7 +7549,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, dest_obj, src_obj, dest_bucket_info, src_bucket_info, src_mtime, mtime, mod_ptr, unmod_ptr, high_precision_time, if_match, if_nomatch, attrs_mod, copy_if_newer, attrs, category, - olh_epoch, delete_at, version_id, ptag, petag, err, progress_cb, progress_data); + olh_epoch, delete_at, version_id, ptag, petag, progress_cb, progress_data); } map src_attrs; @@ -7568,7 +7564,6 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, read_op.params.attrs = &src_attrs; read_op.params.lastmod = src_mtime; read_op.params.obj_size = &obj_size; - read_op.params.perr = err; ret = read_op.prepare(); if (ret < 0) { @@ -7648,7 +7643,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, if (copy_data) { /* refcounting tail wouldn't work here, just copy the data */ return copy_obj_data(obj_ctx, dest_bucket_info, read_op, obj_size - 1, dest_obj, src_obj, max_chunk_size, mtime, real_time(), attrs, category, olh_epoch, delete_at, - version_id, ptag, petag, err); + version_id, ptag, petag); } RGWObjManifest::obj_iterator miter = astate->manifest.obj_begin(); @@ -7784,8 +7779,7 @@ int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx, real_time delete_at, string *version_id, string *ptag, - ceph::buffer::list *petag, - struct rgw_err *err) + ceph::buffer::list *petag) { bufferlist first_chunk; RGWObjManifest manifest; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index cbb6610235e..e60ccbdf0be 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -2595,9 +2595,8 @@ public: ceph::real_time *lastmod; uint64_t *obj_size; map *attrs; - struct rgw_err *perr; - StatParams() : lastmod(NULL), obj_size(NULL), attrs(NULL), perr(NULL) {} + StatParams() : lastmod(NULL), obj_size(NULL), attrs(NULL) {} } stat_params; struct ReadParams { @@ -2708,9 +2707,8 @@ public: ceph::real_time *lastmod; uint64_t *obj_size; map *attrs; - struct rgw_err *perr; - Params() : lastmod(NULL), obj_size(NULL), attrs(NULL), perr(NULL) {} + Params() : lastmod(NULL), obj_size(NULL), attrs(NULL) {} } params; explicit Read(RGWRados::Object *_source) : source(_source) {} @@ -3023,7 +3021,6 @@ public: string *version_id, string *ptag, ceph::buffer::list *petag, - struct rgw_err *err, void (*progress_cb)(off_t, void *), void *progress_data); /** @@ -3038,7 +3035,6 @@ public: * parameter, source object attributes are not copied; * ATTRSMOD_MERGE - any conflicting meta keys on the source object's attributes * are overwritten by values contained in attrs parameter. - * err: stores any errors resulting from the get of the original object * Returns: 0 on success, -ERR# otherwise. */ int copy_obj(RGWObjectCtx& obj_ctx, @@ -3067,7 +3063,6 @@ public: string *version_id, string *ptag, ceph::buffer::list *petag, - struct rgw_err *err, void (*progress_cb)(off_t, void *), void *progress_data); @@ -3085,8 +3080,7 @@ public: ceph::real_time delete_at, string *version_id, string *ptag, - ceph::buffer::list *petag, - struct rgw_err *err); + ceph::buffer::list *petag); int check_bucket_empty(RGWBucketInfo& bucket_info); diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 040f972467c..6063212436f 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -1,6 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab + #include #include @@ -18,8 +19,7 @@ #include "rgw_rest_s3.h" #include "rgw_swift_auth.h" #include "rgw_cors_s3.h" -#include "rgw_http_errors.h" -#include "rgw_lib.h" +// #include "rgw_lib.h" // XXX mdw is this necessary? #include "rgw_client_io.h" #include "rgw_resolve.h" @@ -28,6 +28,53 @@ #define dout_subsys ceph_subsys_rgw +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" }, + { 301, "Moved Permanently" }, + { 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" }, + { 501, "Not Implemented" }, + { 0, NULL }, +}; struct rgw_http_attr { const char *rgw_attr; @@ -176,10 +223,8 @@ string camelcase_dash_http_attr(const string& orig) static set hostnames_set; static set hostnames_s3website_set; -void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group) +void rgw_rest_init(CephContext *cct) { - store->init_host_id(); - for (const auto& rgw2http : base_rgw_to_http_attrs) { rgw_to_http_attrs[rgw2http.rgw_attr] = rgw2http.http_attr; } @@ -209,6 +254,12 @@ void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group) } hostnames_set.insert(cct->_conf->rgw_dns_name); +} + +void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group) +{ + store->init_host_id(); + rgw_rest_init(cct); hostnames_set.insert(zone_group.hostnames.begin(), zone_group.hostnames.end()); hostnames_set.erase(""); // filter out empty hostnames ldout(cct, 20) << "RGW hostnames: " << hostnames_set << dendl; @@ -309,45 +360,6 @@ void rgw_flush_formatter(struct req_state *s, Formatter *formatter) } } -void set_req_state_err(struct rgw_err& err, /* out */ - int err_no, /* in */ - const int prot_flags) /* in */ -{ - const struct rgw_http_errors *r; - - if (err_no < 0) - err_no = -err_no; - err.ret = -err_no; - if (prot_flags & RGW_REST_SWIFT) { - r = search_err(err_no, RGW_HTTP_SWIFT_ERRORS, - ARRAY_LEN(RGW_HTTP_SWIFT_ERRORS)); - if (r) { - err.http_ret = r->http_ret; - err.s3_code = r->s3_code; - return; - } - } - - r = search_err(err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS)); - if (r) { - err.http_ret = r->http_ret; - err.s3_code = r->s3_code; - return; - } - dout(0) << "WARNING: set_req_state_err err_no=" << err_no - << " resorting to 500" << dendl; - - err.http_ret = 500; - err.s3_code = "UnknownError"; -} - -void set_req_state_err(struct req_state * const s, const int err_no) -{ - if (s) { - set_req_state_err(s->err, err_no, s->prot_flags); - } -} - void dump_errno(int http_ret, string& out) { stringstream ss; @@ -361,7 +373,7 @@ void dump_errno(const struct rgw_err &err, string& out) { void dump_errno(struct req_state *s) { - dump_status(s, s->err.http_ret, http_status_names[s->err.http_ret]); + dump_status(s, s->err->http_ret, http_status_names[s->err->http_ret]); } void dump_errno(struct req_state *s, int http_ret) @@ -650,22 +662,22 @@ void dump_trans_id(req_state *s) } } -void end_header(struct req_state* s, RGWOp* op, const char *content_type, - const int64_t proposed_content_length, bool force_content_type, - bool force_no_error) +void end_header(struct req_state* s, boost::function dump_more, + const char *content_type, const int64_t proposed_content_length, + bool force_content_type, bool force_no_error) { string ctype; dump_trans_id(s); - if ((!s->err.is_err()) && + if ((!s->is_err()) && (s->bucket_info.owner != s->user->user_id) && (s->bucket_info.requester_pays)) { dump_header(s, "x-amz-request-charged", "requester"); } - if (op) { - dump_access_control(s, op); + if (dump_more) { + dump_more(); } if (s->prot_flags & RGW_REST_SWIFT && !content_type) { @@ -675,7 +687,7 @@ void end_header(struct req_state* s, RGWOp* op, const char *content_type, /* do not send content type if content length is zero and the content type was not set by the user */ if (force_content_type || - (!content_type && s->formatter->get_len() != 0) || s->err.is_err()){ + (!content_type && s->formatter->get_len() != 0) || s->is_err()){ switch (s->format) { case RGW_FORMAT_XML: ctype = "application/xml"; @@ -694,24 +706,9 @@ void end_header(struct req_state* s, RGWOp* op, const char *content_type, ctype.append("; charset=utf-8"); content_type = ctype.c_str(); } - if (!force_no_error && s->err.is_err()) { + if (!force_no_error && s->is_err()) { dump_start(s); - if (s->format != RGW_FORMAT_HTML) { - s->formatter->open_object_section("Error"); - } - if (!s->err.s3_code.empty()) - s->formatter->dump_string("Code", s->err.s3_code); - if (!s->err.message.empty()) - s->formatter->dump_string("Message", s->err.message); - if (!s->bucket_name.empty()) // TODO: connect to expose_bucket - s->formatter->dump_string("BucketName", s->bucket_name); - if (!s->trans_id.empty()) // TODO: connect to expose_bucket or another toggle - s->formatter->dump_string("RequestId", s->trans_id); - s->formatter->dump_string("HostId", s->host_id); - if (s->format != RGW_FORMAT_HTML) { - s->formatter->close_section(); - } - s->formatter->output_footer(); + s->err->dump(); dump_content_length(s, s->formatter->get_len()); } else { if (proposed_content_length == CHUNKED_TRANSFER_ENCODING) { @@ -736,45 +733,38 @@ void end_header(struct req_state* s, RGWOp* op, const char *content_type, rgw_flush_formatter_and_reset(s, s->formatter); } -void abort_early(struct req_state *s, RGWOp *op, int err_no, - RGWHandler* handler) +void end_header(struct req_state* s, RGWOp* op, const char *content_type, + const int64_t proposed_content_length, bool force_content_type, + bool force_no_error) +{ + boost::function dump_more; + + if (op) dump_more = op->dump_access_control_f(); + end_header(s, dump_more, content_type, + proposed_content_length, force_content_type, force_no_error); +} + +void abort_early(struct req_state *s, boost::function dump_more, + string& error_content, int err_no) { - string error_content(""); if (!s->formatter) { s->formatter = new JSONFormatter; s->format = RGW_FORMAT_JSON; } - // op->error_handler is responsible for calling it's handler error_handler - if (op != NULL) { - int new_err_no; - new_err_no = op->error_handler(err_no, &error_content); - ldout(s->cct, 20) << "op->ERRORHANDLER: err_no=" << err_no - << " new_err_no=" << new_err_no << dendl; - err_no = new_err_no; - } else if (handler != NULL) { - int new_err_no; - new_err_no = handler->error_handler(err_no, &error_content); - ldout(s->cct, 20) << "handler->ERRORHANDLER: err_no=" << err_no - << " new_err_no=" << new_err_no << dendl; - err_no = new_err_no; - } - // If the error handler(s) above dealt with it completely, they should have // returned 0. If non-zero, we need to continue here. if (err_no) { // Watch out, we might have a custom error state already set! - if (s->err.http_ret && s->err.http_ret != 200) { - dump_errno(s); - } else { - set_req_state_err(s, err_no); - dump_errno(s); + if (!s->err->http_ret || s->err->http_ret == 200) { + s->set_req_state_err(err_no); } + dump_errno(s); dump_bucket_from_state(s); if (err_no == -ERR_PERMANENT_REDIRECT || err_no == -ERR_WEBSITE_REDIRECT) { string dest_uri; if (!s->redirect.empty()) { - dest_uri = s->redirect; + dest_uri = s->redirect; } else if (!s->zonegroup_endpoint.empty()) { dest_uri = s->zonegroup_endpoint; /* @@ -803,15 +793,39 @@ void abort_early(struct req_state *s, RGWOp *op, int err_no, * x-amz-error-message: The specified key does not exist. * x-amz-error-detail-Key: foo */ - end_header(s, op, NULL, error_content.size(), false, true); + end_header(s, dump_more, NULL, error_content.size(), false, true); RESTFUL_IO(s)->send_body(error_content.c_str(), error_content.size()); } else { - end_header(s, op); + end_header(s, dump_more); } } perfcounter->inc(l_rgw_failed_req); } +void abort_early(struct req_state *s, RGWOp* op, int err_no, + RGWHandler* handler) +{ + string error_content(""); + boost::function dump_more; + + // op->error_handler is responsible for calling it's handler error_handler + if (op != NULL) { + int new_err_no; + new_err_no = op->error_handler(err_no, &error_content); + ldout(s->cct, 20) << "op->ERRORHANDLER: err_no=" << err_no + << " new_err_no=" << new_err_no << dendl; + err_no = new_err_no; + } else if (handler != NULL) { + int new_err_no; + new_err_no = handler->error_handler(err_no, &error_content); + ldout(s->cct, 20) << "handler->ERRORHANDLER: err_no=" << err_no + << " new_err_no=" << new_err_no << dendl; + err_no = new_err_no; + } + if (op) dump_more = op->dump_access_control_f(); + abort_early(s, dump_more, error_content, err_no); +} + void dump_continue(struct req_state * const s) { try { @@ -1091,7 +1105,7 @@ int RESTArgs::get_bool(struct req_state *s, const string& name, bool def_val, bo void RGWRESTFlusher::do_start(int ret) { - set_req_state_err(s, ret); /* no going back from here */ + s->set_req_state_err(ret); /* no going back from here */ dump_errno(s); dump_start(s); end_header(s, op); @@ -1785,7 +1799,7 @@ int RGWDeleteMultiObj_ObjStore::get_params() void RGWRESTOp::send_response() { if (!flusher.did_start()) { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s, this); } diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index 4b092935e46..0a9f0b9db7a 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -20,6 +20,7 @@ extern std::map rgw_to_http_attrs; extern string camelcase_dash_http_attr(const string& orig); extern string lowercase_dash_http_attr(const string& orig); +extern void rgw_rest_init(CephContext *cct); extern void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group); extern void rgw_flush_formatter_and_reset(struct req_state *s, @@ -130,16 +131,16 @@ public: class RGWRESTFlusher : public RGWFormatterFlusher { struct req_state *s; - RGWOp *op; + boost::function op; protected: void do_flush() override; void do_start(int ret) override; public: - RGWRESTFlusher(struct req_state *_s, RGWOp *_op) : + RGWRESTFlusher(struct req_state *_s, boost::function _op) : RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {} RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {} - void init(struct req_state *_s, RGWOp *_op) { + void init(struct req_state *_s, boost::function _op) { s = _s; op = _op; set_formatter(s->formatter); @@ -462,7 +463,7 @@ public: void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) override { RGWOp::init(store, s, dialect_handler); - flusher.init(s, this); + flusher.init(s, dump_access_control_f()); } void send_response() override; virtual int check_caps(RGWUserCaps& caps) @@ -626,8 +627,6 @@ public: static constexpr int64_t NO_CONTENT_LENGTH = -1; static constexpr int64_t CHUNKED_TRANSFER_ENCODING = -2; -extern void set_req_state_err(struct rgw_err &err, int err_no, int prot_flags); -extern void set_req_state_err(struct req_state *s, int err_no); extern void dump_errno(int http_ret, string& out); extern void dump_errno(const struct rgw_err &err, string& out); extern void dump_errno(struct req_state *s); @@ -639,6 +638,13 @@ extern void end_header(struct req_state *s, NO_CONTENT_LENGTH, bool force_content_type = false, bool force_no_error = false); +extern void end_header(struct req_state *s, + boost::function dump_more, + const char *content_type = nullptr, + const int64_t proposed_content_length = + NO_CONTENT_LENGTH, + bool force_content_type = false, + bool force_no_error = false); 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, const rgw_user& id, string& name, @@ -702,6 +708,8 @@ extern void dump_time_header(struct req_state *s, const char *name, real_time t) extern void dump_last_modified(struct req_state *s, real_time t); extern void abort_early(struct req_state* s, RGWOp* op, int err, RGWHandler* handler); +extern void abort_early(struct req_state* s, boost::function dump_more, + string& error_content, 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); diff --git a/src/rgw/rgw_rest_config.cc b/src/rgw/rgw_rest_config.cc index 3770cec15de..4a4cb3901f7 100644 --- a/src/rgw/rgw_rest_config.cc +++ b/src/rgw/rgw_rest_config.cc @@ -33,7 +33,7 @@ void RGWOp_ZoneGroupMap_Get::execute() { } void RGWOp_ZoneGroupMap_Get::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); diff --git a/src/rgw/rgw_rest_log.cc b/src/rgw/rgw_rest_log.cc index 5ba563f4c40..2e933c2ddc0 100644 --- a/src/rgw/rgw_rest_log.cc +++ b/src/rgw/rgw_rest_log.cc @@ -20,6 +20,7 @@ #include "rgw_client_io.h" #include "rgw_sync.h" #include "rgw_data_sync.h" +#include "rgw_common.h" #include "common/errno.h" #include "include/assert.h" @@ -108,7 +109,7 @@ void RGWOp_MDLog_List::execute() { } void RGWOp_MDLog_List::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -139,7 +140,7 @@ void RGWOp_MDLog_Info::execute() { } void RGWOp_MDLog_Info::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -181,7 +182,7 @@ void RGWOp_MDLog_ShardInfo::execute() { } void RGWOp_MDLog_ShardInfo::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -434,7 +435,7 @@ void RGWOp_BILog_List::send_response() { if (sent_header) return; - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -504,7 +505,7 @@ void RGWOp_BILog_Info::execute() { } void RGWOp_BILog_Info::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -620,7 +621,7 @@ void RGWOp_DATALog_List::execute() { } void RGWOp_DATALog_List::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -655,7 +656,7 @@ void RGWOp_DATALog_Info::execute() { } void RGWOp_DATALog_Info::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -680,7 +681,7 @@ void RGWOp_DATALog_ShardInfo::execute() { } void RGWOp_DATALog_ShardInfo::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -868,7 +869,7 @@ void RGWOp_MDLog_Status::execute() void RGWOp_MDLog_Status::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -907,7 +908,7 @@ void RGWOp_DATALog_Status::execute() void RGWOp_DATALog_Status::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); diff --git a/src/rgw/rgw_rest_metadata.cc b/src/rgw/rgw_rest_metadata.cc index 272e304f17e..792f49ab64d 100644 --- a/src/rgw/rgw_rest_metadata.cc +++ b/src/rgw/rgw_rest_metadata.cc @@ -201,7 +201,7 @@ void RGWOp_Metadata_Put::send_response() { int http_return_code = http_ret; if ((http_ret == STATUS_NO_APPLY) || (http_ret == STATUS_APPLIED)) http_return_code = STATUS_NO_CONTENT; - set_req_state_err(s, http_return_code); + s->set_req_state_err(http_return_code); dump_errno(s); stringstream ver_stream; ver_stream << "ver:" << ondisk_version.ver diff --git a/src/rgw/rgw_rest_opstate.cc b/src/rgw/rgw_rest_opstate.cc index af9c024e13f..af079803333 100644 --- a/src/rgw/rgw_rest_opstate.cc +++ b/src/rgw/rgw_rest_opstate.cc @@ -75,7 +75,7 @@ void RGWOp_Opstate_List::send_response() { if (sent_header) return; - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); diff --git a/src/rgw/rgw_rest_realm.cc b/src/rgw/rgw_rest_realm.cc index d5ef848b805..3dde7803cbd 100644 --- a/src/rgw/rgw_rest_realm.cc +++ b/src/rgw/rgw_rest_realm.cc @@ -26,15 +26,13 @@ class RGWOp_Period_Base : public RGWRESTOp { // reply with the period object on success void RGWOp_Period_Base::send_response() { - s->err.message = error_stream.str(); - - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret, error_stream.str()); dump_errno(s); if (http_ret < 0) { - if (!s->err.message.empty()) { + if (!s->err->message.empty()) { ldout(s->cct, 4) << "Request failed with " << http_ret - << ": " << s->err.message << dendl; + << ": " << s->err->message << dendl; } end_header(s); return; @@ -265,7 +263,7 @@ void RGWOp_Realm_Get::execute() void RGWOp_Realm_Get::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); if (http_ret < 0) { diff --git a/src/rgw/rgw_rest_replica_log.cc b/src/rgw/rgw_rest_replica_log.cc index 919815f5723..dd40c34286a 100644 --- a/src/rgw/rgw_rest_replica_log.cc +++ b/src/rgw/rgw_rest_replica_log.cc @@ -108,7 +108,7 @@ void RGWOp_OBJLog_GetBounds::execute() { } void RGWOp_OBJLog_GetBounds::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); @@ -230,7 +230,7 @@ void RGWOp_BILog_GetBounds::execute() { } void RGWOp_BILog_GetBounds::send_response() { - set_req_state_err(s, http_ret); + s->set_req_state_err(http_ret); dump_errno(s); end_header(s); diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index b41441160f5..9c7ac61b0c9 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -65,14 +65,13 @@ void dump_bucket(struct req_state *s, RGWBucketEnt& obj) s->formatter->close_section(); } -void rgw_get_errno_s3(rgw_http_errors *e , int err_no) +void rgw_get_errno_s3(rgw_http_error *e , int err_no) { - const struct rgw_http_errors *r; - r = search_err(err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS)); + rgw_http_errors::const_iterator r = rgw_http_s3_errors.find(err_no); - if (r) { - e->http_ret = r->http_ret; - e->s3_code = r->s3_code; + if (r != rgw_http_s3_errors.end()) { + e->http_ret = r->second.first; + e->s3_code = r->second.second; } else { e->http_ret = 500; e->s3_code = "UnknownError"; @@ -100,10 +99,10 @@ int RGWGetObj_ObjStore_S3Website::send_response_data(bufferlist& bl, off_t bl_of if (iter != attrs.end()) { bufferlist &bl = iter->second; s->redirect = string(bl.c_str(), bl.length()); - s->err.http_ret = 301; + s->err->http_ret = 301; ldout(s->cct, 20) << __CEPH_ASSERT_FUNCTION << " redirecting per x-amz-website-redirect-location=" << s->redirect << dendl; op_ret = -ERR_WEBSITE_REDIRECT; - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); dump_content_length(s, 0); dump_redirect(s, s->redirect); @@ -169,10 +168,10 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs, goto send_data; if (custom_http_ret) { - set_req_state_err(s, 0); + s->set_req_state_err(0); dump_errno(s, custom_http_ret); } else { - set_req_state_err(s, (partial_content && !op_ret) ? STATUS_PARTIAL_CONTENT + s->set_req_state_err((partial_content && !op_ret) ? STATUS_PARTIAL_CONTENT : op_ret); dump_errno(s); } @@ -341,7 +340,7 @@ int RGWGetObj_ObjStore_S3::get_decrypt_filter(std::unique_ptr *fil void RGWListBuckets_ObjStore_S3::send_response_begin(bool has_buckets) { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); dump_start(s); end_header(s, NULL, "application/xml"); @@ -407,7 +406,7 @@ static void dump_usage_categories_info(Formatter *formatter, const rgw_usage_log void RGWGetUsage_ObjStore_S3::send_response() { if (op_ret < 0) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -619,7 +618,7 @@ void RGWListBucket_ObjStore_S3::send_versioned_response() void RGWListBucket_ObjStore_S3::send_response() { if (op_ret < 0) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -817,7 +816,7 @@ int RGWSetBucketVersioning_ObjStore_S3::get_params() void RGWSetBucketVersioning_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s); } @@ -868,7 +867,7 @@ int RGWSetBucketWebsite_ObjStore_S3::get_params() void RGWSetBucketWebsite_ObjStore_S3::send_response() { if (op_ret < 0) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s); } @@ -878,7 +877,7 @@ void RGWDeleteBucketWebsite_ObjStore_S3::send_response() if (op_ret == 0) { op_ret = STATUS_NO_CONTENT; } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s); } @@ -886,7 +885,7 @@ void RGWDeleteBucketWebsite_ObjStore_S3::send_response() void RGWGetBucketWebsite_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); dump_start(s); @@ -915,7 +914,7 @@ void RGWStatBucket_ObjStore_S3::send_response() dump_bucket_metadata(s, bucket); } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); @@ -1055,7 +1054,7 @@ void RGWCreateBucket_ObjStore_S3::send_response() if (op_ret == -ERR_BUCKET_EXISTS) op_ret = 0; if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s); @@ -1080,7 +1079,7 @@ void RGWDeleteBucket_ObjStore_S3::send_response() if (!r) r = STATUS_NO_CONTENT; - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); end_header(s, this); @@ -1360,13 +1359,13 @@ static int get_success_retcode(int code) void RGWPutObj_ObjStore_S3::send_response() { if (op_ret) { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); } else { if (s->cct->_conf->rgw_s3_success_create_obj_status) { op_ret = get_success_retcode( s->cct->_conf->rgw_s3_success_create_obj_status); - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } if (!copy_source) { dump_errno(s); @@ -1888,8 +1887,8 @@ done: s->formatter->dump_string("Key", s->object.name); s->formatter->close_section(); } - s->err.message = err_msg; - set_req_state_err(s, op_ret); + s->err->message = err_msg; + s->set_req_state_err(op_ret); dump_errno(s); if (op_ret >= 0) { dump_content_length(s, s->formatter->get_len()); @@ -1948,7 +1947,7 @@ void RGWDeleteObj_ObjStore_S3::send_response() if (!r) r = STATUS_NO_CONTENT; - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); if (!version_id.empty()) { dump_header(s, "x-amz-version-id", version_id); @@ -2037,7 +2036,7 @@ void RGWCopyObj_ObjStore_S3::send_partial_response(off_t ofs) { if (! sent_header) { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -2073,7 +2072,7 @@ void RGWCopyObj_ObjStore_S3::send_response() void RGWGetACLs_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); dump_start(s); @@ -2119,7 +2118,7 @@ int RGWPutACLs_ObjStore_S3::get_policy_from_state(RGWRados *store, void RGWPutACLs_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); dump_start(s); @@ -2149,9 +2148,9 @@ void RGWGetLC_ObjStore_S3::send_response() { if (op_ret) { if (op_ret == -ENOENT) { - set_req_state_err(s, ERR_NO_SUCH_LC); + s->set_req_state_err(ERR_NO_SUCH_LC); } else { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } } dump_errno(s); @@ -2168,7 +2167,7 @@ void RGWGetLC_ObjStore_S3::send_response() void RGWPutLC_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); dump_start(s); @@ -2179,7 +2178,7 @@ void RGWDeleteLC_ObjStore_S3::send_response() if (op_ret == 0) op_ret = STATUS_NO_CONTENT; if (op_ret) { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } dump_errno(s); end_header(s, this, "application/xml"); @@ -2190,9 +2189,9 @@ void RGWGetCORS_ObjStore_S3::send_response() { if (op_ret) { if (op_ret == -ENOENT) - set_req_state_err(s, ERR_NOT_FOUND); + s->set_req_state_err(ERR_NOT_FOUND); else - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } dump_errno(s); end_header(s, NULL, "application/xml"); @@ -2260,7 +2259,7 @@ int RGWPutCORS_ObjStore_S3::get_params() void RGWPutCORS_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, NULL, "application/xml"); dump_start(s); @@ -2272,7 +2271,7 @@ void RGWDeleteCORS_ObjStore_S3::send_response() if (!r || r == -ENOENT) r = STATUS_NO_CONTENT; - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); end_header(s, NULL); } @@ -2287,7 +2286,7 @@ void RGWOptionsCORS_ObjStore_S3::send_response() if (op_ret == -ENOENT) op_ret = -EACCES; if (op_ret < 0) { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, NULL); return; @@ -2382,7 +2381,7 @@ done: void RGWSetRequestPayment_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s); } @@ -2402,7 +2401,7 @@ int RGWInitMultipart_ObjStore_S3::get_params() void RGWInitMultipart_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); for (auto &it : crypt_http_responses) dump_header(s, it.first, it.second); @@ -2446,7 +2445,7 @@ int RGWCompleteMultipart_ObjStore_S3::get_params() void RGWCompleteMultipart_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); if (op_ret == 0) { @@ -2481,7 +2480,7 @@ void RGWAbortMultipart_ObjStore_S3::send_response() if (!r) r = STATUS_NO_CONTENT; - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); end_header(s, this); } @@ -2489,7 +2488,7 @@ void RGWAbortMultipart_ObjStore_S3::send_response() void RGWListMultipart_ObjStore_S3::send_response() { if (op_ret) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -2539,7 +2538,7 @@ void RGWListMultipart_ObjStore_S3::send_response() void RGWListBucketMultiparts_ObjStore_S3::send_response() { if (op_ret < 0) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -2617,7 +2616,7 @@ void RGWDeleteMultiObj_ObjStore_S3::send_status() { if (! status_dumped) { if (op_ret < 0) - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); status_dumped = true; } @@ -2654,7 +2653,7 @@ void RGWDeleteMultiObj_ObjStore_S3::send_partial_response(rgw_obj_key& key, } s->formatter->close_section(); } else if (op_ret < 0) { - struct rgw_http_errors r; + struct rgw_http_error r; int err_no; s->formatter->open_object_section("Error"); @@ -3868,7 +3867,7 @@ int RGWHandler_REST_S3Website::retarget(RGWOp* op, RGWOp** new_op) { &redirect_code); // APply a custom HTTP response code if (redirect_code > 0) - s->err.http_ret = redirect_code; // Apply a custom HTTP response code + s->err->http_ret = redirect_code; // Apply a custom HTTP response code ldout(s->cct, 10) << "retarget redirect code=" << redirect_code << " proto+host:" << protocol << "://" << hostname << " -> " << s->redirect << dendl; @@ -3969,11 +3968,11 @@ int RGWHandler_REST_S3Website::serve_errordoc(int http_ret, const string& errord int RGWHandler_REST_S3Website::error_handler(int err_no, string* error_content) { int new_err_no = -1; - const struct rgw_http_errors* r; + rgw_http_errors::const_iterator r = rgw_http_s3_errors.find(err_no > 0 ? err_no : -err_no); int http_error_code = -1; - r = search_err(err_no > 0 ? err_no : -err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS)); - if (r) { - http_error_code = r->http_ret; + + if (r != rgw_http_s3_errors.end()) { + http_error_code = r->second.first; } ldout(s->cct, 10) << "RGWHandler_REST_S3Website::error_handler err_no=" << err_no << " http_ret=" << http_error_code << dendl; @@ -3991,7 +3990,7 @@ int RGWHandler_REST_S3Website::error_handler(int err_no, &redirect_code); // Apply a custom HTTP response code if (redirect_code > 0) - s->err.http_ret = redirect_code; // Apply a custom HTTP response code + s->err->http_ret = redirect_code; // Apply a custom HTTP response code ldout(s->cct, 10) << "error handler redirect code=" << redirect_code << " proto+host:" << protocol << "://" << hostname << " -> " << s->redirect << dendl; diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index 1e100efb2c5..072717a6822 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -27,7 +27,12 @@ #define RGW_AUTH_GRACE_MINS 15 -void rgw_get_errno_s3(struct rgw_http_errors *e, int err_no); +struct rgw_http_error { + int http_ret; + const char *s3_code; +}; + +void rgw_get_errno_s3(struct rgw_http_error *e, int err_no); class RGWGetObj_ObjStore_S3 : public RGWGetObj_ObjStore { diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index f778d87c412..f05ced9e282 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -33,6 +33,22 @@ #define dout_context g_ceph_context #define dout_subsys ceph_subsys_rgw +struct swift_err : public rgw_err { + swift_err(struct req_state *s) : rgw_err(s) {}; + + virtual bool set_rgw_err(int err_no) { + rgw_http_errors::const_iterator r; + + r = rgw_http_swift_errors.find(err_no); + if (r != rgw_http_swift_errors.end()) { + http_ret = r->second.first; + s3_code = r->second.second; + return true; + } + return rgw_err::set_rgw_err(err_no); + } +}; + int RGWListBuckets_ObjStore_SWIFT::get_params() { prefix = s->info.args.get("prefix"); @@ -140,10 +156,10 @@ static void dump_account_metadata(struct req_state * const s, void RGWListBuckets_ObjStore_SWIFT::send_response_begin(bool has_buckets) { if (op_ret) { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } else if (!has_buckets && s->format == RGW_FORMAT_PLAIN) { op_ret = STATUS_NO_CONTENT; - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); } if (! s->cct->_conf->rgw_swift_enforce_content_length) { @@ -360,7 +376,7 @@ next: op_ret = 0; } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, NULL, content_len); if (op_ret < 0) { @@ -477,7 +493,7 @@ void RGWStatAccount_ObjStore_SWIFT::send_response() static_cast(*s->user_acl)); } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, NULL, NULL, 0, true); @@ -493,7 +509,7 @@ void RGWStatBucket_ObjStore_SWIFT::send_response() s->bucket_info.website_conf); } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, NULL, 0, true); @@ -652,7 +668,7 @@ void RGWCreateBucket_ObjStore_SWIFT::send_response() op_ret = STATUS_CREATED; else if (op_ret == -ERR_BUCKET_EXISTS) op_ret = STATUS_ACCEPTED; - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); /* Propose ending HTTP header with 0 Content-Length header. */ end_header(s, NULL, NULL, 0); @@ -665,7 +681,7 @@ void RGWDeleteBucket_ObjStore_SWIFT::send_response() if (!r) r = STATUS_NO_CONTENT; - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); end_header(s, this, NULL, 0); rgw_flush_formatter_and_reset(s, s->formatter); @@ -838,7 +854,7 @@ void RGWPutObj_ObjStore_SWIFT::send_response() } dump_last_modified(s, mtime); - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); rgw_flush_formatter_and_reset(s, s->formatter); @@ -895,7 +911,7 @@ void RGWPutMetadataAccount_ObjStore_SWIFT::send_response() if (! op_ret) { op_ret = STATUS_NO_CONTENT; } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); rgw_flush_formatter_and_reset(s, s->formatter); @@ -925,7 +941,7 @@ void RGWPutMetadataBucket_ObjStore_SWIFT::send_response() if (!op_ret && (op_ret != -EINVAL)) { op_ret = STATUS_NO_CONTENT; } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); rgw_flush_formatter_and_reset(s, s->formatter); @@ -955,8 +971,8 @@ void RGWPutMetadataObject_ObjStore_SWIFT::send_response() if (! op_ret) { op_ret = STATUS_ACCEPTED; } - set_req_state_err(s, op_ret); - if (!s->err.is_err()) { + s->set_req_state_err(op_ret); + if (!s->is_err()) { dump_content_length(s, 0); } dump_errno(s); @@ -967,10 +983,9 @@ void RGWPutMetadataObject_ObjStore_SWIFT::send_response() static void bulkdelete_respond(const unsigned num_deleted, const unsigned int num_unfound, const std::list& failures, - const int prot_flags, /* in */ - ceph::Formatter& formatter) /* out */ + struct req_state *s) /* out */ { - formatter.open_object_section("delete"); + s->formatter->open_object_section("delete"); string resp_status; string resp_body; @@ -983,8 +998,8 @@ static void bulkdelete_respond(const unsigned num_deleted, } } - rgw_err err; - set_req_state_err(err, reason, prot_flags); + swift_err err(s); + err.set_rgw_err(reason); dump_errno(err, resp_status); } else if (0 == num_deleted && 0 == num_unfound) { /* 400 Bad Request */ @@ -995,29 +1010,29 @@ static void bulkdelete_respond(const unsigned num_deleted, dump_errno(200, resp_status); } - encode_json("Number Deleted", num_deleted, &formatter); - encode_json("Number Not Found", num_unfound, &formatter); - encode_json("Response Body", resp_body, &formatter); - encode_json("Response Status", resp_status, &formatter); + encode_json("Number Deleted", num_deleted, s->formatter); + encode_json("Number Not Found", num_unfound, s->formatter); + encode_json("Response Body", resp_body, s->formatter); + encode_json("Response Status", resp_status, s->formatter); - formatter.open_array_section("Errors"); + s->formatter->open_array_section("Errors"); for (const auto fail_desc : failures) { - formatter.open_array_section("object"); + s->formatter->open_array_section("object"); stringstream ss_name; ss_name << fail_desc.path; - encode_json("Name", ss_name.str(), &formatter); + encode_json("Name", ss_name.str(), s->formatter); - rgw_err err; - set_req_state_err(err, fail_desc.err, prot_flags); + swift_err err(s); + err.set_rgw_err(fail_desc.err); string status; dump_errno(err, status); - encode_json("Status", status, &formatter); - formatter.close_section(); + encode_json("Status", status, s->formatter); + s->formatter->close_section(); } - formatter.close_section(); + s->formatter->close_section(); - formatter.close_section(); + s->formatter->close_section(); } int RGWDeleteObj_ObjStore_SWIFT::verify_permission() @@ -1052,7 +1067,7 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response() r = STATUS_NO_CONTENT; } - set_req_state_err(s, r); + s->set_req_state_err(r); dump_errno(s); if (multipart_delete) { @@ -1063,10 +1078,9 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response() bulkdelete_respond(deleter->get_num_deleted(), deleter->get_num_unfound(), deleter->get_failures(), - s->prot_flags, - *s->formatter); + s); } else if (-ENOENT == op_ret) { - bulkdelete_respond(0, 1, {}, s->prot_flags, *s->formatter); + bulkdelete_respond(0, 1, {}, s); } else { RGWBulkDelete::acct_path_t path; path.bucket_name = s->bucket_name; @@ -1076,7 +1090,7 @@ void RGWDeleteObj_ObjStore_SWIFT::send_response() fail_desc.err = op_ret; fail_desc.path = path; - bulkdelete_respond(0, 0, { fail_desc }, s->prot_flags, *s->formatter); + bulkdelete_respond(0, 0, { fail_desc }, s); } } else { end_header(s, this); @@ -1190,7 +1204,7 @@ void RGWCopyObj_ObjStore_SWIFT::send_partial_response(off_t ofs) if (! sent_header) { if (! op_ret) op_ret = STATUS_CREATED; - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); @@ -1227,7 +1241,7 @@ void RGWCopyObj_ObjStore_SWIFT::send_response() string content_type; if (! op_ret) op_ret = STATUS_CREATED; - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); dump_etag(s, etag); dump_last_modified(s, mtime); @@ -1289,14 +1303,14 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl, } if (custom_http_ret) { - set_req_state_err(s, 0); + s->set_req_state_err(0); dump_errno(s, custom_http_ret); } else { - set_req_state_err(s, (partial_content && !op_ret) ? STATUS_PARTIAL_CONTENT + s->set_req_state_err((partial_content && !op_ret) ? STATUS_PARTIAL_CONTENT : op_ret); dump_errno(s); - if (s->err.is_err()) { + if (s->is_err()) { end_header(s, NULL); return 0; } @@ -1306,7 +1320,7 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl, dump_range(s, ofs, end, s->obj_size); } - if (s->err.is_err()) { + if (s->is_err()) { end_header(s, NULL); return 0; } @@ -1359,7 +1373,7 @@ void RGWOptionsCORS_ObjStore_SWIFT::send_response() if (op_ret == -ENOENT) op_ret = -EACCES; if (op_ret < 0) { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, NULL); return; @@ -1426,7 +1440,7 @@ int RGWBulkDelete_ObjStore_SWIFT::get_data( void RGWBulkDelete_ObjStore_SWIFT::send_response() { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this /* RGWOp */, nullptr /* contype */, CHUNKED_TRANSFER_ENCODING); @@ -1434,8 +1448,7 @@ void RGWBulkDelete_ObjStore_SWIFT::send_response() bulkdelete_respond(deleter->get_num_deleted(), deleter->get_num_unfound(), deleter->get_failures(), - s->prot_flags, - *s->formatter); + s); rgw_flush_formatter_and_reset(s, s->formatter); } @@ -1571,7 +1584,7 @@ void RGWBulkUploadOp_ObjStore_SWIFT::send_response() void RGWGetCrossDomainPolicy_ObjStore_SWIFT::send_response() { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -1589,7 +1602,7 @@ void RGWGetCrossDomainPolicy_ObjStore_SWIFT::send_response() void RGWGetHealthCheck_ObjStore_SWIFT::send_response() { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this, "application/xml"); @@ -1647,7 +1660,7 @@ void RGWInfo_ObjStore_SWIFT::send_response() if (op_ret < 0) { op_ret = STATUS_NO_CONTENT; } - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); end_header(s, this); rgw_flush_formatter_and_reset(s, s->formatter); @@ -2073,7 +2086,7 @@ int RGWSwiftWebsiteHandler::error_handler(const int err_no, const auto& ws_conf = s->bucket_info.website_conf; if (can_be_website_req() && ! ws_conf.error_doc.empty()) { - struct rgw_err err; + struct rgw_err err(s); set_req_state_err(err, err_no, s->prot_flags); return serve_errordoc(err.http_ret, ws_conf.error_doc); } @@ -2131,7 +2144,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_redirect_op() } void send_response() override { - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); dump_content_length(s, 0); dump_redirect(s, location); @@ -2176,7 +2189,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_listing_op() void send_response() override { /* Generate the header now. */ - set_req_state_err(s, op_ret); + s->set_req_state_err(op_ret); dump_errno(s); dump_container_metadata(s, bucket, bucket_quota, s->bucket_info.website_conf); @@ -2612,6 +2625,8 @@ int RGWHandler_REST_SWIFT::init_from_header(struct req_state* const s, string req; string first; + assert(!s->err); + s->err = new swift_err(s); s->prot_flags |= RGW_REST_SWIFT; char reqbuf[frontend_prefix.length() + s->decoded_uri.length() + 1]; diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 9f38209deb3..0b1293e286f 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -11,6 +11,7 @@ #include "rgw_op.h" #include "rgw_rest.h" #include "rgw_swift_auth.h" +#include "rgw_http_errors.h" #include diff --git a/src/rgw/rgw_swift_auth.cc b/src/rgw/rgw_swift_auth.cc index cc26db4fcce..4365385d8e5 100644 --- a/src/rgw/rgw_swift_auth.cc +++ b/src/rgw/rgw_swift_auth.cc @@ -627,7 +627,7 @@ void RGW_SWIFT_Auth_Get::execute() ret = STATUS_NO_CONTENT; done: - set_req_state_err(s, ret); + s->set_req_state_err(ret); dump_errno(s); end_header(s); } diff --git a/src/rgw/rgw_tools.cc b/src/rgw/rgw_tools.cc index 79bffb2018f..b79fecb6a85 100644 --- a/src/rgw/rgw_tools.cc +++ b/src/rgw/rgw_tools.cc @@ -42,7 +42,6 @@ int rgw_get_system_obj(RGWRados *rgwstore, RGWObjectCtx& obj_ctx, const rgw_pool RGWObjVersionTracker *objv_tracker, real_time *pmtime, map *pattrs, rgw_cache_entry_info *cache_info) { - struct rgw_err err; bufferlist::iterator iter; int request_len = READ_CHUNK_LEN; rgw_raw_obj obj(pool, key); @@ -58,7 +57,6 @@ int rgw_get_system_obj(RGWRados *rgwstore, RGWObjectCtx& obj_ctx, const rgw_pool rop.stat_params.attrs = pattrs; rop.stat_params.lastmod = pmtime; - rop.stat_params.perr = &err; int ret = rop.stat(objv_tracker); if (ret < 0) -- 2.39.5