]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Merge branch 'wip-rgw-static-website-yehuda' 7381/head
authorYehuda Sadeh <yehuda@redhat.com>
Wed, 27 Jan 2016 19:07:43 +0000 (11:07 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Wed, 27 Jan 2016 19:07:43 +0000 (11:07 -0800)
Conflicts:
src/rgw/rgw_common.h
src/rgw/rgw_op.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h

14 files changed:
1  2 
src/CMakeLists.txt
src/common/Makefile.am
src/common/config_opts.h
src/os/kstore/KStore.cc
src/rgw/rgw_common.h
src/rgw/rgw_http_errors.h
src/rgw/rgw_main.cc
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_rest_swift.cc

Simple merge
Simple merge
Simple merge
Simple merge
index 585facd1079dcf0b5e8c3c913013bf31619a1044,b5a4d4867b29137964ca5784f0f907cfa20d8ad7..1034b57e49dcb409a2096c3562d0db208c8fa09c
@@@ -161,7 -169,8 +169,9 @@@ using ceph::crypto::MD5
  #define ERR_INVALID_SECRET_KEY   2034
  #define ERR_INVALID_KEY_TYPE     2035
  #define ERR_INVALID_CAP          2036
 -#define ERR_WEBSITE_REDIRECT     2037
 -#define ERR_NO_SUCH_WEBSITE_CONFIGURATION 2038
 +#define ERR_INVALID_TENANT_NAME  2037
++#define ERR_WEBSITE_REDIRECT     2038
++#define ERR_NO_SUCH_WEBSITE_CONFIGURATION 2039
  #define ERR_USER_SUSPENDED       2100
  #define ERR_INTERNAL_ERROR       2200
  #define ERR_NOT_IMPLEMENTED      2201
Simple merge
index 3a4ad478e93322a1e7319a3043ce92ce01ba3cfd,5fbee746055cb504a4b4f3447262749b87914858..181d943c921a1a8d2af7aad7f84e32ab6a47c440
@@@ -573,10 -574,10 +574,10 @@@ static int process_request(RGWRados *st
  
    should_log = mgr->get_logging();
  
 -  req->log(s, "getting op");
 +  req->log_format(s, "getting op %d", s->op);
    op = handler->get_op(store);
    if (!op) {
-     abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED);
+     abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED, handler);
      goto done;
    }
    req->op = op;
      goto done;
    }
  
-     abort_early(s, op, ret);
 +  req->log(s, "normalizing buckets and tenants");
 +  ret = handler->postauth_init();
 +  if (ret < 0) {
 +    dout(10) << "failed to run post-auth init" << dendl;
++    abort_early(s, op, ret, handler);
 +    goto done;
 +  }
 +
    if (s->user.suspended) {
      dout(10) << "user is suspended, uid=" << s->user.user_id << dendl;
-     abort_early(s, op, -ERR_USER_SUSPENDED);
+     abort_early(s, op, -ERR_USER_SUSPENDED, handler);
      goto done;
    }
+   req->log(s, "init permissions");
+   ret = handler->init_permissions(op);
+   if (ret < 0) {
+     abort_early(s, op, ret, handler);
+     goto done;
+   }
+   /**
+    * Only some accesses support website mode, and website mode does NOT apply
+    * if you are using the REST endpoint either (ergo, no authenticated access)
+    */
+   req->log(s, "recalculating target");
+   ret = handler->retarget(op, &op);
+   if (ret < 0) {
+     abort_early(s, op, ret, handler);
+     goto done;
+   }
+   req->op = op;
    req->log(s, "reading permissions");
    ret = handler->read_permissions(op);
    if (ret < 0) {
Simple merge
index 7051e79f96f791b43895b38dfd866d1d2f570d04,7f96d25f4af6e614be14336d23b25cac16b5f1c0..148e75093e8b32e0f962a2cc1780df794741984e
@@@ -1302,9 -1320,16 +1320,17 @@@ public
  
    virtual RGWOp *get_op(RGWRados *store);
    virtual void put_op(RGWOp *op);
+   virtual int init_permissions(RGWOp *op) {
+     return 0;
+   }
+   virtual int retarget(RGWOp *op, RGWOp **new_op) {
+     *new_op = op;
+     return 0;
+   }
    virtual int read_permissions(RGWOp *op) = 0;
    virtual int authorize() = 0;
 +  virtual int postauth_init() = 0;
+   virtual int error_handler(int err_no, string *error_content);
  };
  
  #endif
Simple merge
index 188022db64667a0559d965f411d1179f24114a50,3ddd1bfb0a9ac2adcdb984cda6c088762dec1d05..8f1c4edf361a6ef6f68809441cbc9889e06ddc47
@@@ -356,10 -356,14 +356,15 @@@ protected
  public:
    RGWHandler_ObjStore() {}
    virtual ~RGWHandler_ObjStore() {}
+   int init_permissions(RGWOp *op);
    int read_permissions(RGWOp *op);
+   virtual int retarget(RGWOp *op, RGWOp **new_op) {
+     *new_op = op;
+     return 0;
+   }
  
    virtual int authorize() = 0;
 +  // virtual int postauth_init(struct req_init_state *t) = 0;
  };
  
  class RGWHandler_ObjStore_SWIFT;
index 5ea703c429298a5f4ccd82d994600105052cadd5,91eb4652537d42b5e193062f2c03afbac077cf28..40db6fcbed44132465e25511198043f4deb8cb6d
@@@ -2685,11 -2816,180 +2820,180 @@@ RGWHandler *RGWRESTMgr_S3::get_handler(
    if (ret < 0)
      return NULL;
  
-   if (s->init_state.url_bucket.empty())
-     return new RGWHandler_ObjStore_Service_S3;
+   RGWHandler* handler;
+   // TODO: Make this more readable
+   if (is_s3website) {
 -    if (s->bucket_name.empty()) {
++    if (s->init_state.url_bucket.empty()) {
+       handler = new RGWHandler_ObjStore_Service_S3Website;
+     } else if (s->object.empty()) {
+       handler = new RGWHandler_ObjStore_Bucket_S3Website;
+     } else {
+       handler = new RGWHandler_ObjStore_Obj_S3Website;
+     }
+   } else {
 -    if (s->bucket_name.empty()) {
++    if (s->init_state.url_bucket.empty()) {
+       handler = new RGWHandler_ObjStore_Service_S3;
+     } else if (s->object.empty()) {
+       handler = new RGWHandler_ObjStore_Bucket_S3;
+     } else {
+       handler = new RGWHandler_ObjStore_Obj_S3;
+     }
+   }
+   ldout(s->cct, 20) << __func__ << " handler=" << typeid(*handler).name() << dendl;
+   return handler;
+ }
+ int RGWHandler_ObjStore_S3Website::retarget(RGWOp *op, RGWOp **new_op) {
+   *new_op = op;
+   ldout(s->cct, 10) << __func__ << "Starting retarget" << dendl;
+   if (!(s->prot_flags & RGW_REST_WEBSITE))
+     return 0;
+   RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
+   int ret = store->get_bucket_info(obj_ctx, s->bucket_tenant, s->bucket_name, s->bucket_info, NULL, &s->bucket_attrs);
+   if (ret < 0) {
+       // TODO-FUTURE: if the bucket does not exist, maybe expose it here?
+       return -ERR_NO_SUCH_BUCKET;
+   }
+   if (!s->bucket_info.has_website) {
+       // TODO-FUTURE: if the bucket has no WebsiteConfig, expose it here
+       return -ERR_NO_SUCH_WEBSITE_CONFIGURATION;
+   }
+   rgw_obj_key new_obj;
+   s->bucket_info.website_conf.get_effective_key(s->object.name, &new_obj.name);
+   ldout(s->cct, 10) << "retarget get_effective_key " << s->object << " -> " << new_obj << dendl;
+   RGWBWRoutingRule rrule;
+   bool should_redirect = s->bucket_info.website_conf.should_redirect(new_obj.name, 0, &rrule);
+   if (should_redirect) {
+     const string& hostname = s->info.env->get("HTTP_HOST", "");
+     const string& protocol = (s->info.env->get("SERVER_PORT_SECURE") ? "https" : "http");
+     int redirect_code = 0;
+     rrule.apply_rule(protocol, hostname, s->object.name, &s->redirect, &redirect_code);
+     // APply a custom HTTP response code
+     if (redirect_code > 0)
+       s->err.http_ret = redirect_code; // Apply a custom HTTP response code
+     ldout(s->cct, 10) << "retarget redirect code=" << redirect_code << " proto+host:" << protocol << "://" << hostname << " -> " << s->redirect << dendl;
+     return -ERR_WEBSITE_REDIRECT;
+   }
+   /*
+    * FIXME: if s->object != new_obj, drop op and create a new op to handle operation. Or
+    * remove this comment if it's not applicable anymore
+    */
+   s->object = new_obj;
+   return 0;
+ }
+ RGWOp *RGWHandler_ObjStore_S3Website::op_get()
+ {
+   return get_obj_op(true);
+ }
  
-   if (s->object.empty())
-     return new RGWHandler_ObjStore_Bucket_S3;
+ RGWOp *RGWHandler_ObjStore_S3Website::op_head()
+ {
+   return get_obj_op(false);
+ }
+ int RGWHandler_ObjStore_S3Website::get_errordoc(const string errordoc_key, string *error_content) {
+     ldout(s->cct, 20) << "TODO Serve Custom error page here if bucket has <Error>" << dendl;
+     *error_content = errordoc_key;
+     // 1. Check if errordoc exists
+     // 2. Check if errordoc is public
+     // 3. Fetch errordoc content
+     /*
+      * FIXME maybe:  need to make sure all of the fields for conditional requests are cleared
+      */
+     RGWGetObj_ObjStore_S3Website *getop = new RGWGetObj_ObjStore_S3Website(true);
+     getop->set_get_data(true);
+     getop->init(store, s, this);
+     RGWGetObj_CB cb(getop);
+     rgw_obj obj(s->bucket, errordoc_key);
+     RGWObjectCtx rctx(store);
+     //RGWRados::Object op_target(store, s->bucket_info, *static_cast<RGWObjectCtx *>(s->obj_ctx), obj);
+     RGWRados::Object op_target(store, s->bucket_info, rctx, obj);
+     RGWRados::Object::Read read_op(&op_target);
+     int ret;
+     int64_t ofs = 0; 
+     int64_t end = -1;
+     ret = read_op.prepare(&ofs, &end);
+     if (ret < 0) {
+       goto done;
+     }
  
-   return new RGWHandler_ObjStore_Obj_S3;
+     ret = read_op.iterate(ofs, end, &cb); // FIXME: need to know the final size?
+ done:
+     delete getop;
+     return ret;
+ }
+   
+ int RGWHandler_ObjStore_S3Website::error_handler(int err_no, string *error_content) {
+   const struct rgw_http_errors *r;
+   int http_error_code = -1;
+   r = search_err(err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS));
+   if (r) {
+     http_error_code = r->http_ret;
+   }
+   RGWBWRoutingRule rrule;
+   bool should_redirect = s->bucket_info.website_conf.should_redirect(s->object.name, http_error_code, &rrule);
+   if (should_redirect) {
+     const string& hostname = s->info.env->get("HTTP_HOST", "");
+     const string& protocol = (s->info.env->get("SERVER_PORT_SECURE") ? "https" : "http");
+     int redirect_code = 0;
+     rrule.apply_rule(protocol, hostname, s->object.name, &s->redirect, &redirect_code);
+     // APply a custom HTTP response code
+     if (redirect_code > 0)
+       s->err.http_ret = redirect_code; // Apply a custom HTTP response code
+     ldout(s->cct, 10) << "error handler redirect code=" << redirect_code << " proto+host:" << protocol << "://" << hostname << " -> " << s->redirect << dendl;
+     return -ERR_WEBSITE_REDIRECT;
+   } else if (!s->bucket_info.website_conf.error_doc.empty()) {
+     RGWHandler_ObjStore_S3Website::get_errordoc(s->bucket_info.website_conf.error_doc, error_content);
+   } else {
+     ldout(s->cct, 20) << "No special error handling today!" << dendl;
+   }
+   return err_no;
+ }
+ RGWOp *RGWHandler_ObjStore_Obj_S3Website::get_obj_op(bool get_data)
+ {
+   /** If we are in website mode, then it is explicitly impossible to run GET or
+    * HEAD on the actual directory. We must convert the request to run on the
+    * suffix object instead!
+    */
+   RGWGetObj_ObjStore_S3Website *op = new RGWGetObj_ObjStore_S3Website;
+   op->set_get_data(get_data);
+   return op;
+ }
+ RGWOp *RGWHandler_ObjStore_Bucket_S3Website::get_obj_op(bool get_data)
+ {
+   /** If we are in website mode, then it is explicitly impossible to run GET or
+    * HEAD on the actual directory. We must convert the request to run on the
+    * suffix object instead!
+    */
+   RGWGetObj_ObjStore_S3Website *op = new RGWGetObj_ObjStore_S3Website;
+   op->set_get_data(get_data);
+   return op;
+ }
+ RGWOp *RGWHandler_ObjStore_Service_S3Website::get_obj_op(bool get_data)
+ {
+   /** If we are in website mode, then it is explicitly impossible to run GET or
+    * HEAD on the actual directory. We must convert the request to run on the
+    * suffix object instead!
+    */
+   RGWGetObj_ObjStore_S3Website *op = new RGWGetObj_ObjStore_S3Website;
+   op->set_get_data(get_data);
+   return op;
  }
index e3b6030e6f408fff255074c8ab4b5300c58fbf28,9176f00e8be1cfa24ced1e46c23732f54f90bf35..9e7d15b20275c682471768d8f05485e86b6c6c45
@@@ -397,7 -421,10 +422,11 @@@ public
    virtual int authorize() {
      return RGW_Auth_S3::authorize(store, s);
    }
 +  int postauth_init();
+   virtual int retarget(RGWOp *op, RGWOp **new_op) {
+     *new_op = op;
+     return 0;
+   }
  };
  
  class RGWHandler_ObjStore_Service_S3 : public RGWHandler_ObjStore_S3 {
Simple merge