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 RGWListBuckets_ObjStore
: public RGWListBuckets
{
166 RGWListBuckets_ObjStore() {}
167 ~RGWListBuckets_ObjStore() override
{}
170 class RGWGetUsage_ObjStore
: public RGWGetUsage
{
172 RGWGetUsage_ObjStore() {}
173 ~RGWGetUsage_ObjStore() override
{}
176 class RGWListBucket_ObjStore
: public RGWListBucket
{
178 RGWListBucket_ObjStore() {}
179 ~RGWListBucket_ObjStore() override
{}
182 class RGWStatAccount_ObjStore
: public RGWStatAccount
{
184 RGWStatAccount_ObjStore() {}
185 ~RGWStatAccount_ObjStore() override
{}
188 class RGWStatBucket_ObjStore
: public RGWStatBucket
{
190 RGWStatBucket_ObjStore() {}
191 ~RGWStatBucket_ObjStore() override
{}
194 class RGWCreateBucket_ObjStore
: public RGWCreateBucket
{
196 RGWCreateBucket_ObjStore() {}
197 ~RGWCreateBucket_ObjStore() override
{}
200 class RGWDeleteBucket_ObjStore
: public RGWDeleteBucket
{
202 RGWDeleteBucket_ObjStore() {}
203 ~RGWDeleteBucket_ObjStore() override
{}
206 class RGWPutObj_ObjStore
: public RGWPutObj
209 RGWPutObj_ObjStore() {}
210 ~RGWPutObj_ObjStore() override
{}
212 int verify_params() override
;
213 int get_params() override
;
214 int get_data(bufferlist
& bl
) override
;
216 int get_padding_last_aws4_chunk_encoded(bufferlist
&bl
, uint64_t chunk_size
);
219 class RGWPostObj_ObjStore
: public RGWPostObj
221 std::string boundary
;
224 struct post_part_field
{
226 std::map
<std::string
, std::string
> params
;
229 struct post_form_part
{
231 std::map
<std::string
, post_part_field
, ltstr_nocase
> fields
;
232 ceph::bufferlist data
;
236 using parts_collection_t
= \
237 std::map
<std::string
, post_form_part
, const ltstr_nocase
>;
240 ceph::bufferlist in_data
;
242 int read_with_boundary(ceph::bufferlist
& bl
,
245 bool& reached_boundary
,
248 int read_line(ceph::bufferlist
& bl
,
250 bool& reached_boundary
,
253 int read_data(ceph::bufferlist
& bl
,
255 bool& reached_boundary
,
258 int read_form_part_header(struct post_form_part
*part
, bool& done
);
260 int get_params() override
;
262 static int parse_part_field(const std::string
& line
,
263 std::string
& field_name
, /* out */
264 post_part_field
& field
); /* out */
266 static void parse_boundary_params(const std::string
& params_str
,
268 std::map
<std::string
, std::string
>& params
);
270 static bool part_str(parts_collection_t
& parts
,
271 const std::string
& name
,
274 static std::string
get_part_str(parts_collection_t
& parts
,
275 const std::string
& name
,
276 const std::string
& def_val
= std::string());
278 static bool part_bl(parts_collection_t
& parts
,
279 const std::string
& name
,
280 ceph::bufferlist
*pbl
);
283 RGWPostObj_ObjStore() {}
284 ~RGWPostObj_ObjStore() override
{}
286 int verify_params() override
;
290 class RGWPutMetadataAccount_ObjStore
: public RGWPutMetadataAccount
293 RGWPutMetadataAccount_ObjStore() {}
294 ~RGWPutMetadataAccount_ObjStore() override
{}
297 class RGWPutMetadataBucket_ObjStore
: public RGWPutMetadataBucket
300 RGWPutMetadataBucket_ObjStore() {}
301 ~RGWPutMetadataBucket_ObjStore() override
{}
304 class RGWPutMetadataObject_ObjStore
: public RGWPutMetadataObject
307 RGWPutMetadataObject_ObjStore() {}
308 ~RGWPutMetadataObject_ObjStore() override
{}
311 class RGWDeleteObj_ObjStore
: public RGWDeleteObj
{
313 RGWDeleteObj_ObjStore() {}
314 ~RGWDeleteObj_ObjStore() override
{}
317 class RGWGetCrossDomainPolicy_ObjStore
: public RGWGetCrossDomainPolicy
{
319 RGWGetCrossDomainPolicy_ObjStore() = default;
320 ~RGWGetCrossDomainPolicy_ObjStore() override
= default;
323 class RGWGetHealthCheck_ObjStore
: public RGWGetHealthCheck
{
325 RGWGetHealthCheck_ObjStore() = default;
326 ~RGWGetHealthCheck_ObjStore() override
= default;
329 class RGWCopyObj_ObjStore
: public RGWCopyObj
{
331 RGWCopyObj_ObjStore() {}
332 ~RGWCopyObj_ObjStore() override
{}
335 class RGWGetACLs_ObjStore
: public RGWGetACLs
{
337 RGWGetACLs_ObjStore() {}
338 ~RGWGetACLs_ObjStore() override
{}
341 class RGWPutACLs_ObjStore
: public RGWPutACLs
{
343 RGWPutACLs_ObjStore() {}
344 ~RGWPutACLs_ObjStore() override
{}
346 int get_params() override
;
349 class RGWGetLC_ObjStore
: public RGWGetLC
{
351 RGWGetLC_ObjStore() {}
352 ~RGWGetLC_ObjStore() override
{}
355 class RGWPutLC_ObjStore
: public RGWPutLC
{
357 RGWPutLC_ObjStore() {}
358 ~RGWPutLC_ObjStore() override
{}
360 int get_params() override
;
363 class RGWDeleteLC_ObjStore
: public RGWDeleteLC
{
365 RGWDeleteLC_ObjStore() {}
366 ~RGWDeleteLC_ObjStore() override
{}
370 class RGWGetCORS_ObjStore
: public RGWGetCORS
{
372 RGWGetCORS_ObjStore() {}
373 ~RGWGetCORS_ObjStore() override
{}
376 class RGWPutCORS_ObjStore
: public RGWPutCORS
{
378 RGWPutCORS_ObjStore() {}
379 ~RGWPutCORS_ObjStore() override
{}
382 class RGWDeleteCORS_ObjStore
: public RGWDeleteCORS
{
384 RGWDeleteCORS_ObjStore() {}
385 ~RGWDeleteCORS_ObjStore() override
{}
388 class RGWOptionsCORS_ObjStore
: public RGWOptionsCORS
{
390 RGWOptionsCORS_ObjStore() {}
391 ~RGWOptionsCORS_ObjStore() override
{}
394 class RGWInitMultipart_ObjStore
: public RGWInitMultipart
{
396 RGWInitMultipart_ObjStore() {}
397 ~RGWInitMultipart_ObjStore() override
{}
400 class RGWCompleteMultipart_ObjStore
: public RGWCompleteMultipart
{
402 RGWCompleteMultipart_ObjStore() {}
403 ~RGWCompleteMultipart_ObjStore() override
{}
405 int get_params() override
;
408 class RGWAbortMultipart_ObjStore
: public RGWAbortMultipart
{
410 RGWAbortMultipart_ObjStore() {}
411 ~RGWAbortMultipart_ObjStore() override
{}
414 class RGWListMultipart_ObjStore
: public RGWListMultipart
{
416 RGWListMultipart_ObjStore() {}
417 ~RGWListMultipart_ObjStore() override
{}
419 int get_params() override
;
422 class RGWListBucketMultiparts_ObjStore
: public RGWListBucketMultiparts
{
424 RGWListBucketMultiparts_ObjStore() {}
425 ~RGWListBucketMultiparts_ObjStore() override
{}
427 int get_params() override
;
430 class RGWBulkDelete_ObjStore
: public RGWBulkDelete
{
432 RGWBulkDelete_ObjStore() {}
433 ~RGWBulkDelete_ObjStore() override
{}
436 class RGWBulkUploadOp_ObjStore
: public RGWBulkUploadOp
{
438 RGWBulkUploadOp_ObjStore() = default;
439 ~RGWBulkUploadOp_ObjStore() = default;
442 class RGWDeleteMultiObj_ObjStore
: public RGWDeleteMultiObj
{
444 RGWDeleteMultiObj_ObjStore() {}
445 ~RGWDeleteMultiObj_ObjStore() override
{}
447 int get_params() override
;
450 class RGWInfo_ObjStore
: public RGWInfo
{
452 RGWInfo_ObjStore() = default;
453 ~RGWInfo_ObjStore() override
= default;
456 class RGWRESTOp
: public RGWOp
{
459 RGWRESTFlusher flusher
;
461 RGWRESTOp() : http_ret(0) {}
462 void init(RGWRados
*store
, struct req_state
*s
,
463 RGWHandler
*dialect_handler
) override
{
464 RGWOp::init(store
, s
, dialect_handler
);
465 flusher
.init(s
, this);
467 void send_response() override
;
468 virtual int check_caps(RGWUserCaps
& caps
)
469 { return -EPERM
; } /* should to be implemented! */
470 int verify_permission() override
;
473 class RGWHandler_REST
: public RGWHandler
{
476 virtual bool is_obj_update_op() { return false; }
477 virtual RGWOp
*op_get() { return NULL
; }
478 virtual RGWOp
*op_put() { return NULL
; }
479 virtual RGWOp
*op_delete() { return NULL
; }
480 virtual RGWOp
*op_head() { return NULL
; }
481 virtual RGWOp
*op_post() { return NULL
; }
482 virtual RGWOp
*op_copy() { return NULL
; }
483 virtual RGWOp
*op_options() { return NULL
; }
485 static int allocate_formatter(struct req_state
*s
, int default_formatter
,
488 static constexpr int MAX_BUCKET_NAME_LEN
= 255;
489 static constexpr int MAX_OBJ_NAME_LEN
= 1024;
492 ~RGWHandler_REST() override
{}
494 static int validate_tenant_name(const string
& bucket
);
495 static int validate_bucket_name(const string
& bucket
);
496 static int validate_object_name(const string
& object
);
498 int init_permissions(RGWOp
* op
) override
;
499 int read_permissions(RGWOp
* op
) override
;
501 virtual RGWOp
* get_op(RGWRados
* store
);
502 virtual void put_op(RGWOp
* op
);
505 class RGWHandler_REST_SWIFT
;
506 class RGWHandler_SWIFT_Auth
;
507 class RGWHandler_REST_S3
;
512 class StrategyRegistry
;
521 std::map
<std::string
, RGWRESTMgr
*> resource_mgrs
;
522 std::multimap
<size_t, std::string
> resources_by_size
;
523 RGWRESTMgr
* default_mgr
;
525 virtual RGWRESTMgr
* get_resource_mgr(struct req_state
* s
,
526 const std::string
& uri
,
527 std::string
* out_uri
);
529 virtual RGWRESTMgr
* get_resource_mgr_as_default(struct req_state
* const s
,
530 const std::string
& uri
,
531 std::string
* our_uri
) {
538 default_mgr(nullptr) {
540 virtual ~RGWRESTMgr();
542 void register_resource(std::string resource
, RGWRESTMgr
* mgr
);
543 void register_default_mgr(RGWRESTMgr
* mgr
);
545 virtual RGWRESTMgr
* get_manager(struct req_state
* const s
,
546 /* Prefix to be concatenated with @uri
547 * during the lookup. */
548 const std::string
& frontend_prefix
,
549 const std::string
& uri
,
550 std::string
* out_uri
) final
{
551 return get_resource_mgr(s
, frontend_prefix
+ uri
, out_uri
);
554 virtual RGWHandler_REST
* get_handler(
555 struct req_state
* const s
,
556 const rgw::auth::StrategyRegistry
& auth_registry
,
557 const std::string
& frontend_prefix
562 virtual void put_handler(RGWHandler_REST
* const handler
) {
566 void set_logging(bool _should_log
) {
567 should_log
= _should_log
;
570 bool get_logging() const {
579 using x_header
= basic_sstring
<char, uint16_t, 32>;
580 boost::container::flat_set
<x_header
> x_headers
;
583 static int preprocess(struct req_state
*s
, rgw::io::BasicClient
* rio
);
586 RGWHandler_REST
*get_handler(RGWRados
*store
,
588 const rgw::auth::StrategyRegistry
& auth_registry
,
589 const std::string
& frontend_prefix
,
594 RGWHandler
*get_handler(RGWRados
*store
, struct req_state
*s
,
595 RGWLibIO
*io
, RGWRESTMgr
**pmgr
,
599 void put_handler(RGWHandler_REST
*handler
) {
600 mgr
.put_handler(handler
);
603 void register_resource(string resource
, RGWRESTMgr
*m
,
604 bool register_empty
= false) {
605 if (!register_empty
&& resource
.empty())
608 mgr
.register_resource(resource
, m
);
611 void register_default_mgr(RGWRESTMgr
*m
) {
612 mgr
.register_default_mgr(m
);
615 void register_x_headers(const std::string
& headers
);
617 bool log_x_headers(void) {
618 return (x_headers
.size() > 0);
621 bool log_x_header(const std::string
& header
) {
622 return (x_headers
.find(header
) != x_headers
.end());
626 static constexpr int64_t NO_CONTENT_LENGTH
= -1;
627 static constexpr int64_t CHUNKED_TRANSFER_ENCODING
= -2;
629 extern void set_req_state_err(struct rgw_err
&err
, int err_no
, int prot_flags
);
630 extern void set_req_state_err(struct req_state
*s
, int err_no
);
631 extern void dump_errno(int http_ret
, string
& out
);
632 extern void dump_errno(const struct rgw_err
&err
, string
& out
);
633 extern void dump_errno(struct req_state
*s
);
634 extern void dump_errno(struct req_state
*s
, int http_ret
);
635 extern void end_header(struct req_state
*s
,
637 const char *content_type
= nullptr,
638 const int64_t proposed_content_length
=
640 bool force_content_type
= false,
641 bool force_no_error
= false);
642 extern void dump_start(struct req_state
*s
);
643 extern void list_all_buckets_start(struct req_state
*s
);
644 extern void dump_owner(struct req_state
*s
, const rgw_user
& id
, string
& name
,
645 const char *section
= NULL
);
646 extern void dump_header(struct req_state
* s
,
647 const boost::string_ref
& name
,
648 const boost::string_ref
& val
);
649 extern void dump_header(struct req_state
* s
,
650 const boost::string_ref
& name
,
651 ceph::buffer::list
& bl
);
652 extern void dump_header(struct req_state
* s
,
653 const boost::string_ref
& name
,
655 extern void dump_header(struct req_state
* s
,
656 const boost::string_ref
& name
,
658 template <class... Args
>
659 static inline void dump_header_prefixed(struct req_state
* s
,
660 const boost::string_ref
& name_prefix
,
661 const boost::string_ref
& name
,
663 char full_name_buf
[name_prefix
.size() + name
.size() + 1];
664 const auto len
= snprintf(full_name_buf
, sizeof(full_name_buf
), "%.*s%.*s",
665 static_cast<int>(name_prefix
.length()),
667 static_cast<int>(name
.length()),
669 boost::string_ref
full_name(full_name_buf
, len
);
670 return dump_header(s
, std::move(full_name
), std::forward
<Args
>(args
)...);
673 template <class... Args
>
674 static inline void dump_header_quoted(struct req_state
* s
,
675 const boost::string_ref
& name
,
676 const boost::string_ref
& val
) {
677 /* We need two extra bytes for quotes. */
678 char qvalbuf
[val
.size() + 2 + 1];
679 const auto len
= snprintf(qvalbuf
, sizeof(qvalbuf
), "\"%.*s\"",
680 static_cast<int>(val
.length()), val
.data());
681 return dump_header(s
, name
, boost::string_ref(qvalbuf
, len
));
684 template <class ValueT
>
685 static inline void dump_header_if_nonempty(struct req_state
* s
,
686 const boost::string_ref
& name
,
687 const ValueT
& value
) {
688 if (name
.length() > 0 && value
.length() > 0) {
689 return dump_header(s
, name
, value
);
693 extern void dump_content_length(struct req_state
*s
, uint64_t len
);
694 extern void dump_etag(struct req_state
*s
,
695 const boost::string_ref
& etag
,
696 bool quoted
= false);
697 extern void dump_etag(struct req_state
*s
,
698 ceph::buffer::list
& bl_etag
,
699 bool quoted
= false);
700 extern void dump_epoch_header(struct req_state
*s
, const char *name
, real_time t
);
701 extern void dump_time_header(struct req_state
*s
, const char *name
, real_time t
);
702 extern void dump_last_modified(struct req_state
*s
, real_time t
);
703 extern void abort_early(struct req_state
* s
, RGWOp
* op
, int err
,
704 RGWHandler
* handler
);
705 extern void dump_range(struct req_state
* s
, uint64_t ofs
, uint64_t end
,
706 uint64_t total_size
);
707 extern void dump_continue(struct req_state
*s
);
708 extern void list_all_buckets_end(struct req_state
*s
);
709 extern void dump_time(struct req_state
*s
, const char *name
, real_time
*t
);
710 extern std::string
dump_time_to_str(const real_time
& t
);
711 extern void dump_bucket_from_state(struct req_state
*s
);
712 extern void dump_uri_from_state(struct req_state
*s
);
713 extern void dump_redirect(struct req_state
*s
, const string
& redirect
);
714 extern bool is_valid_url(const char *url
);
715 extern void dump_access_control(struct req_state
*s
, const char *origin
,
717 const char *hdr
, const char *exp_hdr
,
719 extern void dump_access_control(req_state
*s
, RGWOp
*op
);
721 extern int dump_body(struct req_state
* s
, const char* buf
, size_t len
);
722 extern int dump_body(struct req_state
* s
, /* const */ ceph::buffer::list
& bl
);
723 extern int dump_body(struct req_state
* s
, const std::string
& str
);
725 extern int recv_body(struct req_state
* s
, char* buf
, size_t max
);
727 #endif /* CEPH_RGW_REST_H */