diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/rgw/rgw_rest.h | |
parent | Initial commit. (diff) | |
download | ceph-upstream/16.2.11+ds.tar.xz ceph-upstream/16.2.11+ds.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/rgw/rgw_rest.h | 840 |
1 files changed, 840 insertions, 0 deletions
diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h new file mode 100644 index 000000000..0d6b67bbb --- /dev/null +++ b/src/rgw/rgw_rest.h @@ -0,0 +1,840 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +#pragma once + +#define TIME_BUF_SIZE 128 + +#include <string_view> +#include <boost/container/flat_set.hpp> +#include "common/sstring.hh" +#include "common/ceph_json.h" +#include "include/ceph_assert.h" /* needed because of common/ceph_json.h */ +#include "rgw_op.h" +#include "rgw_formats.h" +#include "rgw_client_io.h" + +extern std::map<std::string, std::string> rgw_to_http_attrs; + +extern void rgw_rest_init(CephContext *cct, const RGWZoneGroup& zone_group); + +extern void rgw_flush_formatter_and_reset(struct req_state *s, + ceph::Formatter *formatter); + +extern void rgw_flush_formatter(struct req_state *s, + ceph::Formatter *formatter); + +std::tuple<int, bufferlist > rgw_rest_read_all_input(struct req_state *s, + const uint64_t max_len, + const bool allow_chunked=true); + +inline std::string_view rgw_sanitized_hdrval(ceph::buffer::list& raw) +{ + /* std::string and thus std::string_view ARE OBLIGED to carry multiple + * 0x00 and count them to the length of a string. We need to take that + * into consideration and sanitize the size of a ceph::buffer::list used + * to store metadata values (x-amz-meta-*, X-Container-Meta-*, etags). + * Otherwise we might send 0x00 to clients. */ + const char* const data = raw.c_str(); + size_t len = raw.length(); + + if (len && data[len - 1] == '\0') { + /* That's the case - the null byte has been included at the last position + * of the bufferlist. We need to restore the proper string length we'll + * pass to string_ref. */ + len--; + } + + return std::string_view(data, len); +} + +template <class T> +int rgw_rest_get_json_input(CephContext *cct, req_state *s, T& out, + uint64_t max_len, bool *empty) +{ + if (empty) + *empty = false; + + int rv = 0; + bufferlist data; + std::tie(rv, data) = rgw_rest_read_all_input(s, max_len); + if (rv < 0) { + return rv; + } + + if (!data.length()) { + if (empty) { + *empty = true; + } + + return -EINVAL; + } + + JSONParser parser; + + if (!parser.parse(data.c_str(), data.length())) { + return -EINVAL; + } + + try { + decode_json_obj(out, &parser); + } catch (JSONDecoder::err& e) { + return -EINVAL; + } + + return 0; +} + +template <class T> +std::tuple<int, bufferlist > rgw_rest_get_json_input_keep_data(CephContext *cct, req_state *s, T& out, uint64_t max_len) +{ + int rv = 0; + bufferlist data; + std::tie(rv, data) = rgw_rest_read_all_input(s, max_len); + if (rv < 0) { + return std::make_tuple(rv, std::move(data)); + } + + if (!data.length()) { + return std::make_tuple(-EINVAL, std::move(data)); + } + + JSONParser parser; + + if (!parser.parse(data.c_str(), data.length())) { + return std::make_tuple(-EINVAL, std::move(data)); + } + + try { + decode_json_obj(out, &parser); + } catch (JSONDecoder::err& e) { + return std::make_tuple(-EINVAL, std::move(data)); + } + + return std::make_tuple(0, std::move(data)); +} + +class RESTArgs { +public: + static int get_string(struct req_state *s, const string& name, + const string& def_val, string *val, + bool *existed = NULL); + static int get_uint64(struct req_state *s, const string& name, + uint64_t def_val, uint64_t *val, bool *existed = NULL); + static int get_int64(struct req_state *s, const string& name, + int64_t def_val, int64_t *val, bool *existed = NULL); + static int get_uint32(struct req_state *s, const string& name, + uint32_t def_val, uint32_t *val, bool *existed = NULL); + static int get_int32(struct req_state *s, const string& name, + int32_t def_val, int32_t *val, bool *existed = NULL); + static int get_time(struct req_state *s, const string& name, + const utime_t& def_val, utime_t *val, + bool *existed = NULL); + static int get_epoch(struct req_state *s, const string& name, + uint64_t def_val, uint64_t *epoch, + bool *existed = NULL); + static int get_bool(struct req_state *s, const string& name, bool def_val, + bool *val, bool *existed = NULL); +}; + +class RGWRESTFlusher : public RGWFormatterFlusher { + struct req_state *s; + RGWOp *op; +protected: + void do_flush() override; + void do_start(int ret) override; +public: + RGWRESTFlusher(struct req_state *_s, RGWOp *_op) : + RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {} + RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {} + + void init(struct req_state *_s, RGWOp *_op) { + s = _s; + op = _op; + set_formatter(s->formatter); + } +}; + +class RGWGetObj_ObjStore : public RGWGetObj +{ +protected: + bool sent_header; +public: + RGWGetObj_ObjStore() : sent_header(false) {} + + void init(rgw::sal::RGWRadosStore *store, struct req_state *s, RGWHandler *h) override { + RGWGetObj::init(store, s, h); + sent_header = false; + } + + int get_params(optional_yield y) override; +}; + +class RGWGetObjTags_ObjStore : public RGWGetObjTags { +public: + RGWGetObjTags_ObjStore() {}; + ~RGWGetObjTags_ObjStore() {}; +}; + +class RGWPutObjTags_ObjStore: public RGWPutObjTags { +public: + RGWPutObjTags_ObjStore() {}; + ~RGWPutObjTags_ObjStore() {}; +}; + +class RGWGetBucketTags_ObjStore : public RGWGetBucketTags { +public: + RGWGetBucketTags_ObjStore() = default; + virtual ~RGWGetBucketTags_ObjStore() = default; +}; + +class RGWPutBucketTags_ObjStore: public RGWPutBucketTags { +public: + RGWPutBucketTags_ObjStore() = default; + virtual ~RGWPutBucketTags_ObjStore() = default; +}; + +class RGWGetBucketReplication_ObjStore : public RGWGetBucketReplication { +public: + RGWGetBucketReplication_ObjStore() {}; + ~RGWGetBucketReplication_ObjStore() {}; +}; + +class RGWPutBucketReplication_ObjStore: public RGWPutBucketReplication { +public: + RGWPutBucketReplication_ObjStore() = default; + virtual ~RGWPutBucketReplication_ObjStore() = default; +}; + +class RGWDeleteBucketReplication_ObjStore: public RGWDeleteBucketReplication { +public: + RGWDeleteBucketReplication_ObjStore() = default; + virtual ~RGWDeleteBucketReplication_ObjStore() = default; +}; + +class RGWListBuckets_ObjStore : public RGWListBuckets { +public: + RGWListBuckets_ObjStore() {} + ~RGWListBuckets_ObjStore() override {} +}; + +class RGWGetUsage_ObjStore : public RGWGetUsage { +public: + RGWGetUsage_ObjStore() {} + ~RGWGetUsage_ObjStore() override {} +}; + +class RGWListBucket_ObjStore : public RGWListBucket { +public: + RGWListBucket_ObjStore() {} + ~RGWListBucket_ObjStore() override {} +}; + +class RGWStatAccount_ObjStore : public RGWStatAccount { +public: + RGWStatAccount_ObjStore() {} + ~RGWStatAccount_ObjStore() override {} +}; + +class RGWStatBucket_ObjStore : public RGWStatBucket { +public: + RGWStatBucket_ObjStore() {} + ~RGWStatBucket_ObjStore() override {} +}; + +class RGWCreateBucket_ObjStore : public RGWCreateBucket { +public: + RGWCreateBucket_ObjStore() {} + ~RGWCreateBucket_ObjStore() override {} +}; + +class RGWDeleteBucket_ObjStore : public RGWDeleteBucket { +public: + RGWDeleteBucket_ObjStore() {} + ~RGWDeleteBucket_ObjStore() override {} +}; + +class RGWPutObj_ObjStore : public RGWPutObj +{ +public: + RGWPutObj_ObjStore() {} + ~RGWPutObj_ObjStore() override {} + + int verify_params() override; + int get_params(optional_yield y) override; + int get_data(bufferlist& bl) override; +}; + +class RGWPostObj_ObjStore : public RGWPostObj +{ + std::string boundary; + +public: + struct post_part_field { + std::string val; + std::map<std::string, std::string> params; + }; + + struct post_form_part { + std::string name; + std::map<std::string, post_part_field, ltstr_nocase> fields; + ceph::bufferlist data; + }; + +protected: + using parts_collection_t = \ + std::map<std::string, post_form_part, const ltstr_nocase>; + + std::string err_msg; + ceph::bufferlist in_data; + + int read_with_boundary(ceph::bufferlist& bl, + uint64_t max, + bool check_eol, + bool& reached_boundary, + bool& done); + + int read_line(ceph::bufferlist& bl, + uint64_t max, + bool& reached_boundary, + bool& done); + + int read_data(ceph::bufferlist& bl, + uint64_t max, + bool& reached_boundary, + bool& done); + + int read_form_part_header(struct post_form_part *part, bool& done); + + int get_params(optional_yield y) override; + + static int parse_part_field(const std::string& line, + std::string& field_name, /* out */ + post_part_field& field); /* out */ + + static void parse_boundary_params(const std::string& params_str, + std::string& first, + std::map<std::string, std::string>& params); + + static bool part_str(parts_collection_t& parts, + const std::string& name, + std::string *val); + + static std::string get_part_str(parts_collection_t& parts, + const std::string& name, + const std::string& def_val = std::string()); + + static bool part_bl(parts_collection_t& parts, + const std::string& name, + ceph::bufferlist *pbl); + +public: + RGWPostObj_ObjStore() {} + ~RGWPostObj_ObjStore() override {} + + int verify_params() override; +}; + + +class RGWPutMetadataAccount_ObjStore : public RGWPutMetadataAccount +{ +public: + RGWPutMetadataAccount_ObjStore() {} + ~RGWPutMetadataAccount_ObjStore() override {} +}; + +class RGWPutMetadataBucket_ObjStore : public RGWPutMetadataBucket +{ +public: + RGWPutMetadataBucket_ObjStore() {} + ~RGWPutMetadataBucket_ObjStore() override {} +}; + +class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject +{ +public: + RGWPutMetadataObject_ObjStore() {} + ~RGWPutMetadataObject_ObjStore() override {} +}; + +class RGWDeleteObj_ObjStore : public RGWDeleteObj { +public: + RGWDeleteObj_ObjStore() {} + ~RGWDeleteObj_ObjStore() override {} +}; + +class RGWGetCrossDomainPolicy_ObjStore : public RGWGetCrossDomainPolicy { +public: + RGWGetCrossDomainPolicy_ObjStore() = default; + ~RGWGetCrossDomainPolicy_ObjStore() override = default; +}; + +class RGWGetHealthCheck_ObjStore : public RGWGetHealthCheck { +public: + RGWGetHealthCheck_ObjStore() = default; + ~RGWGetHealthCheck_ObjStore() override = default; +}; + +class RGWCopyObj_ObjStore : public RGWCopyObj { +public: + RGWCopyObj_ObjStore() {} + ~RGWCopyObj_ObjStore() override {} +}; + +class RGWGetACLs_ObjStore : public RGWGetACLs { +public: + RGWGetACLs_ObjStore() {} + ~RGWGetACLs_ObjStore() override {} +}; + +class RGWPutACLs_ObjStore : public RGWPutACLs { +public: + RGWPutACLs_ObjStore() {} + ~RGWPutACLs_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWGetLC_ObjStore : public RGWGetLC { +public: + RGWGetLC_ObjStore() {} + ~RGWGetLC_ObjStore() override {} +}; + +class RGWPutLC_ObjStore : public RGWPutLC { +public: + RGWPutLC_ObjStore() {} + ~RGWPutLC_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWDeleteLC_ObjStore : public RGWDeleteLC { +public: + RGWDeleteLC_ObjStore() {} + ~RGWDeleteLC_ObjStore() override {} + +}; + +class RGWGetCORS_ObjStore : public RGWGetCORS { +public: + RGWGetCORS_ObjStore() {} + ~RGWGetCORS_ObjStore() override {} +}; + +class RGWPutCORS_ObjStore : public RGWPutCORS { +public: + RGWPutCORS_ObjStore() {} + ~RGWPutCORS_ObjStore() override {} +}; + +class RGWDeleteCORS_ObjStore : public RGWDeleteCORS { +public: + RGWDeleteCORS_ObjStore() {} + ~RGWDeleteCORS_ObjStore() override {} +}; + +class RGWOptionsCORS_ObjStore : public RGWOptionsCORS { +public: + RGWOptionsCORS_ObjStore() {} + ~RGWOptionsCORS_ObjStore() override {} +}; + +class RGWInitMultipart_ObjStore : public RGWInitMultipart { +public: + RGWInitMultipart_ObjStore() {} + ~RGWInitMultipart_ObjStore() override {} +}; + +class RGWCompleteMultipart_ObjStore : public RGWCompleteMultipart { +public: + RGWCompleteMultipart_ObjStore() {} + ~RGWCompleteMultipart_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWAbortMultipart_ObjStore : public RGWAbortMultipart { +public: + RGWAbortMultipart_ObjStore() {} + ~RGWAbortMultipart_ObjStore() override {} +}; + +class RGWListMultipart_ObjStore : public RGWListMultipart { +public: + RGWListMultipart_ObjStore() {} + ~RGWListMultipart_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWListBucketMultiparts_ObjStore : public RGWListBucketMultiparts { +public: + RGWListBucketMultiparts_ObjStore() {} + ~RGWListBucketMultiparts_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWBulkDelete_ObjStore : public RGWBulkDelete { +public: + RGWBulkDelete_ObjStore() {} + ~RGWBulkDelete_ObjStore() override {} +}; + +class RGWBulkUploadOp_ObjStore : public RGWBulkUploadOp { +public: + RGWBulkUploadOp_ObjStore() = default; + ~RGWBulkUploadOp_ObjStore() = default; +}; + +class RGWDeleteMultiObj_ObjStore : public RGWDeleteMultiObj { +public: + RGWDeleteMultiObj_ObjStore() {} + ~RGWDeleteMultiObj_ObjStore() override {} + + int get_params(optional_yield y) override; +}; + +class RGWInfo_ObjStore : public RGWInfo { +public: + RGWInfo_ObjStore() = default; + ~RGWInfo_ObjStore() override = default; +}; + +class RGWPutBucketObjectLock_ObjStore : public RGWPutBucketObjectLock { +public: + RGWPutBucketObjectLock_ObjStore() = default; + ~RGWPutBucketObjectLock_ObjStore() = default; + int get_params(optional_yield y) override; +}; + +class RGWGetBucketObjectLock_ObjStore : public RGWGetBucketObjectLock { +public: + RGWGetBucketObjectLock_ObjStore() = default; + ~RGWGetBucketObjectLock_ObjStore() override = default; +}; + +class RGWPutObjRetention_ObjStore : public RGWPutObjRetention { +public: + RGWPutObjRetention_ObjStore() = default; + ~RGWPutObjRetention_ObjStore() override = default; +}; + +class RGWGetObjRetention_ObjStore : public RGWGetObjRetention { +public: + RGWGetObjRetention_ObjStore() = default; + ~RGWGetObjRetention_ObjStore() = default; +}; + +class RGWPutObjLegalHold_ObjStore : public RGWPutObjLegalHold { +public: + RGWPutObjLegalHold_ObjStore() = default; + ~RGWPutObjLegalHold_ObjStore() override = default; + int get_params(optional_yield y) override; +}; + +class RGWGetObjLegalHold_ObjStore : public RGWGetObjLegalHold { +public: + RGWGetObjLegalHold_ObjStore() = default; + ~RGWGetObjLegalHold_ObjStore() = default; +}; + +class RGWRESTOp : public RGWOp { +protected: + RGWRESTFlusher flusher; +public: + void init(rgw::sal::RGWRadosStore *store, struct req_state *s, + RGWHandler *dialect_handler) override { + RGWOp::init(store, s, dialect_handler); + flusher.init(s, this); + } + void send_response() override; + virtual int check_caps(const RGWUserCaps& caps) + { return -EPERM; } /* should to be implemented! */ + int verify_permission(optional_yield y) override; + dmc::client_id dmclock_client() override { return dmc::client_id::admin; } +}; + +class RGWHandler_REST : public RGWHandler { +protected: + + virtual bool is_obj_update_op() const { return false; } + virtual RGWOp *op_get() { return NULL; } + virtual RGWOp *op_put() { return NULL; } + virtual RGWOp *op_delete() { return NULL; } + virtual RGWOp *op_head() { return NULL; } + virtual RGWOp *op_post() { return NULL; } + virtual RGWOp *op_copy() { return NULL; } + virtual RGWOp *op_options() { return NULL; } + +public: + static int allocate_formatter(struct req_state *s, int default_formatter, + bool configurable); + + static constexpr int MAX_BUCKET_NAME_LEN = 255; + static constexpr int MAX_OBJ_NAME_LEN = 1024; + + RGWHandler_REST() {} + ~RGWHandler_REST() override {} + + static int validate_bucket_name(const string& bucket); + static int validate_object_name(const string& object); + static int reallocate_formatter(struct req_state *s, int type); + + int init_permissions(RGWOp* op, optional_yield y) override; + int read_permissions(RGWOp* op, optional_yield y) override; + + virtual RGWOp* get_op(void); + virtual void put_op(RGWOp* op); +}; + +class RGWHandler_REST_SWIFT; +class RGWHandler_SWIFT_Auth; +class RGWHandler_REST_S3; + +namespace rgw::auth { + +class StrategyRegistry; + +} + +class RGWRESTMgr { + bool should_log; + +protected: + std::map<std::string, RGWRESTMgr*> resource_mgrs; + std::multimap<size_t, std::string> resources_by_size; + RGWRESTMgr* default_mgr; + + virtual RGWRESTMgr* get_resource_mgr(struct req_state* s, + const std::string& uri, + std::string* out_uri); + + virtual RGWRESTMgr* get_resource_mgr_as_default(struct req_state* const s, + const std::string& uri, + std::string* our_uri) { + return this; + } + +public: + RGWRESTMgr() + : should_log(false), + default_mgr(nullptr) { + } + virtual ~RGWRESTMgr(); + + void register_resource(std::string resource, RGWRESTMgr* mgr); + void register_default_mgr(RGWRESTMgr* mgr); + + virtual RGWRESTMgr* get_manager(struct req_state* const s, + /* Prefix to be concatenated with @uri + * during the lookup. */ + const std::string& frontend_prefix, + const std::string& uri, + std::string* out_uri) final { + return get_resource_mgr(s, frontend_prefix + uri, out_uri); + } + + virtual RGWHandler_REST* get_handler( + rgw::sal::RGWRadosStore *store, + struct req_state* const s, + const rgw::auth::StrategyRegistry& auth_registry, + const std::string& frontend_prefix + ) { + return nullptr; + } + + virtual void put_handler(RGWHandler_REST* const handler) { + delete handler; + } + + void set_logging(bool _should_log) { + should_log = _should_log; + } + + bool get_logging() const { + return should_log; + } +}; + +class RGWLibIO; +class RGWRestfulIO; + +class RGWREST { + using x_header = basic_sstring<char, uint16_t, 32>; + boost::container::flat_set<x_header> x_headers; + RGWRESTMgr mgr; + + static int preprocess(struct req_state *s, rgw::io::BasicClient* rio); +public: + RGWREST() {} + RGWHandler_REST *get_handler(rgw::sal::RGWRadosStore *store, + struct req_state *s, + const rgw::auth::StrategyRegistry& auth_registry, + const std::string& frontend_prefix, + RGWRestfulIO *rio, + RGWRESTMgr **pmgr, + int *init_error); +#if 0 + RGWHandler *get_handler(RGWRados *store, struct req_state *s, + RGWLibIO *io, RGWRESTMgr **pmgr, + int *init_error); +#endif + + void put_handler(RGWHandler_REST *handler) { + mgr.put_handler(handler); + } + + void register_resource(string resource, RGWRESTMgr *m, + bool register_empty = false) { + if (!register_empty && resource.empty()) + return; + + mgr.register_resource(resource, m); + } + + void register_default_mgr(RGWRESTMgr *m) { + mgr.register_default_mgr(m); + } + + void register_x_headers(const std::string& headers); + + bool log_x_headers(void) { + return (x_headers.size() > 0); + } + + bool log_x_header(const std::string& header) { + return (x_headers.find(header) != x_headers.end()); + } +}; + +static constexpr int64_t NO_CONTENT_LENGTH = -1; +static constexpr int64_t CHUNKED_TRANSFER_ENCODING = -2; + +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); +extern void dump_errno(struct req_state *s, int http_ret); +extern void end_header(struct req_state *s, + RGWOp* op = nullptr, + 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, + const char *section = NULL); +extern void dump_header(struct req_state* s, + const std::string_view& name, + const std::string_view& val); +extern void dump_header(struct req_state* s, + const std::string_view& name, + ceph::buffer::list& bl); +extern void dump_header(struct req_state* s, + const std::string_view& name, + long long val); +extern void dump_header(struct req_state* s, + const std::string_view& name, + const utime_t& val); + +template <class... Args> +inline void dump_header_prefixed(struct req_state* s, + const std::string_view& name_prefix, + const std::string_view& name, + Args&&... args) { + char full_name_buf[name_prefix.size() + name.size() + 1]; + const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s", + static_cast<int>(name_prefix.length()), + name_prefix.data(), + static_cast<int>(name.length()), + name.data()); + std::string_view full_name(full_name_buf, len); + return dump_header(s, std::move(full_name), std::forward<Args>(args)...); +} + +template <class... Args> +inline void dump_header_infixed(struct req_state* s, + const std::string_view& prefix, + const std::string_view& infix, + const std::string_view& sufix, + Args&&... args) { + char full_name_buf[prefix.size() + infix.size() + sufix.size() + 1]; + const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s%.*s", + static_cast<int>(prefix.length()), + prefix.data(), + static_cast<int>(infix.length()), + infix.data(), + static_cast<int>(sufix.length()), + sufix.data()); + std::string_view full_name(full_name_buf, len); + return dump_header(s, std::move(full_name), std::forward<Args>(args)...); +} + +template <class... Args> +inline void dump_header_quoted(struct req_state* s, + const std::string_view& name, + const std::string_view& val) { + /* We need two extra bytes for quotes. */ + char qvalbuf[val.size() + 2 + 1]; + const auto len = snprintf(qvalbuf, sizeof(qvalbuf), "\"%.*s\"", + static_cast<int>(val.length()), val.data()); + return dump_header(s, name, std::string_view(qvalbuf, len)); +} + +template <class ValueT> +inline void dump_header_if_nonempty(struct req_state* s, + const std::string_view& name, + const ValueT& value) { + if (name.length() > 0 && value.length() > 0) { + return dump_header(s, name, value); + } +} + +inline std::string compute_domain_uri(const struct req_state *s) { + std::string uri = (!s->info.domain.empty()) ? s->info.domain : + [&s]() -> std::string { + RGWEnv const &env(*(s->info.env)); + std::string uri = + env.get("SERVER_PORT_SECURE") ? "https://" : "http://"; + if (env.exists("SERVER_NAME")) { + uri.append(env.get("SERVER_NAME", "<SERVER_NAME>")); + } else { + uri.append(env.get("HTTP_HOST", "<HTTP_HOST>")); + } + return uri; + }(); + return uri; +} + +extern void dump_content_length(struct req_state *s, uint64_t len); +extern int64_t parse_content_length(const char *content_length); +extern void dump_etag(struct req_state *s, + const std::string_view& etag, + bool quoted = false); +extern void dump_epoch_header(struct req_state *s, const char *name, real_time t); +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, optional_yield y); +extern void dump_range(struct req_state* s, uint64_t ofs, uint64_t end, + uint64_t total_size); +extern void dump_continue(struct req_state *s); +extern void list_all_buckets_end(struct req_state *s); +extern void dump_time(struct req_state *s, const char *name, real_time *t); +extern std::string dump_time_to_str(const real_time& t); +extern void dump_bucket_from_state(struct req_state *s); +extern void dump_redirect(struct req_state *s, const string& redirect); +extern bool is_valid_url(const char *url); +extern void dump_access_control(struct req_state *s, const char *origin, + const char *meth, + const char *hdr, const char *exp_hdr, + uint32_t max_age); +extern void dump_access_control(req_state *s, RGWOp *op); + +extern int dump_body(struct req_state* s, const char* buf, size_t len); +extern int dump_body(struct req_state* s, /* const */ ceph::buffer::list& bl); +extern int dump_body(struct req_state* s, const std::string& str); +extern int recv_body(struct req_state* s, char* buf, size_t max); |