]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
RGW/S3: truncate S3 LastModified response (timestamp) to exact seconds
authorOguzhan Ozmen <oozmen@bloomberg.net>
Thu, 9 Jan 2025 16:27:55 +0000 (16:27 +0000)
committerOguzhan Ozmen <oozmen@bloomberg.net>
Thu, 9 Jan 2025 17:15:37 +0000 (17:15 +0000)
With this change, LastModified timestamp in S3 responses will be in
seconds granularity: i.e., milliseconds portion will be normalized.

Fixes: https://tracker.ceph.com/issues/67846
Signed-off-by: Oguzhan Ozmen <oozmen@bloomberg.net>
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc

index ac5e65c0dd6f32fc311c61d54577bd80daa1be68..be6047b5dd5638fab041dd646f04ebd3d91809be 100644 (file)
@@ -502,6 +502,11 @@ void dump_time(req_state *s, const char *name, real_time t)
   s->formatter->dump_string(name, buf);
 }
 
+void dump_time_exact_seconds(req_state *s, const char *name, real_time t)
+{
+  dump_time(s, name, std::chrono::time_point_cast<std::chrono::seconds>(t));
+}
+
 void dump_owner(req_state *s, const std::string& id, const string& name,
                const char *section)
 {
index aa33080af563c1cb5c2b29221a5a49dbf3758ee7..d556eba527f8753309607242aaf0a7366e44beb4 100644 (file)
@@ -903,6 +903,7 @@ extern void dump_range(req_state* s, uint64_t ofs, uint64_t end,
 extern void dump_continue(req_state *s);
 extern void list_all_buckets_end(req_state *s);
 extern void dump_time(req_state *s, const char *name, real_time t);
+extern void dump_time_exact_seconds(req_state *s, const char *name, real_time t);
 extern std::string dump_time_to_str(const real_time& t);
 extern void dump_bucket_from_state(req_state *s);
 extern void dump_redirect(req_state *s, const std::string& redirect);
index 13f6bb0015a4ccaa14d46d280cdee0ddb0c78e05..8a61959d7e5aeb9bd1052808dc89b2b77c52f214 100644 (file)
@@ -1880,7 +1880,7 @@ void RGWListBucket_ObjStore_S3::send_versioned_response()
       }
       s->formatter->dump_string("VersionId", version_id);
       s->formatter->dump_bool("IsLatest", iter->is_current());
-      dump_time(s, "LastModified", iter->meta.mtime);
+      dump_time_exact_seconds(s, "LastModified", iter->meta.mtime);
       if (!iter->is_delete_marker()) {
         s->formatter->dump_format("ETag", "\"%s\"", iter->meta.etag.c_str());
         s->formatter->dump_int("Size", iter->meta.accounted_size);
@@ -1973,7 +1973,7 @@ void RGWListBucket_ObjStore_S3::send_response()
        s->formatter->open_object_section("dummy");
       }
       dump_urlsafe(s ,encode_key, "Key", key.name);
-      dump_time(s, "LastModified", iter->meta.mtime);
+      dump_time_exact_seconds(s, "LastModified", iter->meta.mtime);
       s->formatter->dump_format("ETag", "\"%s\"", iter->meta.etag.c_str());
       s->formatter->dump_int("Size", iter->meta.accounted_size);
       auto& storage_class = rgw_placement_rule::get_canonical_storage_class(iter->meta.storage_class);
@@ -2047,7 +2047,7 @@ void RGWListBucket_ObjStore_S3v2::send_versioned_response()
       }
       s->formatter->dump_string("VersionId", version_id);
       s->formatter->dump_bool("IsLatest", iter->is_current());
-      dump_time(s, "LastModified", iter->meta.mtime);
+      dump_time_exact_seconds(s, "LastModified", iter->meta.mtime);
       if (!iter->is_delete_marker()) {
         s->formatter->dump_format("ETag", "\"%s\"", iter->meta.etag.c_str());
         s->formatter->dump_int("Size", iter->meta.accounted_size);
@@ -2117,7 +2117,7 @@ void RGWListBucket_ObjStore_S3v2::send_response()
       rgw_obj_key key(iter->key);
       s->formatter->open_array_section("Contents");
       dump_urlsafe(s, encode_key, "Key", key.name);
-      dump_time(s, "LastModified", iter->meta.mtime);
+      dump_time_exact_seconds(s, "LastModified", iter->meta.mtime);
       s->formatter->dump_format("ETag", "\"%s\"", iter->meta.etag.c_str());
       s->formatter->dump_int("Size", iter->meta.accounted_size);
       auto& storage_class = rgw_placement_rule::get_canonical_storage_class(iter->meta.storage_class);
@@ -3757,7 +3757,7 @@ void RGWCopyObj_ObjStore_S3::send_response()
     send_partial_response(0);
 
   if (op_ret == 0) {
-    dump_time(s, "LastModified", mtime);
+    dump_time_exact_seconds(s, "LastModified", mtime);
     if (!etag.empty()) {
       s->formatter->dump_format("ETag", "\"%s\"",etag.c_str());
     }
@@ -4329,7 +4329,7 @@ void RGWListMultipart_ObjStore_S3::send_response()
       rgw::sal::MultipartPart* part = iter->second.get();
       s->formatter->open_object_section("Part");
 
-      dump_time(s, "LastModified", part->get_mtime());
+      dump_time_exact_seconds(s, "LastModified", part->get_mtime());
 
       s->formatter->dump_unsigned("PartNumber", part->get_num());
       s->formatter->dump_format("ETag", "\"%s\"", part->get_etag().c_str());