mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-08 14:23:13 +00:00
@@ -1,4 +1,3 @@
|
||||
#![allow(unused_variables, unused_mut, unused_must_use)]
|
||||
// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -12,6 +11,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#![allow(unused_variables, unused_mut, unused_must_use)]
|
||||
|
||||
use http::{HeaderMap, StatusCode};
|
||||
//use iam::get_global_action_cred;
|
||||
@@ -461,3 +461,182 @@ impl Operation for ClearTier {
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
|
||||
}
|
||||
}
|
||||
|
||||
/*pub struct PostRestoreObject {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for PostRestoreObject {
|
||||
async fn call(&self, req: S3Request<Body>, params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let query = {
|
||||
if let Some(query) = req.uri.query() {
|
||||
let input: PostRestoreObject =
|
||||
from_bytes(query.as_bytes()).map_err(|_e| s3_error!(InvalidArgument, "get query failed"))?;
|
||||
input
|
||||
} else {
|
||||
PostRestoreObject::default()
|
||||
}
|
||||
};
|
||||
|
||||
let bucket = params.bucket;
|
||||
if let Err(e) = un_escape_path(params.object) {
|
||||
warn!("post restore object failed, e: {:?}", e);
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("PostRestoreObjectFailed".into()), "post restore object failed"));
|
||||
}
|
||||
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
|
||||
let get_object_info = store.get_object_info();
|
||||
|
||||
if Err(err) = check_request_auth_type(req, policy::RestoreObjectAction, bucket, object) {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("PostRestoreObjectFailed".into()), "post restore object failed"));
|
||||
}
|
||||
|
||||
if req.content_length <= 0 {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
}
|
||||
let Some(opts) = post_restore_opts(req, bucket, object) else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
};
|
||||
|
||||
let Some(obj_info) = getObjectInfo(ctx, bucket, object, opts) else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
};
|
||||
|
||||
if obj_info.transitioned_object.status != lifecycle::TRANSITION_COMPLETE {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
}
|
||||
|
||||
let mut api_err;
|
||||
let Some(rreq) = parsere_store_request(req.body(), req.content_length) else {
|
||||
let api_err = errorCodes.ToAPIErr(ErrMalformedXML);
|
||||
api_err.description = err.Error()
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
};
|
||||
let mut status_code = http::StatusCode::OK;
|
||||
let mut already_restored = false;
|
||||
if Err(err) = rreq.validate(store) {
|
||||
api_err = errorCodes.ToAPIErr(ErrMalformedXML)
|
||||
api_err.description = err.Error()
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrEmptyRequestBody".into()), "post restore object failed"));
|
||||
} else {
|
||||
if obj_info.restore_ongoing && rreq.Type != "SELECT" {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrObjectRestoreAlreadyInProgress".into()), "post restore object failed"));
|
||||
}
|
||||
if !obj_info.restore_ongoing && !obj_info.restore_expires.unix_timestamp() == 0 {
|
||||
status_code = http::StatusCode::Accepted;
|
||||
already_restored = true;
|
||||
}
|
||||
}
|
||||
let restore_expiry = lifecycle::expected_expiry_time(OffsetDateTime::now_utc(), rreq.days);
|
||||
let mut metadata = clone_mss(obj_info.user_defined);
|
||||
|
||||
if rreq.type != "SELECT" {
|
||||
obj_info.metadataOnly = true;
|
||||
metadata[xhttp.AmzRestoreExpiryDays] = rreq.days;
|
||||
metadata[xhttp.AmzRestoreRequestDate] = OffsetDateTime::now_utc().format(http::TimeFormat);
|
||||
if already_restored {
|
||||
metadata[xhttp.AmzRestore] = completedRestoreObj(restore_expiry).String()
|
||||
} else {
|
||||
metadata[xhttp.AmzRestore] = ongoingRestoreObj().String()
|
||||
}
|
||||
obj_info.user_defined = metadata;
|
||||
if let Err(err) = store.copy_object(bucket, object, bucket, object, obj_info, ObjectOptions {
|
||||
version_id: obj_info.version_id,
|
||||
}, ObjectOptions {
|
||||
version_id: obj_info.version_id,
|
||||
m_time: obj_info.mod_time,
|
||||
}) {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrInvalidObjectState".into()), "post restore object failed"));
|
||||
}
|
||||
if already_restored {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let restore_object = must_get_uuid();
|
||||
if rreq.output_location.s3.bucket_name != "" {
|
||||
w.Header()[xhttp.AmzRestoreOutputPath] = []string{pathJoin(rreq.OutputLocation.S3.BucketName, rreq.OutputLocation.S3.Prefix, restoreObject)}
|
||||
}
|
||||
w.WriteHeader(status_code)
|
||||
send_event(EventArgs {
|
||||
event_name: event::ObjectRestorePost,
|
||||
bucket_name: bucket,
|
||||
object: obj_info,
|
||||
req_params: extract_req_params(r),
|
||||
user_agent: req.user_agent(),
|
||||
host: handlers::get_source_ip(r),
|
||||
});
|
||||
tokio::spawn(async move {
|
||||
if !rreq.SelectParameters.IsEmpty() {
|
||||
let actual_size = obj_info.get_actual_size();
|
||||
if actual_size.is_err() {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrInvalidObjectState".into()), "post restore object failed"));
|
||||
}
|
||||
|
||||
let object_rsc = s3select.NewObjectReadSeekCloser(
|
||||
|offset int64| -> (io.ReadCloser, error) {
|
||||
rs := &HTTPRangeSpec{
|
||||
IsSuffixLength: false,
|
||||
Start: offset,
|
||||
End: -1,
|
||||
}
|
||||
return getTransitionedObjectReader(bucket, object, rs, r.Header,
|
||||
obj_info, ObjectOptions {version_id: obj_info.version_id});
|
||||
},
|
||||
actual_size.unwrap(),
|
||||
);
|
||||
if err = rreq.SelectParameters.Open(objectRSC); err != nil {
|
||||
if serr, ok := err.(s3select.SelectError); ok {
|
||||
let encoded_error_response = encodeResponse(APIErrorResponse {
|
||||
code: serr.ErrorCode(),
|
||||
message: serr.ErrorMessage(),
|
||||
bucket_name: bucket,
|
||||
key: object,
|
||||
resource: r.URL.Path,
|
||||
request_id: w.Header().Get(xhttp.AmzRequestID),
|
||||
host_id: globalDeploymentID(),
|
||||
});
|
||||
//writeResponse(w, serr.HTTPStatusCode(), encodedErrorResponse, mimeXML)
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header));
|
||||
} else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::Custom("ErrInvalidObjectState".into()), "post restore object failed"));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let nr = httptest.NewRecorder();
|
||||
let rw = xhttp.NewResponseRecorder(nr);
|
||||
rw.log_err_body = true;
|
||||
rw.log_all_body = true;
|
||||
rreq.select_parameters.evaluate(rw);
|
||||
rreq.select_parameters.Close();
|
||||
return Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header));
|
||||
}
|
||||
let opts = ObjectOptions {
|
||||
transition: TransitionOptions {
|
||||
restore_request: rreq,
|
||||
restore_expiry: restore_expiry,
|
||||
},
|
||||
version_id: objInfo.version_id,
|
||||
}
|
||||
if Err(err) = store.restore_transitioned_object(bucket, object, opts) {
|
||||
format!(format!("unable to restore transitioned bucket/object {}/{}: {}", bucket, object, err.to_string()));
|
||||
return Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header));
|
||||
}
|
||||
|
||||
send_event(EventArgs {
|
||||
EventName: event.ObjectRestoreCompleted,
|
||||
BucketName: bucket,
|
||||
Object: objInfo,
|
||||
ReqParams: extractReqParams(r),
|
||||
UserAgent: r.UserAgent(),
|
||||
Host: handlers.GetSourceIP(r),
|
||||
});
|
||||
});
|
||||
|
||||
let mut header = HeaderMap::new();
|
||||
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -1977,18 +1977,18 @@ impl S3 for FS {
|
||||
} = req.input;
|
||||
|
||||
let mut lr_retention = false;
|
||||
let rcfg = metadata_sys::get_object_lock_config(&bucket).await;
|
||||
/*let rcfg = metadata_sys::get_object_lock_config(&bucket).await;
|
||||
if let Ok(rcfg) = rcfg {
|
||||
if let Some(rule) = rcfg.0.rule {
|
||||
if let Some(retention) = rule.default_retention {
|
||||
if let Some(mode) = retention.mode {
|
||||
if mode == ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::GOVERNANCE) {
|
||||
//if mode == ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::GOVERNANCE) {
|
||||
lr_retention = true;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//info!("lifecycle_configuration: {:?}", &lifecycle_configuration);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user