1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_RGW_REST_H
5 #define CEPH_RGW_REST_H
7 #define TIME_BUF_SIZE 128
9 #include <boost/utility/string_ref.hpp>
10 #include <boost/container/flat_set.hpp>
11 #include "common/sstring.hh"
12 #include "common/ceph_json.h"
13 #include "include/assert.h" /* needed because of common/ceph_json.h */
15 #include "rgw_formats.h"
16 #include "rgw_client_io.h"
18 extern std::map<std::string, std::string> rgw_to_http_attrs;
20 extern string camelcase_dash_http_attr(const string& orig);
21 extern string lowercase_dash_http_attr(const string& orig);
23 extern void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group);
25 extern void rgw_flush_formatter_and_reset(struct req_state *s,
26 ceph::Formatter *formatter);
28 extern void rgw_flush_formatter(struct req_state *s,
29 ceph::Formatter *formatter);
31 extern int rgw_rest_read_all_input(struct req_state *s, char **data, int *plen,
32 uint64_t max_len, bool allow_chunked=true);
35 int rgw_rest_get_json_input(CephContext *cct, req_state *s, T& out,
36 uint64_t max_len, bool *empty)
44 if ((rv = rgw_rest_read_all_input(s, &data, &data_len, max_len)) < 0) {
58 if (!parser.parse(data, data_len)) {
66 decode_json_obj(out, &parser);
67 } catch (JSONDecoder::err& e) {
75 int rgw_rest_get_json_input_keep_data(CephContext *cct, req_state *s, T& out, uint64_t max_len, char **pdata, int *len)
80 if ((rv = rgw_rest_read_all_input(s, &data, &data_len, max_len)) < 0) {
92 if (!parser.parse(data, data_len)) {
98 decode_json_obj(out, &parser);
99 } catch (JSONDecoder::err& e) {
110 static int get_string(struct req_state *s, const string& name,
111 const string& def_val, string *val,
112 bool *existed = NULL);
113 static int get_uint64(struct req_state *s, const string& name,
114 uint64_t def_val, uint64_t *val, bool *existed = NULL);
115 static int get_int64(struct req_state *s, const string& name,
116 int64_t def_val, int64_t *val, bool *existed = NULL);
117 static int get_uint32(struct req_state *s, const string& name,
118 uint32_t def_val, uint32_t *val, bool *existed = NULL);
119 static int get_int32(struct req_state *s, const string& name,
120 int32_t def_val, int32_t *val, bool *existed = NULL);
121 static int get_time(struct req_state *s, const string& name,
122 const utime_t& def_val, utime_t *val,
123 bool *existed = NULL);
124 static int get_epoch(struct req_state *s, const string& name,
125 uint64_t def_val, uint64_t *epoch,
126 bool *existed = NULL);
127 static int get_bool(struct req_state *s, const string& name, bool def_val,
128 bool *val, bool *existed = NULL);
131 class RGWRESTFlusher : public RGWFormatterFlusher {
135 void do_flush() override;
136 void do_start(int ret) override;
138 RGWRESTFlusher(struct req_state *_s, RGWOp *_op) :
139 RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {}
140 RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {}
142 void init(struct req_state *_s, RGWOp *_op) {
145 set_formatter(s->formatter);
149 class RGWGetObj_ObjStore : public RGWGetObj
154 RGWGetObj_ObjStore() : sent_header(false) {}
156 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
157 RGWGetObj::init(store, s, h);
161 int get_params() override;
164 class RGWGetObjTags_ObjStore : public RGWGetObjTags {
166 RGWGetObjTags_ObjStore() {};
167 ~RGWGetObjTags_ObjStore() {};
170 class RGWPutObjTags_ObjStore: public RGWPutObjTags {
172 RGWPutObjTags_ObjStore() {};
173 ~RGWPutObjTags_ObjStore() {};
176 class RGWListBuckets_ObjStore : public RGWListBuckets {
178 RGWListBuckets_ObjStore() {}
179 ~RGWListBuckets_ObjStore() override {}
182 class RGWGetUsage_ObjStore : public RGWGetUsage {
184 RGWGetUsage_ObjStore() {}
185 ~RGWGetUsage_ObjStore() override {}
188 class RGWListBucket_ObjStore : public RGWListBucket {
190 RGWListBucket_ObjStore() {}
191 ~RGWListBucket_ObjStore() override {}
194 class RGWStatAccount_ObjStore : public RGWStatAccount {
196 RGWStatAccount_ObjStore() {}
197 ~RGWStatAccount_ObjStore() override {}
200 class RGWStatBucket_ObjStore : public RGWStatBucket {
202 RGWStatBucket_ObjStore() {}
203 ~RGWStatBucket_ObjStore() override {}
206 class RGWCreateBucket_ObjStore : public RGWCreateBucket {
208 RGWCreateBucket_ObjStore() {}
209 ~RGWCreateBucket_ObjStore() override {}
212 class RGWDeleteBucket_ObjStore : public RGWDeleteBucket {
214 RGWDeleteBucket_ObjStore() {}
215 ~RGWDeleteBucket_ObjStore() override {}
218 class RGWPutObj_ObjStore : public RGWPutObj
221 RGWPutObj_ObjStore() {}
222 ~RGWPutObj_ObjStore() override {}
224 int verify_params() override;
225 int get_params() override;
226 int get_data(bufferlist& bl) override;
229 class RGWPostObj_ObjStore : public RGWPostObj
231 std::string boundary;
234 struct post_part_field {
236 std::map<std::string, std::string> params;
239 struct post_form_part {
241 std::map<std::string, post_part_field, ltstr_nocase> fields;
242 ceph::bufferlist data;
246 using parts_collection_t = \
247 std::map<std::string, post_form_part, const ltstr_nocase>;
250 ceph::bufferlist in_data;
252 int read_with_boundary(ceph::bufferlist& bl,
255 bool& reached_boundary,
258 int read_line(ceph::bufferlist& bl,
260 bool& reached_boundary,
263 int read_data(ceph::bufferlist& bl,
265 bool& reached_boundary,
268 int read_form_part_header(struct post_form_part *part, bool& done);
270 int get_params() override;
272 static int parse_part_field(const std::string& line,
273 std::string& field_name, /* out */
274 post_part_field& field); /* out */
276 static void parse_boundary_params(const std::string& params_str,
278 std::map<std::string, std::string>& params);
280 static bool part_str(parts_collection_t& parts,
281 const std::string& name,
284 static std::string get_part_str(parts_collection_t& parts,
285 const std::string& name,
286 const std::string& def_val = std::string());
288 static bool part_bl(parts_collection_t& parts,
289 const std::string& name,
290 ceph::bufferlist *pbl);
293 RGWPostObj_ObjStore() {}
294 ~RGWPostObj_ObjStore() override {}
296 int verify_params() override;
300 class RGWPutMetadataAccount_ObjStore : public RGWPutMetadataAccount
303 RGWPutMetadataAccount_ObjStore() {}
304 ~RGWPutMetadataAccount_ObjStore() override {}
307 class RGWPutMetadataBucket_ObjStore : public RGWPutMetadataBucket
310 RGWPutMetadataBucket_ObjStore() {}
311 ~RGWPutMetadataBucket_ObjStore() override {}
314 class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject
317 RGWPutMetadataObject_ObjStore() {}
318 ~RGWPutMetadataObject_ObjStore() override {}
321 class RGWDeleteObj_ObjStore : public RGWDeleteObj {
323 RGWDeleteObj_ObjStore() {}
324 ~RGWDeleteObj_ObjStore() override {}
327 class RGWGetCrossDomainPolicy_ObjStore : public RGWGetCrossDomainPolicy {
329 RGWGetCrossDomainPolicy_ObjStore() = default;
330 ~RGWGetCrossDomainPolicy_ObjStore() override = default;
333 class RGWGetHealthCheck_ObjStore : public RGWGetHealthCheck {
335 RGWGetHealthCheck_ObjStore() = default;
336 ~RGWGetHealthCheck_ObjStore() override = default;
339 class RGWCopyObj_ObjStore : public RGWCopyObj {
341 RGWCopyObj_ObjStore() {}
342 ~RGWCopyObj_ObjStore() override {}
345 class RGWGetACLs_ObjStore : public RGWGetACLs {
347 RGWGetACLs_ObjStore() {}
348 ~RGWGetACLs_ObjStore() override {}
351 class RGWPutACLs_ObjStore : public RGWPutACLs {
353 RGWPutACLs_ObjStore() {}
354 ~RGWPutACLs_ObjStore() override {}
356 int get_params() override;
359 class RGWGetLC_ObjStore : public RGWGetLC {
361 RGWGetLC_ObjStore() {}
362 ~RGWGetLC_ObjStore() override {}
365 class RGWPutLC_ObjStore : public RGWPutLC {
367 RGWPutLC_ObjStore() {}
368 ~RGWPutLC_ObjStore() override {}
370 int get_params() override;
373 class RGWDeleteLC_ObjStore : public RGWDeleteLC {
375 RGWDeleteLC_ObjStore() {}
376 ~RGWDeleteLC_ObjStore() override {}
380 class RGWGetCORS_ObjStore : public RGWGetCORS {
382 RGWGetCORS_ObjStore() {}
383 ~RGWGetCORS_ObjStore() override {}
386 class RGWPutCORS_ObjStore : public RGWPutCORS {
388 RGWPutCORS_ObjStore() {}
389 ~RGWPutCORS_ObjStore() override {}
392 class RGWDeleteCORS_ObjStore : public RGWDeleteCORS {
394 RGWDeleteCORS_ObjStore() {}
395 ~RGWDeleteCORS_ObjStore() override {}
398 class RGWOptionsCORS_ObjStore : public RGWOptionsCORS {
400 RGWOptionsCORS_ObjStore() {}
401 ~RGWOptionsCORS_ObjStore() override {}
404 class RGWInitMultipart_ObjStore : public RGWInitMultipart {
406 RGWInitMultipart_ObjStore() {}
407 ~RGWInitMultipart_ObjStore() override {}
410 class RGWCompleteMultipart_ObjStore : public RGWCompleteMultipart {
412 RGWCompleteMultipart_ObjStore() {}
413 ~RGWCompleteMultipart_ObjStore() override {}
415 int get_params() override;
418 class RGWAbortMultipart_ObjStore : public RGWAbortMultipart {
420 RGWAbortMultipart_ObjStore() {}
421 ~RGWAbortMultipart_ObjStore() override {}
424 class RGWListMultipart_ObjStore : public RGWListMultipart {
426 RGWListMultipart_ObjStore() {}
427 ~RGWListMultipart_ObjStore() override {}
429 int get_params() override;
432 class RGWListBucketMultiparts_ObjStore : public RGWListBucketMultiparts {
434 RGWListBucketMultiparts_ObjStore() {}
435 ~RGWListBucketMultiparts_ObjStore() override {}
437 int get_params() override;
440 class RGWBulkDelete_ObjStore : public RGWBulkDelete {
442 RGWBulkDelete_ObjStore() {}
443 ~RGWBulkDelete_ObjStore() override {}
446 class RGWBulkUploadOp_ObjStore : public RGWBulkUploadOp {
448 RGWBulkUploadOp_ObjStore() = default;
449 ~RGWBulkUploadOp_ObjStore() = default;
452 class RGWDeleteMultiObj_ObjStore : public RGWDeleteMultiObj {
454 RGWDeleteMultiObj_ObjStore() {}
455 ~RGWDeleteMultiObj_ObjStore() override {}
457 int get_params() override;
460 class RGWInfo_ObjStore : public RGWInfo {
462 RGWInfo_ObjStore() = default;
463 ~RGWInfo_ObjStore() override = default;
466 class RGWRESTOp : public RGWOp {
469 RGWRESTFlusher flusher;
471 RGWRESTOp() : http_ret(0) {}
472 void init(RGWRados *store, struct req_state *s,
473 RGWHandler *dialect_handler) override {
474 RGWOp::init(store, s, dialect_handler);
475 flusher.init(s, this);
477 void send_response() override;
478 virtual int check_caps(RGWUserCaps& caps)
479 { return -EPERM; } /* should to be implemented! */
480 int verify_permission() override;
483 class RGWHandler_REST : public RGWHandler {
486 virtual bool is_obj_update_op() { return false; }
487 virtual RGWOp *op_get() { return NULL; }
488 virtual RGWOp *op_put() { return NULL; }
489 virtual RGWOp *op_delete() { return NULL; }
490 virtual RGWOp *op_head() { return NULL; }
491 virtual RGWOp *op_post() { return NULL; }
492 virtual RGWOp *op_copy() { return NULL; }
493 virtual RGWOp *op_options() { return NULL; }
495 static int allocate_formatter(struct req_state *s, int default_formatter,
498 static constexpr int MAX_BUCKET_NAME_LEN = 255;
499 static constexpr int MAX_OBJ_NAME_LEN = 1024;
502 ~RGWHandler_REST() override {}
504 static int validate_bucket_name(const string& bucket);
505 static int validate_object_name(const string& object);
507 int init_permissions(RGWOp* op) override;
508 int read_permissions(RGWOp* op) override;
510 virtual RGWOp* get_op(RGWRados* store);
511 virtual void put_op(RGWOp* op);
514 class RGWHandler_REST_SWIFT;
515 class RGWHandler_SWIFT_Auth;
516 class RGWHandler_REST_S3;
521 class StrategyRegistry;
530 std::map<std::string, RGWRESTMgr*> resource_mgrs;
531 std::multimap<size_t, std::string> resources_by_size;
532 RGWRESTMgr* default_mgr;
534 virtual RGWRESTMgr* get_resource_mgr(struct req_state* s,
535 const std::string& uri,
536 std::string* out_uri);
538 virtual RGWRESTMgr* get_resource_mgr_as_default(struct req_state* const s,
539 const std::string& uri,
540 std::string* our_uri) {
547 default_mgr(nullptr) {
549 virtual ~RGWRESTMgr();
551 void register_resource(std::string resource, RGWRESTMgr* mgr);
552 void register_default_mgr(RGWRESTMgr* mgr);
554 virtual RGWRESTMgr* get_manager(struct req_state* const s,
555 /* Prefix to be concatenated with @uri
556 * during the lookup. */
557 const std::string& frontend_prefix,
558 const std::string& uri,
559 std::string* out_uri) final {
560 return get_resource_mgr(s, frontend_prefix + uri, out_uri);
563 virtual RGWHandler_REST* get_handler(
564 struct req_state* const s,
565 const rgw::auth::StrategyRegistry& auth_registry,
566 const std::string& frontend_prefix
571 virtual void put_handler(RGWHandler_REST* const handler) {
575 void set_logging(bool _should_log) {
576 should_log = _should_log;
579 bool get_logging() const {
588 using x_header = basic_sstring<char, uint16_t, 32>;
589 boost::container::flat_set<x_header> x_headers;
592 static int preprocess(struct req_state *s, rgw::io::BasicClient* rio);
595 RGWHandler_REST *get_handler(RGWRados *store,
597 const rgw::auth::StrategyRegistry& auth_registry,
598 const std::string& frontend_prefix,
603 RGWHandler *get_handler(RGWRados *store, struct req_state *s,
604 RGWLibIO *io, RGWRESTMgr **pmgr,
608 void put_handler(RGWHandler_REST *handler) {
609 mgr.put_handler(handler);
612 void register_resource(string resource, RGWRESTMgr *m,
613 bool register_empty = false) {
614 if (!register_empty && resource.empty())
617 mgr.register_resource(resource, m);
620 void register_default_mgr(RGWRESTMgr *m) {
621 mgr.register_default_mgr(m);
624 void register_x_headers(const std::string& headers);
626 bool log_x_headers(void) {
627 return (x_headers.size() > 0);
630 bool log_x_header(const std::string& header) {
631 return (x_headers.find(header) != x_headers.end());
635 static constexpr int64_t NO_CONTENT_LENGTH = -1;
636 static constexpr int64_t CHUNKED_TRANSFER_ENCODING = -2;
638 extern void dump_errno(int http_ret, string& out);
639 extern void dump_errno(const struct rgw_err &err, string& out);
640 extern void dump_errno(struct req_state *s);
641 extern void dump_errno(struct req_state *s, int http_ret);
642 extern void end_header(struct req_state *s,
644 const char *content_type = nullptr,
645 const int64_t proposed_content_length =
647 bool force_content_type = false,
648 bool force_no_error = false);
649 extern void dump_start(struct req_state *s);
650 extern void list_all_buckets_start(struct req_state *s);
651 extern void dump_owner(struct req_state *s, const rgw_user& id, string& name,
652 const char *section = NULL);
653 extern void dump_header(struct req_state* s,
654 const boost::string_ref& name,
655 const boost::string_ref& val);
656 extern void dump_header(struct req_state* s,
657 const boost::string_ref& name,
658 ceph::buffer::list& bl);
659 extern void dump_header(struct req_state* s,
660 const boost::string_ref& name,
662 extern void dump_header(struct req_state* s,
663 const boost::string_ref& name,
666 template <class... Args>
667 static inline void dump_header_prefixed(struct req_state* s,
668 const boost::string_ref& name_prefix,
669 const boost::string_ref& name,
671 char full_name_buf[name_prefix.size() + name.size() + 1];
672 const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s",
673 static_cast<int>(name_prefix.length()),
675 static_cast<int>(name.length()),
677 boost::string_ref full_name(full_name_buf, len);
678 return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
681 template <class... Args>
682 static inline void dump_header_infixed(struct req_state* s,
683 const boost::string_ref& prefix,
684 const boost::string_ref& infix,
685 const boost::string_ref& sufix,
687 char full_name_buf[prefix.size() + infix.size() + sufix.size() + 1];
688 const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s%.*s",
689 static_cast<int>(prefix.length()),
691 static_cast<int>(infix.length()),
693 static_cast<int>(sufix.length()),
695 boost::string_ref full_name(full_name_buf, len);
696 return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
699 template <class... Args>
700 static inline void dump_header_quoted(struct req_state* s,
701 const boost::string_ref& name,
702 const boost::string_ref& val) {
703 /* We need two extra bytes for quotes. */
704 char qvalbuf[val.size() + 2 + 1];
705 const auto len = snprintf(qvalbuf, sizeof(qvalbuf), "\"%.*s\"",
706 static_cast<int>(val.length()), val.data());
707 return dump_header(s, name, boost::string_ref(qvalbuf, len));
710 template <class ValueT>
711 static inline void dump_header_if_nonempty(struct req_state* s,
712 const boost::string_ref& name,
713 const ValueT& value) {
714 if (name.length() > 0 && value.length() > 0) {
715 return dump_header(s, name, value);
719 extern void dump_content_length(struct req_state *s, uint64_t len);
720 extern int64_t parse_content_length(const char *content_length);
721 extern void dump_etag(struct req_state *s,
722 const boost::string_ref& etag,
723 bool quoted = false);
724 extern void dump_etag(struct req_state *s,
725 ceph::buffer::list& bl_etag,
726 bool quoted = false);
727 extern void dump_epoch_header(struct req_state *s, const char *name, real_time t);
728 extern void dump_time_header(struct req_state *s, const char *name, real_time t);
729 extern void dump_last_modified(struct req_state *s, real_time t);
730 extern void abort_early(struct req_state* s, RGWOp* op, int err,
731 RGWHandler* handler);
732 extern void dump_range(struct req_state* s, uint64_t ofs, uint64_t end,
733 uint64_t total_size);
734 extern void dump_continue(struct req_state *s);
735 extern void list_all_buckets_end(struct req_state *s);
736 extern void dump_time(struct req_state *s, const char *name, real_time *t);
737 extern std::string dump_time_to_str(const real_time& t);
738 extern void dump_bucket_from_state(struct req_state *s);
739 extern void dump_uri_from_state(struct req_state *s);
740 extern void dump_redirect(struct req_state *s, const string& redirect);
741 extern bool is_valid_url(const char *url);
742 extern void dump_access_control(struct req_state *s, const char *origin,
744 const char *hdr, const char *exp_hdr,
746 extern void dump_access_control(req_state *s, RGWOp *op);
748 extern int dump_body(struct req_state* s, const char* buf, size_t len);
749 extern int dump_body(struct req_state* s, /* const */ ceph::buffer::list& bl);
750 extern int dump_body(struct req_state* s, const std::string& str);
752 extern int recv_body(struct req_state* s, char* buf, size_t max);
754 #endif /* CEPH_RGW_REST_H */