]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest.h
import quincy 17.2.0
[ceph.git] / ceph / src / rgw / rgw_rest.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #pragma once
5
6 #define TIME_BUF_SIZE 128
7
8 #include <string_view>
9 #include <boost/container/flat_set.hpp>
10 #include "common/sstring.hh"
11 #include "common/ceph_json.h"
12 #include "include/ceph_assert.h" /* needed because of common/ceph_json.h */
13 #include "rgw_op.h"
14 #include "rgw_formats.h"
15 #include "rgw_client_io.h"
16
17 extern std::map<std::string, std::string> rgw_to_http_attrs;
18
19 extern void rgw_rest_init(CephContext *cct, const RGWZoneGroup& zone_group);
20
21 extern void rgw_flush_formatter_and_reset(struct req_state *s,
22 ceph::Formatter *formatter);
23
24 extern void rgw_flush_formatter(struct req_state *s,
25 ceph::Formatter *formatter);
26
27 inline std::string_view rgw_sanitized_hdrval(ceph::buffer::list& raw)
28 {
29 /* std::string and thus std::string_view ARE OBLIGED to carry multiple
30 * 0x00 and count them to the length of a string. We need to take that
31 * into consideration and sanitize the size of a ceph::buffer::list used
32 * to store metadata values (x-amz-meta-*, X-Container-Meta-*, etags).
33 * Otherwise we might send 0x00 to clients. */
34 const char* const data = raw.c_str();
35 size_t len = raw.length();
36
37 if (len && data[len - 1] == '\0') {
38 /* That's the case - the null byte has been included at the last position
39 * of the bufferlist. We need to restore the proper string length we'll
40 * pass to string_ref. */
41 len--;
42 }
43
44 return std::string_view(data, len);
45 }
46
47 template <class T>
48 std::tuple<int, bufferlist > rgw_rest_get_json_input_keep_data(CephContext *cct, req_state *s, T& out, uint64_t max_len)
49 {
50 int rv = 0;
51 bufferlist data;
52 std::tie(rv, data) = rgw_rest_read_all_input(s, max_len);
53 if (rv < 0) {
54 return std::make_tuple(rv, std::move(data));
55 }
56
57 if (!data.length()) {
58 return std::make_tuple(-EINVAL, std::move(data));
59 }
60
61 JSONParser parser;
62
63 if (!parser.parse(data.c_str(), data.length())) {
64 return std::make_tuple(-EINVAL, std::move(data));
65 }
66
67 try {
68 decode_json_obj(out, &parser);
69 } catch (JSONDecoder::err& e) {
70 return std::make_tuple(-EINVAL, std::move(data));
71 }
72
73 return std::make_tuple(0, std::move(data));
74 }
75
76 class RESTArgs {
77 public:
78 static int get_string(struct req_state *s, const std::string& name,
79 const std::string& def_val, std::string *val,
80 bool *existed = NULL);
81 static int get_uint64(struct req_state *s, const std::string& name,
82 uint64_t def_val, uint64_t *val, bool *existed = NULL);
83 static int get_int64(struct req_state *s, const std::string& name,
84 int64_t def_val, int64_t *val, bool *existed = NULL);
85 static int get_uint32(struct req_state *s, const std::string& name,
86 uint32_t def_val, uint32_t *val, bool *existed = NULL);
87 static int get_int32(struct req_state *s, const std::string& name,
88 int32_t def_val, int32_t *val, bool *existed = NULL);
89 static int get_time(struct req_state *s, const std::string& name,
90 const utime_t& def_val, utime_t *val,
91 bool *existed = NULL);
92 static int get_epoch(struct req_state *s, const std::string& name,
93 uint64_t def_val, uint64_t *epoch,
94 bool *existed = NULL);
95 static int get_bool(struct req_state *s, const std::string& name, bool def_val,
96 bool *val, bool *existed = NULL);
97 };
98
99 class RGWRESTFlusher : public RGWFormatterFlusher {
100 struct req_state *s;
101 RGWOp *op;
102 protected:
103 void do_flush() override;
104 void do_start(int ret) override;
105 public:
106 RGWRESTFlusher(struct req_state *_s, RGWOp *_op) :
107 RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {}
108 RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {}
109
110 void init(struct req_state *_s, RGWOp *_op) {
111 s = _s;
112 op = _op;
113 set_formatter(s->formatter);
114 }
115 };
116
117 class RGWGetObj_ObjStore : public RGWGetObj
118 {
119 protected:
120 bool sent_header;
121 public:
122 RGWGetObj_ObjStore() : sent_header(false) {}
123
124 void init(rgw::sal::Store* store, struct req_state *s, RGWHandler *h) override {
125 RGWGetObj::init(store, s, h);
126 sent_header = false;
127 }
128
129 int get_params(optional_yield y) override;
130 };
131
132 class RGWGetObjTags_ObjStore : public RGWGetObjTags {
133 public:
134 RGWGetObjTags_ObjStore() {};
135 ~RGWGetObjTags_ObjStore() {};
136 };
137
138 class RGWPutObjTags_ObjStore: public RGWPutObjTags {
139 public:
140 RGWPutObjTags_ObjStore() {};
141 ~RGWPutObjTags_ObjStore() {};
142 };
143
144 class RGWGetBucketTags_ObjStore : public RGWGetBucketTags {
145 public:
146 RGWGetBucketTags_ObjStore() = default;
147 virtual ~RGWGetBucketTags_ObjStore() = default;
148 };
149
150 class RGWPutBucketTags_ObjStore: public RGWPutBucketTags {
151 public:
152 RGWPutBucketTags_ObjStore() = default;
153 virtual ~RGWPutBucketTags_ObjStore() = default;
154 };
155
156 class RGWGetBucketReplication_ObjStore : public RGWGetBucketReplication {
157 public:
158 RGWGetBucketReplication_ObjStore() {};
159 ~RGWGetBucketReplication_ObjStore() {};
160 };
161
162 class RGWPutBucketReplication_ObjStore: public RGWPutBucketReplication {
163 public:
164 RGWPutBucketReplication_ObjStore() = default;
165 virtual ~RGWPutBucketReplication_ObjStore() = default;
166 };
167
168 class RGWDeleteBucketReplication_ObjStore: public RGWDeleteBucketReplication {
169 public:
170 RGWDeleteBucketReplication_ObjStore() = default;
171 virtual ~RGWDeleteBucketReplication_ObjStore() = default;
172 };
173
174 class RGWListBuckets_ObjStore : public RGWListBuckets {
175 public:
176 RGWListBuckets_ObjStore() {}
177 ~RGWListBuckets_ObjStore() override {}
178 };
179
180 class RGWGetUsage_ObjStore : public RGWGetUsage {
181 public:
182 RGWGetUsage_ObjStore() {}
183 ~RGWGetUsage_ObjStore() override {}
184 };
185
186 class RGWListBucket_ObjStore : public RGWListBucket {
187 public:
188 RGWListBucket_ObjStore() {}
189 ~RGWListBucket_ObjStore() override {}
190 };
191
192 class RGWStatAccount_ObjStore : public RGWStatAccount {
193 public:
194 RGWStatAccount_ObjStore() {}
195 ~RGWStatAccount_ObjStore() override {}
196 };
197
198 class RGWStatBucket_ObjStore : public RGWStatBucket {
199 public:
200 RGWStatBucket_ObjStore() {}
201 ~RGWStatBucket_ObjStore() override {}
202 };
203
204 class RGWCreateBucket_ObjStore : public RGWCreateBucket {
205 public:
206 RGWCreateBucket_ObjStore() {}
207 ~RGWCreateBucket_ObjStore() override {}
208 };
209
210 class RGWDeleteBucket_ObjStore : public RGWDeleteBucket {
211 public:
212 RGWDeleteBucket_ObjStore() {}
213 ~RGWDeleteBucket_ObjStore() override {}
214 };
215
216 class RGWPutObj_ObjStore : public RGWPutObj
217 {
218 public:
219 RGWPutObj_ObjStore() {}
220 ~RGWPutObj_ObjStore() override {}
221
222 int verify_params() override;
223 int get_params(optional_yield y) override;
224 int get_data(bufferlist& bl) override;
225 };
226
227 class RGWPostObj_ObjStore : public RGWPostObj
228 {
229 std::string boundary;
230
231 public:
232 struct post_part_field {
233 std::string val;
234 std::map<std::string, std::string> params;
235 };
236
237 struct post_form_part {
238 std::string name;
239 std::map<std::string, post_part_field, ltstr_nocase> fields;
240 ceph::bufferlist data;
241 };
242
243 protected:
244 using parts_collection_t = \
245 std::map<std::string, post_form_part, const ltstr_nocase>;
246
247 std::string err_msg;
248 ceph::bufferlist in_data;
249
250 int read_with_boundary(ceph::bufferlist& bl,
251 uint64_t max,
252 bool check_eol,
253 bool& reached_boundary,
254 bool& done);
255
256 int read_line(ceph::bufferlist& bl,
257 uint64_t max,
258 bool& reached_boundary,
259 bool& done);
260
261 int read_data(ceph::bufferlist& bl,
262 uint64_t max,
263 bool& reached_boundary,
264 bool& done);
265
266 int read_form_part_header(struct post_form_part *part, bool& done);
267
268 int get_params(optional_yield y) override;
269
270 static int parse_part_field(const std::string& line,
271 std::string& field_name, /* out */
272 post_part_field& field); /* out */
273
274 static void parse_boundary_params(const std::string& params_str,
275 std::string& first,
276 std::map<std::string, std::string>& params);
277
278 static bool part_str(parts_collection_t& parts,
279 const std::string& name,
280 std::string *val);
281
282 static std::string get_part_str(parts_collection_t& parts,
283 const std::string& name,
284 const std::string& def_val = std::string());
285
286 static bool part_bl(parts_collection_t& parts,
287 const std::string& name,
288 ceph::bufferlist *pbl);
289
290 public:
291 RGWPostObj_ObjStore() {}
292 ~RGWPostObj_ObjStore() override {}
293
294 int verify_params() override;
295 };
296
297
298 class RGWPutMetadataAccount_ObjStore : public RGWPutMetadataAccount
299 {
300 public:
301 RGWPutMetadataAccount_ObjStore() {}
302 ~RGWPutMetadataAccount_ObjStore() override {}
303 };
304
305 class RGWPutMetadataBucket_ObjStore : public RGWPutMetadataBucket
306 {
307 public:
308 RGWPutMetadataBucket_ObjStore() {}
309 ~RGWPutMetadataBucket_ObjStore() override {}
310 };
311
312 class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject
313 {
314 public:
315 RGWPutMetadataObject_ObjStore() {}
316 ~RGWPutMetadataObject_ObjStore() override {}
317 };
318
319 class RGWDeleteObj_ObjStore : public RGWDeleteObj {
320 public:
321 RGWDeleteObj_ObjStore() {}
322 ~RGWDeleteObj_ObjStore() override {}
323 };
324
325 class RGWGetCrossDomainPolicy_ObjStore : public RGWGetCrossDomainPolicy {
326 public:
327 RGWGetCrossDomainPolicy_ObjStore() = default;
328 ~RGWGetCrossDomainPolicy_ObjStore() override = default;
329 };
330
331 class RGWGetHealthCheck_ObjStore : public RGWGetHealthCheck {
332 public:
333 RGWGetHealthCheck_ObjStore() = default;
334 ~RGWGetHealthCheck_ObjStore() override = default;
335 };
336
337 class RGWCopyObj_ObjStore : public RGWCopyObj {
338 public:
339 RGWCopyObj_ObjStore() {}
340 ~RGWCopyObj_ObjStore() override {}
341 };
342
343 class RGWGetACLs_ObjStore : public RGWGetACLs {
344 public:
345 RGWGetACLs_ObjStore() {}
346 ~RGWGetACLs_ObjStore() override {}
347 };
348
349 class RGWPutACLs_ObjStore : public RGWPutACLs {
350 public:
351 RGWPutACLs_ObjStore() {}
352 ~RGWPutACLs_ObjStore() override {}
353
354 int get_params(optional_yield y) override;
355 };
356
357 class RGWGetLC_ObjStore : public RGWGetLC {
358 public:
359 RGWGetLC_ObjStore() {}
360 ~RGWGetLC_ObjStore() override {}
361 };
362
363 class RGWPutLC_ObjStore : public RGWPutLC {
364 public:
365 RGWPutLC_ObjStore() {}
366 ~RGWPutLC_ObjStore() override {}
367
368 int get_params(optional_yield y) override;
369 };
370
371 class RGWDeleteLC_ObjStore : public RGWDeleteLC {
372 public:
373 RGWDeleteLC_ObjStore() {}
374 ~RGWDeleteLC_ObjStore() override {}
375
376 };
377
378 class RGWGetCORS_ObjStore : public RGWGetCORS {
379 public:
380 RGWGetCORS_ObjStore() {}
381 ~RGWGetCORS_ObjStore() override {}
382 };
383
384 class RGWPutCORS_ObjStore : public RGWPutCORS {
385 public:
386 RGWPutCORS_ObjStore() {}
387 ~RGWPutCORS_ObjStore() override {}
388 };
389
390 class RGWDeleteCORS_ObjStore : public RGWDeleteCORS {
391 public:
392 RGWDeleteCORS_ObjStore() {}
393 ~RGWDeleteCORS_ObjStore() override {}
394 };
395
396 class RGWOptionsCORS_ObjStore : public RGWOptionsCORS {
397 public:
398 RGWOptionsCORS_ObjStore() {}
399 ~RGWOptionsCORS_ObjStore() override {}
400 };
401
402 class RGWGetBucketEncryption_ObjStore : public RGWGetBucketEncryption {
403 public:
404 RGWGetBucketEncryption_ObjStore() {}
405 ~RGWGetBucketEncryption_ObjStore() override {}
406 };
407
408 class RGWPutBucketEncryption_ObjStore : public RGWPutBucketEncryption {
409 public:
410 RGWPutBucketEncryption_ObjStore() {}
411 ~RGWPutBucketEncryption_ObjStore() override {}
412 };
413
414 class RGWDeleteBucketEncryption_ObjStore : public RGWDeleteBucketEncryption {
415 public:
416 RGWDeleteBucketEncryption_ObjStore() {}
417 ~RGWDeleteBucketEncryption_ObjStore() override {}
418 };
419
420 class RGWInitMultipart_ObjStore : public RGWInitMultipart {
421 public:
422 RGWInitMultipart_ObjStore() {}
423 ~RGWInitMultipart_ObjStore() override {}
424 };
425
426 class RGWCompleteMultipart_ObjStore : public RGWCompleteMultipart {
427 public:
428 RGWCompleteMultipart_ObjStore() {}
429 ~RGWCompleteMultipart_ObjStore() override {}
430
431 int get_params(optional_yield y) override;
432 };
433
434 class RGWAbortMultipart_ObjStore : public RGWAbortMultipart {
435 public:
436 RGWAbortMultipart_ObjStore() {}
437 ~RGWAbortMultipart_ObjStore() override {}
438 };
439
440 class RGWListMultipart_ObjStore : public RGWListMultipart {
441 public:
442 RGWListMultipart_ObjStore() {}
443 ~RGWListMultipart_ObjStore() override {}
444
445 int get_params(optional_yield y) override;
446 };
447
448 class RGWListBucketMultiparts_ObjStore : public RGWListBucketMultiparts {
449 public:
450 RGWListBucketMultiparts_ObjStore() {}
451 ~RGWListBucketMultiparts_ObjStore() override {}
452
453 int get_params(optional_yield y) override;
454 };
455
456 class RGWBulkDelete_ObjStore : public RGWBulkDelete {
457 public:
458 RGWBulkDelete_ObjStore() {}
459 ~RGWBulkDelete_ObjStore() override {}
460 };
461
462 class RGWBulkUploadOp_ObjStore : public RGWBulkUploadOp {
463 public:
464 RGWBulkUploadOp_ObjStore() = default;
465 ~RGWBulkUploadOp_ObjStore() = default;
466 };
467
468 class RGWDeleteMultiObj_ObjStore : public RGWDeleteMultiObj {
469 public:
470 RGWDeleteMultiObj_ObjStore() {}
471 ~RGWDeleteMultiObj_ObjStore() override {}
472
473 int get_params(optional_yield y) override;
474 };
475
476 class RGWInfo_ObjStore : public RGWInfo {
477 public:
478 RGWInfo_ObjStore() = default;
479 ~RGWInfo_ObjStore() override = default;
480 };
481
482 class RGWPutBucketObjectLock_ObjStore : public RGWPutBucketObjectLock {
483 public:
484 RGWPutBucketObjectLock_ObjStore() = default;
485 ~RGWPutBucketObjectLock_ObjStore() = default;
486 int get_params(optional_yield y) override;
487 };
488
489 class RGWGetBucketObjectLock_ObjStore : public RGWGetBucketObjectLock {
490 public:
491 RGWGetBucketObjectLock_ObjStore() = default;
492 ~RGWGetBucketObjectLock_ObjStore() override = default;
493 };
494
495 class RGWPutObjRetention_ObjStore : public RGWPutObjRetention {
496 public:
497 RGWPutObjRetention_ObjStore() = default;
498 ~RGWPutObjRetention_ObjStore() override = default;
499 };
500
501 class RGWGetObjRetention_ObjStore : public RGWGetObjRetention {
502 public:
503 RGWGetObjRetention_ObjStore() = default;
504 ~RGWGetObjRetention_ObjStore() = default;
505 };
506
507 class RGWPutObjLegalHold_ObjStore : public RGWPutObjLegalHold {
508 public:
509 RGWPutObjLegalHold_ObjStore() = default;
510 ~RGWPutObjLegalHold_ObjStore() override = default;
511 int get_params(optional_yield y) override;
512 };
513
514 class RGWGetObjLegalHold_ObjStore : public RGWGetObjLegalHold {
515 public:
516 RGWGetObjLegalHold_ObjStore() = default;
517 ~RGWGetObjLegalHold_ObjStore() = default;
518 };
519
520 class RGWRESTOp : public RGWOp {
521 protected:
522 RGWRESTFlusher flusher;
523
524 public:
525 void init(rgw::sal::Store* store, struct req_state *s,
526 RGWHandler *dialect_handler) override {
527 RGWOp::init(store, s, dialect_handler);
528 flusher.init(s, this);
529 }
530 void send_response() override;
531 virtual int check_caps(const RGWUserCaps& caps)
532 { return -EPERM; } /* should to be implemented! */
533 int verify_permission(optional_yield y) override;
534 dmc::client_id dmclock_client() override { return dmc::client_id::admin; }
535 };
536
537 class RGWHandler_REST : public RGWHandler {
538 protected:
539
540 virtual bool is_obj_update_op() const { return false; }
541 virtual RGWOp *op_get() { return NULL; }
542 virtual RGWOp *op_put() { return NULL; }
543 virtual RGWOp *op_delete() { return NULL; }
544 virtual RGWOp *op_head() { return NULL; }
545 virtual RGWOp *op_post() { return NULL; }
546 virtual RGWOp *op_copy() { return NULL; }
547 virtual RGWOp *op_options() { return NULL; }
548
549 public:
550 static int allocate_formatter(struct req_state *s, int default_formatter,
551 bool configurable);
552
553 static constexpr int MAX_BUCKET_NAME_LEN = 255;
554 static constexpr int MAX_OBJ_NAME_LEN = 1024;
555
556 RGWHandler_REST() {}
557 ~RGWHandler_REST() override {}
558
559 static int validate_bucket_name(const std::string& bucket);
560 static int validate_object_name(const std::string& object);
561 static int reallocate_formatter(struct req_state *s, int type);
562
563 int init_permissions(RGWOp* op, optional_yield y) override;
564 int read_permissions(RGWOp* op, optional_yield y) override;
565
566 virtual RGWOp* get_op(void);
567 virtual void put_op(RGWOp* op);
568 };
569
570 class RGWHandler_REST_SWIFT;
571 class RGWHandler_SWIFT_Auth;
572 class RGWHandler_REST_S3;
573
574 namespace rgw::auth {
575
576 class StrategyRegistry;
577
578 }
579
580 class RGWRESTMgr {
581 bool should_log;
582
583 protected:
584 std::map<std::string, RGWRESTMgr*> resource_mgrs;
585 std::multimap<size_t, std::string> resources_by_size;
586 RGWRESTMgr* default_mgr;
587
588 virtual RGWRESTMgr* get_resource_mgr(struct req_state* s,
589 const std::string& uri,
590 std::string* out_uri);
591
592 virtual RGWRESTMgr* get_resource_mgr_as_default(struct req_state* const s,
593 const std::string& uri,
594 std::string* our_uri) {
595 return this;
596 }
597
598 public:
599 RGWRESTMgr()
600 : should_log(false),
601 default_mgr(nullptr) {
602 }
603 virtual ~RGWRESTMgr();
604
605 void register_resource(std::string resource, RGWRESTMgr* mgr);
606 void register_default_mgr(RGWRESTMgr* mgr);
607
608 virtual RGWRESTMgr* get_manager(struct req_state* const s,
609 /* Prefix to be concatenated with @uri
610 * during the lookup. */
611 const std::string& frontend_prefix,
612 const std::string& uri,
613 std::string* out_uri) final {
614 return get_resource_mgr(s, frontend_prefix + uri, out_uri);
615 }
616
617 virtual RGWHandler_REST* get_handler(
618 rgw::sal::Store* store,
619 struct req_state* const s,
620 const rgw::auth::StrategyRegistry& auth_registry,
621 const std::string& frontend_prefix
622 ) {
623 return nullptr;
624 }
625
626 virtual void put_handler(RGWHandler_REST* const handler) {
627 delete handler;
628 }
629
630 void set_logging(bool _should_log) {
631 should_log = _should_log;
632 }
633
634 bool get_logging() const {
635 return should_log;
636 }
637 };
638
639 class RGWLibIO;
640 class RGWRestfulIO;
641
642 class RGWREST {
643 using x_header = basic_sstring<char, uint16_t, 32>;
644 boost::container::flat_set<x_header> x_headers;
645 RGWRESTMgr mgr;
646
647 static int preprocess(struct req_state *s, rgw::io::BasicClient* rio);
648 public:
649 RGWREST() {}
650 RGWHandler_REST *get_handler(rgw::sal::Store* store,
651 struct req_state *s,
652 const rgw::auth::StrategyRegistry& auth_registry,
653 const std::string& frontend_prefix,
654 RGWRestfulIO *rio,
655 RGWRESTMgr **pmgr,
656 int *init_error);
657 #if 0
658 RGWHandler *get_handler(RGWRados *store, struct req_state *s,
659 RGWLibIO *io, RGWRESTMgr **pmgr,
660 int *init_error);
661 #endif
662
663 void put_handler(RGWHandler_REST *handler) {
664 mgr.put_handler(handler);
665 }
666
667 void register_resource(std::string resource, RGWRESTMgr *m,
668 bool register_empty = false) {
669 if (!register_empty && resource.empty())
670 return;
671
672 mgr.register_resource(resource, m);
673 }
674
675 void register_default_mgr(RGWRESTMgr *m) {
676 mgr.register_default_mgr(m);
677 }
678
679 void register_x_headers(const std::string& headers);
680
681 bool log_x_headers(void) {
682 return (x_headers.size() > 0);
683 }
684
685 bool log_x_header(const std::string& header) {
686 return (x_headers.find(header) != x_headers.end());
687 }
688 };
689
690 static constexpr int64_t NO_CONTENT_LENGTH = -1;
691 static constexpr int64_t CHUNKED_TRANSFER_ENCODING = -2;
692
693 extern void dump_errno(int http_ret, std::string& out);
694 extern void dump_errno(const struct rgw_err &err, std::string& out);
695 extern void dump_errno(struct req_state *s);
696 extern void dump_errno(struct req_state *s, int http_ret);
697 extern void end_header(struct req_state *s,
698 RGWOp* op = nullptr,
699 const char *content_type = nullptr,
700 const int64_t proposed_content_length =
701 NO_CONTENT_LENGTH,
702 bool force_content_type = false,
703 bool force_no_error = false);
704 extern void dump_start(struct req_state *s);
705 extern void list_all_buckets_start(struct req_state *s);
706 extern void dump_owner(struct req_state *s, const rgw_user& id,
707 const std::string& name, const char *section = NULL);
708 extern void dump_header(struct req_state* s,
709 const std::string_view& name,
710 const std::string_view& val);
711 extern void dump_header(struct req_state* s,
712 const std::string_view& name,
713 ceph::buffer::list& bl);
714 extern void dump_header(struct req_state* s,
715 const std::string_view& name,
716 long long val);
717 extern void dump_header(struct req_state* s,
718 const std::string_view& name,
719 const utime_t& val);
720
721 template <class... Args>
722 inline void dump_header_prefixed(struct req_state* s,
723 const std::string_view& name_prefix,
724 const std::string_view& name,
725 Args&&... args) {
726 char full_name_buf[name_prefix.size() + name.size() + 1];
727 const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s",
728 static_cast<int>(name_prefix.length()),
729 name_prefix.data(),
730 static_cast<int>(name.length()),
731 name.data());
732 std::string_view full_name(full_name_buf, len);
733 return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
734 }
735
736 template <class... Args>
737 inline void dump_header_infixed(struct req_state* s,
738 const std::string_view& prefix,
739 const std::string_view& infix,
740 const std::string_view& sufix,
741 Args&&... args) {
742 char full_name_buf[prefix.size() + infix.size() + sufix.size() + 1];
743 const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s%.*s",
744 static_cast<int>(prefix.length()),
745 prefix.data(),
746 static_cast<int>(infix.length()),
747 infix.data(),
748 static_cast<int>(sufix.length()),
749 sufix.data());
750 std::string_view full_name(full_name_buf, len);
751 return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
752 }
753
754 template <class... Args>
755 inline void dump_header_quoted(struct req_state* s,
756 const std::string_view& name,
757 const std::string_view& val) {
758 /* We need two extra bytes for quotes. */
759 char qvalbuf[val.size() + 2 + 1];
760 const auto len = snprintf(qvalbuf, sizeof(qvalbuf), "\"%.*s\"",
761 static_cast<int>(val.length()), val.data());
762 return dump_header(s, name, std::string_view(qvalbuf, len));
763 }
764
765 template <class ValueT>
766 inline void dump_header_if_nonempty(struct req_state* s,
767 const std::string_view& name,
768 const ValueT& value) {
769 if (name.length() > 0 && value.length() > 0) {
770 return dump_header(s, name, value);
771 }
772 }
773
774 inline std::string compute_domain_uri(const struct req_state *s) {
775 std::string uri = (!s->info.domain.empty()) ? s->info.domain :
776 [&s]() -> std::string {
777 RGWEnv const &env(*(s->info.env));
778 std::string uri =
779 env.get("SERVER_PORT_SECURE") ? "https://" : "http://";
780 if (env.exists("SERVER_NAME")) {
781 uri.append(env.get("SERVER_NAME", "<SERVER_NAME>"));
782 } else {
783 uri.append(env.get("HTTP_HOST", "<HTTP_HOST>"));
784 }
785 return uri;
786 }();
787 return uri;
788 }
789
790 extern void dump_content_length(struct req_state *s, uint64_t len);
791 extern int64_t parse_content_length(const char *content_length);
792 extern void dump_etag(struct req_state *s,
793 const std::string_view& etag,
794 bool quoted = false);
795 extern void dump_epoch_header(struct req_state *s, const char *name, real_time t);
796 extern void dump_time_header(struct req_state *s, const char *name, real_time t);
797 extern void dump_last_modified(struct req_state *s, real_time t);
798 extern void abort_early(struct req_state* s, RGWOp* op, int err,
799 RGWHandler* handler, optional_yield y);
800 extern void dump_range(struct req_state* s, uint64_t ofs, uint64_t end,
801 uint64_t total_size);
802 extern void dump_continue(struct req_state *s);
803 extern void list_all_buckets_end(struct req_state *s);
804 extern void dump_time(struct req_state *s, const char *name, real_time t);
805 extern std::string dump_time_to_str(const real_time& t);
806 extern void dump_bucket_from_state(struct req_state *s);
807 extern void dump_redirect(struct req_state *s, const std::string& redirect);
808 extern bool is_valid_url(const char *url);
809 extern void dump_access_control(struct req_state *s, const char *origin,
810 const char *meth,
811 const char *hdr, const char *exp_hdr,
812 uint32_t max_age);
813 extern void dump_access_control(req_state *s, RGWOp *op);
814
815 extern int dump_body(struct req_state* s, const char* buf, size_t len);
816 extern int dump_body(struct req_state* s, /* const */ ceph::buffer::list& bl);
817 extern int dump_body(struct req_state* s, const std::string& str);
818 extern int recv_body(struct req_state* s, char* buf, size_t max);