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
;
217 class RGWPostObj_ObjStore
: public RGWPostObj
219 std::string boundary
;
222 struct post_part_field
{
224 std::map
<std::string
, std::string
> params
;
227 struct post_form_part
{
229 std::map
<std::string
, post_part_field
, ltstr_nocase
> fields
;
230 ceph::bufferlist data
;
234 using parts_collection_t
= \
235 std::map
<std::string
, post_form_part
, const ltstr_nocase
>;
238 ceph::bufferlist in_data
;
240 int read_with_boundary(ceph::bufferlist
& bl
,
243 bool& reached_boundary
,
246 int read_line(ceph::bufferlist
& bl
,
248 bool& reached_boundary
,
251 int read_data(ceph::bufferlist
& bl
,
253 bool& reached_boundary
,
256 int read_form_part_header(struct post_form_part
*part
, bool& done
);
258 int get_params() override
;
260 static int parse_part_field(const std::string
& line
,
261 std::string
& field_name
, /* out */
262 post_part_field
& field
); /* out */
264 static void parse_boundary_params(const std::string
& params_str
,
266 std::map
<std::string
, std::string
>& params
);
268 static bool part_str(parts_collection_t
& parts
,
269 const std::string
& name
,
272 static std::string
get_part_str(parts_collection_t
& parts
,
273 const std::string
& name
,
274 const std::string
& def_val
= std::string());
276 static bool part_bl(parts_collection_t
& parts
,
277 const std::string
& name
,
278 ceph::bufferlist
*pbl
);
281 RGWPostObj_ObjStore() {}
282 ~RGWPostObj_ObjStore() override
{}
284 int verify_params() override
;
288 class RGWPutMetadataAccount_ObjStore
: public RGWPutMetadataAccount
291 RGWPutMetadataAccount_ObjStore() {}
292 ~RGWPutMetadataAccount_ObjStore() override
{}
295 class RGWPutMetadataBucket_ObjStore
: public RGWPutMetadataBucket
298 RGWPutMetadataBucket_ObjStore() {}
299 ~RGWPutMetadataBucket_ObjStore() override
{}
302 class RGWPutMetadataObject_ObjStore
: public RGWPutMetadataObject
305 RGWPutMetadataObject_ObjStore() {}
306 ~RGWPutMetadataObject_ObjStore() override
{}
309 class RGWDeleteObj_ObjStore
: public RGWDeleteObj
{
311 RGWDeleteObj_ObjStore() {}
312 ~RGWDeleteObj_ObjStore() override
{}
315 class RGWGetCrossDomainPolicy_ObjStore
: public RGWGetCrossDomainPolicy
{
317 RGWGetCrossDomainPolicy_ObjStore() = default;
318 ~RGWGetCrossDomainPolicy_ObjStore() override
= default;
321 class RGWGetHealthCheck_ObjStore
: public RGWGetHealthCheck
{
323 RGWGetHealthCheck_ObjStore() = default;
324 ~RGWGetHealthCheck_ObjStore() override
= default;
327 class RGWCopyObj_ObjStore
: public RGWCopyObj
{
329 RGWCopyObj_ObjStore() {}
330 ~RGWCopyObj_ObjStore() override
{}
333 class RGWGetACLs_ObjStore
: public RGWGetACLs
{
335 RGWGetACLs_ObjStore() {}
336 ~RGWGetACLs_ObjStore() override
{}
339 class RGWPutACLs_ObjStore
: public RGWPutACLs
{
341 RGWPutACLs_ObjStore() {}
342 ~RGWPutACLs_ObjStore() override
{}
344 int get_params() override
;
347 class RGWGetLC_ObjStore
: public RGWGetLC
{
349 RGWGetLC_ObjStore() {}
350 ~RGWGetLC_ObjStore() override
{}
353 class RGWPutLC_ObjStore
: public RGWPutLC
{
355 RGWPutLC_ObjStore() {}
356 ~RGWPutLC_ObjStore() override
{}
358 int get_params() override
;
361 class RGWDeleteLC_ObjStore
: public RGWDeleteLC
{
363 RGWDeleteLC_ObjStore() {}
364 ~RGWDeleteLC_ObjStore() override
{}
368 class RGWGetCORS_ObjStore
: public RGWGetCORS
{
370 RGWGetCORS_ObjStore() {}
371 ~RGWGetCORS_ObjStore() override
{}
374 class RGWPutCORS_ObjStore
: public RGWPutCORS
{
376 RGWPutCORS_ObjStore() {}
377 ~RGWPutCORS_ObjStore() override
{}
380 class RGWDeleteCORS_ObjStore
: public RGWDeleteCORS
{
382 RGWDeleteCORS_ObjStore() {}
383 ~RGWDeleteCORS_ObjStore() override
{}
386 class RGWOptionsCORS_ObjStore
: public RGWOptionsCORS
{
388 RGWOptionsCORS_ObjStore() {}
389 ~RGWOptionsCORS_ObjStore() override
{}
392 class RGWInitMultipart_ObjStore
: public RGWInitMultipart
{
394 RGWInitMultipart_ObjStore() {}
395 ~RGWInitMultipart_ObjStore() override
{}
398 class RGWCompleteMultipart_ObjStore
: public RGWCompleteMultipart
{
400 RGWCompleteMultipart_ObjStore() {}
401 ~RGWCompleteMultipart_ObjStore() override
{}
403 int get_params() override
;
406 class RGWAbortMultipart_ObjStore
: public RGWAbortMultipart
{
408 RGWAbortMultipart_ObjStore() {}
409 ~RGWAbortMultipart_ObjStore() override
{}
412 class RGWListMultipart_ObjStore
: public RGWListMultipart
{
414 RGWListMultipart_ObjStore() {}
415 ~RGWListMultipart_ObjStore() override
{}
417 int get_params() override
;
420 class RGWListBucketMultiparts_ObjStore
: public RGWListBucketMultiparts
{
422 RGWListBucketMultiparts_ObjStore() {}
423 ~RGWListBucketMultiparts_ObjStore() override
{}
425 int get_params() override
;
428 class RGWBulkDelete_ObjStore
: public RGWBulkDelete
{
430 RGWBulkDelete_ObjStore() {}
431 ~RGWBulkDelete_ObjStore() override
{}
434 class RGWBulkUploadOp_ObjStore
: public RGWBulkUploadOp
{
436 RGWBulkUploadOp_ObjStore() = default;
437 ~RGWBulkUploadOp_ObjStore() = default;
440 class RGWDeleteMultiObj_ObjStore
: public RGWDeleteMultiObj
{
442 RGWDeleteMultiObj_ObjStore() {}
443 ~RGWDeleteMultiObj_ObjStore() override
{}
445 int get_params() override
;
448 class RGWInfo_ObjStore
: public RGWInfo
{
450 RGWInfo_ObjStore() = default;
451 ~RGWInfo_ObjStore() override
= default;
454 class RGWRESTOp
: public RGWOp
{
457 RGWRESTFlusher flusher
;
459 RGWRESTOp() : http_ret(0) {}
460 void init(RGWRados
*store
, struct req_state
*s
,
461 RGWHandler
*dialect_handler
) override
{
462 RGWOp::init(store
, s
, dialect_handler
);
463 flusher
.init(s
, this);
465 void send_response() override
;
466 virtual int check_caps(RGWUserCaps
& caps
)
467 { return -EPERM
; } /* should to be implemented! */
468 int verify_permission() override
;
471 class RGWHandler_REST
: public RGWHandler
{
474 virtual bool is_obj_update_op() { return false; }
475 virtual RGWOp
*op_get() { return NULL
; }
476 virtual RGWOp
*op_put() { return NULL
; }
477 virtual RGWOp
*op_delete() { return NULL
; }
478 virtual RGWOp
*op_head() { return NULL
; }
479 virtual RGWOp
*op_post() { return NULL
; }
480 virtual RGWOp
*op_copy() { return NULL
; }
481 virtual RGWOp
*op_options() { return NULL
; }
483 static int allocate_formatter(struct req_state
*s
, int default_formatter
,
486 static constexpr int MAX_BUCKET_NAME_LEN
= 255;
487 static constexpr int MAX_OBJ_NAME_LEN
= 1024;
490 ~RGWHandler_REST() override
{}
492 static int validate_tenant_name(const string
& bucket
);
493 static int validate_bucket_name(const string
& bucket
);
494 static int validate_object_name(const string
& object
);
496 int init_permissions(RGWOp
* op
) override
;
497 int read_permissions(RGWOp
* op
) override
;
499 virtual RGWOp
* get_op(RGWRados
* store
);
500 virtual void put_op(RGWOp
* op
);
503 class RGWHandler_REST_SWIFT
;
504 class RGWHandler_SWIFT_Auth
;
505 class RGWHandler_REST_S3
;
510 class StrategyRegistry
;
519 std::map
<std::string
, RGWRESTMgr
*> resource_mgrs
;
520 std::multimap
<size_t, std::string
> resources_by_size
;
521 RGWRESTMgr
* default_mgr
;
523 virtual RGWRESTMgr
* get_resource_mgr(struct req_state
* s
,
524 const std::string
& uri
,
525 std::string
* out_uri
);
527 virtual RGWRESTMgr
* get_resource_mgr_as_default(struct req_state
* const s
,
528 const std::string
& uri
,
529 std::string
* our_uri
) {
536 default_mgr(nullptr) {
538 virtual ~RGWRESTMgr();
540 void register_resource(std::string resource
, RGWRESTMgr
* mgr
);
541 void register_default_mgr(RGWRESTMgr
* mgr
);
543 virtual RGWRESTMgr
* get_manager(struct req_state
* const s
,
544 /* Prefix to be concatenated with @uri
545 * during the lookup. */
546 const std::string
& frontend_prefix
,
547 const std::string
& uri
,
548 std::string
* out_uri
) final
{
549 return get_resource_mgr(s
, frontend_prefix
+ uri
, out_uri
);
552 virtual RGWHandler_REST
* get_handler(
553 struct req_state
* const s
,
554 const rgw::auth::StrategyRegistry
& auth_registry
,
555 const std::string
& frontend_prefix
560 virtual void put_handler(RGWHandler_REST
* const handler
) {
564 void set_logging(bool _should_log
) {
565 should_log
= _should_log
;
568 bool get_logging() const {
577 using x_header
= basic_sstring
<char, uint16_t, 32>;
578 boost::container::flat_set
<x_header
> x_headers
;
581 static int preprocess(struct req_state
*s
, rgw::io::BasicClient
* rio
);
584 RGWHandler_REST
*get_handler(RGWRados
*store
,
586 const rgw::auth::StrategyRegistry
& auth_registry
,
587 const std::string
& frontend_prefix
,
592 RGWHandler
*get_handler(RGWRados
*store
, struct req_state
*s
,
593 RGWLibIO
*io
, RGWRESTMgr
**pmgr
,
597 void put_handler(RGWHandler_REST
*handler
) {
598 mgr
.put_handler(handler
);
601 void register_resource(string resource
, RGWRESTMgr
*m
,
602 bool register_empty
= false) {
603 if (!register_empty
&& resource
.empty())
606 mgr
.register_resource(resource
, m
);
609 void register_default_mgr(RGWRESTMgr
*m
) {
610 mgr
.register_default_mgr(m
);
613 void register_x_headers(const std::string
& headers
);
615 bool log_x_headers(void) {
616 return (x_headers
.size() > 0);
619 bool log_x_header(const std::string
& header
) {
620 return (x_headers
.find(header
) != x_headers
.end());
624 static constexpr int64_t NO_CONTENT_LENGTH
= -1;
625 static constexpr int64_t CHUNKED_TRANSFER_ENCODING
= -2;
627 extern void dump_errno(int http_ret
, string
& out
);
628 extern void dump_errno(const struct rgw_err
&err
, string
& out
);
629 extern void dump_errno(struct req_state
*s
);
630 extern void dump_errno(struct req_state
*s
, int http_ret
);
631 extern void end_header(struct req_state
*s
,
633 const char *content_type
= nullptr,
634 const int64_t proposed_content_length
=
636 bool force_content_type
= false,
637 bool force_no_error
= false);
638 extern void dump_start(struct req_state
*s
);
639 extern void list_all_buckets_start(struct req_state
*s
);
640 extern void dump_owner(struct req_state
*s
, const rgw_user
& id
, string
& name
,
641 const char *section
= NULL
);
642 extern void dump_header(struct req_state
* s
,
643 const boost::string_ref
& name
,
644 const boost::string_ref
& val
);
645 extern void dump_header(struct req_state
* s
,
646 const boost::string_ref
& name
,
647 ceph::buffer::list
& bl
);
648 extern void dump_header(struct req_state
* s
,
649 const boost::string_ref
& name
,
651 extern void dump_header(struct req_state
* s
,
652 const boost::string_ref
& name
,
654 template <class... Args
>
655 static inline void dump_header_prefixed(struct req_state
* s
,
656 const boost::string_ref
& name_prefix
,
657 const boost::string_ref
& name
,
659 char full_name_buf
[name_prefix
.size() + name
.size() + 1];
660 const auto len
= snprintf(full_name_buf
, sizeof(full_name_buf
), "%.*s%.*s",
661 static_cast<int>(name_prefix
.length()),
663 static_cast<int>(name
.length()),
665 boost::string_ref
full_name(full_name_buf
, len
);
666 return dump_header(s
, std::move(full_name
), std::forward
<Args
>(args
)...);
669 template <class... Args
>
670 static inline void dump_header_quoted(struct req_state
* s
,
671 const boost::string_ref
& name
,
672 const boost::string_ref
& val
) {
673 /* We need two extra bytes for quotes. */
674 char qvalbuf
[val
.size() + 2 + 1];
675 const auto len
= snprintf(qvalbuf
, sizeof(qvalbuf
), "\"%.*s\"",
676 static_cast<int>(val
.length()), val
.data());
677 return dump_header(s
, name
, boost::string_ref(qvalbuf
, len
));
680 template <class ValueT
>
681 static inline void dump_header_if_nonempty(struct req_state
* s
,
682 const boost::string_ref
& name
,
683 const ValueT
& value
) {
684 if (name
.length() > 0 && value
.length() > 0) {
685 return dump_header(s
, name
, value
);
689 extern void dump_content_length(struct req_state
*s
, uint64_t len
);
690 extern int64_t parse_content_length(const char *content_length
);
691 extern void dump_etag(struct req_state
*s
,
692 const boost::string_ref
& etag
,
693 bool quoted
= false);
694 extern void dump_etag(struct req_state
*s
,
695 ceph::buffer::list
& bl_etag
,
696 bool quoted
= false);
697 extern void dump_epoch_header(struct req_state
*s
, const char *name
, real_time t
);
698 extern void dump_time_header(struct req_state
*s
, const char *name
, real_time t
);
699 extern void dump_last_modified(struct req_state
*s
, real_time t
);
700 extern void abort_early(struct req_state
* s
, RGWOp
* op
, int err
,
701 RGWHandler
* handler
);
702 extern void dump_range(struct req_state
* s
, uint64_t ofs
, uint64_t end
,
703 uint64_t total_size
);
704 extern void dump_continue(struct req_state
*s
);
705 extern void list_all_buckets_end(struct req_state
*s
);
706 extern void dump_time(struct req_state
*s
, const char *name
, real_time
*t
);
707 extern std::string
dump_time_to_str(const real_time
& t
);
708 extern void dump_bucket_from_state(struct req_state
*s
);
709 extern void dump_uri_from_state(struct req_state
*s
);
710 extern void dump_redirect(struct req_state
*s
, const string
& redirect
);
711 extern bool is_valid_url(const char *url
);
712 extern void dump_access_control(struct req_state
*s
, const char *origin
,
714 const char *hdr
, const char *exp_hdr
,
716 extern void dump_access_control(req_state
*s
, RGWOp
*op
);
718 extern int dump_body(struct req_state
* s
, const char* buf
, size_t len
);
719 extern int dump_body(struct req_state
* s
, /* const */ ceph::buffer::list
& bl
);
720 extern int dump_body(struct req_state
* s
, const std::string
& str
);
722 extern int recv_body(struct req_state
* s
, char* buf
, size_t max
);
724 #endif /* CEPH_RGW_REST_H */