(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);
<< 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)
req->exec_start();
done:
- return (ret < 0 ? ret : s->err.ret);
+ return (ret < 0 ? ret : s->err->ret);
}
int RGWLibProcess::finish_request(RGWLibContinuedReq* req)
#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"
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);
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()
{
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;
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;
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)
#define UINT32_MAX (0xffffffffu)
#endif
+struct req_state;
+
typedef void *RGWAccessHandle;
/** 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;
void dump(Formatter *f) const;
};
-struct req_state;
-
class RGWEnv;
/* Namespaced forward declarations. */
const char *length;
int64_t content_length;
map<string, string> generic_attrs;
- struct rgw_err err;
+ rgw_err *err;
bool expect_cont;
bool header_ended;
uint64_t obj_size;
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 {
&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*); */
#include "rgw_common.h"
-struct rgw_http_errors {
- int err_no;
- int http_ret;
- const char *s3_code;
-};
+typedef const std::map<int,const std::pair<int, const char*>> 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)
{
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 */
}
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);
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;
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;
#include <boost/algorithm/string/predicate.hpp>
#include <boost/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
+#include <boost/bind.hpp>
#include "common/Clock.h"
#include "common/armor.h"
RGWRados::Object::Read read_op(&op_target);
read_op.params.attrs = &attrs;
- read_op.params.perr = &s->err;
return read_op.prepare();
}
return true;
}
+/**
+ * Return a callable that can invoke dump_access_control().
+ */
+
+boost::function<void()> 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,
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)
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)
(version_id.empty() ? NULL : &version_id),
&s->req_id, /* use req_id as tag */
&etag,
- &s->err,
copy_obj_progress_cb, (void *)this
);
}
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
+#include <boost/function.hpp>
#include "common/armor.h"
#include "common/mime.h"
virtual uint32_t op_mask() { return 0; }
virtual int error_handler(int err_no, string *error_content);
+
+ boost::function<void()> dump_access_control_f();
};
class RGWGetObj : public RGWOp {
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;
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();
<< " ======"
<< dendl;
- return (ret < 0 ? ret : s->err.ret);
+ return (ret < 0 ? ret : s->err->ret);
} /* process_request */
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) {
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) {
}
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 {
string *version_id,
string *ptag,
ceph::buffer::list *petag,
- struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data)
{
string *version_id,
string *ptag,
ceph::buffer::list *petag,
- struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data)
{
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<string, bufferlist> src_attrs;
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) {
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();
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;
ceph::real_time *lastmod;
uint64_t *obj_size;
map<string, bufferlist> *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 {
ceph::real_time *lastmod;
uint64_t *obj_size;
map<string, bufferlist> *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) {}
string *version_id,
string *ptag,
ceph::buffer::list *petag,
- struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data);
/**
* 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,
string *version_id,
string *ptag,
ceph::buffer::list *petag,
- struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data);
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);
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+
#include <errno.h>
#include <limits.h>
#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"
#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;
static set<string> hostnames_set;
static set<string> 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;
}
}
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;
}
}
-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;
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)
}
}
-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<void()> 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) {
/* 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";
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) {
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<void()> 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<void()> 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;
/*
* 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<void()> 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 {
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);
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);
}
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,
class RGWRESTFlusher : public RGWFormatterFlusher {
struct req_state *s;
- RGWOp *op;
+ boost::function<void()> 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<void()> _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<void()> _op) {
s = _s;
op = _op;
set_formatter(s->formatter);
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)
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);
NO_CONTENT_LENGTH,
bool force_content_type = false,
bool force_no_error = false);
+extern void end_header(struct req_state *s,
+ boost::function<void()> 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,
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<void()> 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);
}
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);
#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"
}
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);
}
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);
}
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);
if (sent_header)
return;
- set_req_state_err(s, http_ret);
+ s->set_req_state_err(http_ret);
dump_errno(s);
end_header(s);
}
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);
}
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);
}
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);
}
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);
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);
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);
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
if (sent_header)
return;
- set_req_state_err(s, http_ret);
+ s->set_req_state_err(http_ret);
dump_errno(s);
end_header(s);
// 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;
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) {
}
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);
}
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);
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";
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);
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);
}
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");
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");
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");
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);
}
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);
}
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);
}
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);
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);
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);
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);
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);
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());
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);
{
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");
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);
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);
{
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);
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);
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");
{
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");
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);
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);
}
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;
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);
}
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);
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) {
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);
}
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");
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");
{
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;
}
}
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");
&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;
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;
&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;
#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
{
#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");
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) {
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) {
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*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);
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);
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);
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);
}
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);
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);
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);
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);
static void bulkdelete_respond(const unsigned num_deleted,
const unsigned int num_unfound,
const std::list<RGWBulkDelete::fail_desc_t>& 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;
}
}
- 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 */
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()
r = STATUS_NO_CONTENT;
}
- set_req_state_err(s, r);
+ s->set_req_state_err(r);
dump_errno(s);
if (multipart_delete) {
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;
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);
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);
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);
}
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;
}
dump_range(s, ofs, end, s->obj_size);
}
- if (s->err.is_err()) {
+ if (s->is_err()) {
end_header(s, NULL);
return 0;
}
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;
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);
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);
}
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");
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");
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);
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);
}
}
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);
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);
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];
#include "rgw_op.h"
#include "rgw_rest.h"
#include "rgw_swift_auth.h"
+#include "rgw_http_errors.h"
#include <boost/utility/string_ref.hpp>
ret = STATUS_NO_CONTENT;
done:
- set_req_state_err(s, ret);
+ s->set_req_state_err(ret);
dump_errno(s);
end_header(s);
}
RGWObjVersionTracker *objv_tracker, real_time *pmtime, map<string, bufferlist> *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);
rop.stat_params.attrs = pattrs;
rop.stat_params.lastmod = pmtime;
- rop.stat_params.perr = &err;
int ret = rop.stat(objv_tracker);
if (ret < 0)