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_tenant_name(const string
& bucket
);
505 static int validate_bucket_name(const string
& bucket
);
506 static int validate_object_name(const string
& object
);
508 int init_permissions(RGWOp
* op
) override
;
509 int read_permissions(RGWOp
* op
) override
;
511 virtual RGWOp
* get_op(RGWRados
* store
);
512 virtual void put_op(RGWOp
* op
);
515 class RGWHandler_REST_SWIFT
;
516 class RGWHandler_SWIFT_Auth
;
517 class RGWHandler_REST_S3
;
522 class StrategyRegistry
;
531 std::map
<std::string
, RGWRESTMgr
*> resource_mgrs
;
532 std::multimap
<size_t, std::string
> resources_by_size
;
533 RGWRESTMgr
* default_mgr
;
535 virtual RGWRESTMgr
* get_resource_mgr(struct req_state
* s
,
536 const std::string
& uri
,
537 std::string
* out_uri
);
539 virtual RGWRESTMgr
* get_resource_mgr_as_default(struct req_state
* const s
,
540 const std::string
& uri
,
541 std::string
* our_uri
) {
548 default_mgr(nullptr) {
550 virtual ~RGWRESTMgr();
552 void register_resource(std::string resource
, RGWRESTMgr
* mgr
);
553 void register_default_mgr(RGWRESTMgr
* mgr
);
555 virtual RGWRESTMgr
* get_manager(struct req_state
* const s
,
556 /* Prefix to be concatenated with @uri
557 * during the lookup. */
558 const std::string
& frontend_prefix
,
559 const std::string
& uri
,
560 std::string
* out_uri
) final
{
561 return get_resource_mgr(s
, frontend_prefix
+ uri
, out_uri
);
564 virtual RGWHandler_REST
* get_handler(
565 struct req_state
* const s
,
566 const rgw::auth::StrategyRegistry
& auth_registry
,
567 const std::string
& frontend_prefix
572 virtual void put_handler(RGWHandler_REST
* const handler
) {
576 void set_logging(bool _should_log
) {
577 should_log
= _should_log
;
580 bool get_logging() const {
589 using x_header
= basic_sstring
<char, uint16_t, 32>;
590 boost::container::flat_set
<x_header
> x_headers
;
593 static int preprocess(struct req_state
*s
, rgw::io::BasicClient
* rio
);
596 RGWHandler_REST
*get_handler(RGWRados
*store
,
598 const rgw::auth::StrategyRegistry
& auth_registry
,
599 const std::string
& frontend_prefix
,
604 RGWHandler
*get_handler(RGWRados
*store
, struct req_state
*s
,
605 RGWLibIO
*io
, RGWRESTMgr
**pmgr
,
609 void put_handler(RGWHandler_REST
*handler
) {
610 mgr
.put_handler(handler
);
613 void register_resource(string resource
, RGWRESTMgr
*m
,
614 bool register_empty
= false) {
615 if (!register_empty
&& resource
.empty())
618 mgr
.register_resource(resource
, m
);
621 void register_default_mgr(RGWRESTMgr
*m
) {
622 mgr
.register_default_mgr(m
);
625 void register_x_headers(const std::string
& headers
);
627 bool log_x_headers(void) {
628 return (x_headers
.size() > 0);
631 bool log_x_header(const std::string
& header
) {
632 return (x_headers
.find(header
) != x_headers
.end());
636 static constexpr int64_t NO_CONTENT_LENGTH
= -1;
637 static constexpr int64_t CHUNKED_TRANSFER_ENCODING
= -2;
639 extern void dump_errno(int http_ret
, string
& out
);
640 extern void dump_errno(const struct rgw_err
&err
, string
& out
);
641 extern void dump_errno(struct req_state
*s
);
642 extern void dump_errno(struct req_state
*s
, int http_ret
);
643 extern void end_header(struct req_state
*s
,
645 const char *content_type
= nullptr,
646 const int64_t proposed_content_length
=
648 bool force_content_type
= false,
649 bool force_no_error
= false);
650 extern void dump_start(struct req_state
*s
);
651 extern void list_all_buckets_start(struct req_state
*s
);
652 extern void dump_owner(struct req_state
*s
, const rgw_user
& id
, string
& name
,
653 const char *section
= NULL
);
654 extern void dump_header(struct req_state
* s
,
655 const boost::string_ref
& name
,
656 const boost::string_ref
& val
);
657 extern void dump_header(struct req_state
* s
,
658 const boost::string_ref
& name
,
659 ceph::buffer::list
& bl
);
660 extern void dump_header(struct req_state
* s
,
661 const boost::string_ref
& name
,
663 extern void dump_header(struct req_state
* s
,
664 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_quoted(struct req_state
* s
,
683 const boost::string_ref
& name
,
684 const boost::string_ref
& val
) {
685 /* We need two extra bytes for quotes. */
686 char qvalbuf
[val
.size() + 2 + 1];
687 const auto len
= snprintf(qvalbuf
, sizeof(qvalbuf
), "\"%.*s\"",
688 static_cast<int>(val
.length()), val
.data());
689 return dump_header(s
, name
, boost::string_ref(qvalbuf
, len
));
692 template <class ValueT
>
693 static inline void dump_header_if_nonempty(struct req_state
* s
,
694 const boost::string_ref
& name
,
695 const ValueT
& value
) {
696 if (name
.length() > 0 && value
.length() > 0) {
697 return dump_header(s
, name
, value
);
701 extern void dump_content_length(struct req_state
*s
, uint64_t len
);
702 extern int64_t parse_content_length(const char *content_length
);
703 extern void dump_etag(struct req_state
*s
,
704 const boost::string_ref
& etag
,
705 bool quoted
= false);
706 extern void dump_etag(struct req_state
*s
,
707 ceph::buffer::list
& bl_etag
,
708 bool quoted
= false);
709 extern void dump_epoch_header(struct req_state
*s
, const char *name
, real_time t
);
710 extern void dump_time_header(struct req_state
*s
, const char *name
, real_time t
);
711 extern void dump_last_modified(struct req_state
*s
, real_time t
);
712 extern void abort_early(struct req_state
* s
, RGWOp
* op
, int err
,
713 RGWHandler
* handler
);
714 extern void dump_range(struct req_state
* s
, uint64_t ofs
, uint64_t end
,
715 uint64_t total_size
);
716 extern void dump_continue(struct req_state
*s
);
717 extern void list_all_buckets_end(struct req_state
*s
);
718 extern void dump_time(struct req_state
*s
, const char *name
, real_time
*t
);
719 extern std::string
dump_time_to_str(const real_time
& t
);
720 extern void dump_bucket_from_state(struct req_state
*s
);
721 extern void dump_uri_from_state(struct req_state
*s
);
722 extern void dump_redirect(struct req_state
*s
, const string
& redirect
);
723 extern bool is_valid_url(const char *url
);
724 extern void dump_access_control(struct req_state
*s
, const char *origin
,
726 const char *hdr
, const char *exp_hdr
,
728 extern void dump_access_control(req_state
*s
, RGWOp
*op
);
730 extern int dump_body(struct req_state
* s
, const char* buf
, size_t len
);
731 extern int dump_body(struct req_state
* s
, /* const */ ceph::buffer::list
& bl
);
732 extern int dump_body(struct req_state
* s
, const std::string
& str
);
734 extern int recv_body(struct req_state
* s
, char* buf
, size_t max
);
736 #endif /* CEPH_RGW_REST_H */