Skip to content

Commit 17cb555

Browse files
authored
feat: optimize s3 module string constants (#240)
1 parent 7b62b55 commit 17cb555

File tree

6 files changed

+48
-180
lines changed

6 files changed

+48
-180
lines changed

curvine-s3-gateway/src/auth/sig_v4.rs

Lines changed: 13 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub trait VHeader {
2626
}
2727

2828
use crate::s3::error::Error;
29+
use crate::utils::consts::*;
2930
use crate::utils::GenericResult;
3031
#[derive(Debug)]
3132
pub struct BaseArgs {
@@ -103,7 +104,7 @@ pub fn extract_args<R: VHeader>(r: &R) -> Result<BaseArgs, AuthError> {
103104
// Special handling for common S3 content hash values
104105
let normalized_content_hash = match content_hash.as_str() {
105106
"UNSIGNED-PAYLOAD" => content_hash,
106-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" => content_hash,
107+
EMPTY_PAYLOAD_HASH => content_hash,
107108
_ => content_hash,
108109
};
109110

@@ -223,7 +224,7 @@ pub fn get_v4_signature<T: VHeader, S: ToString>(
223224
fn get_v4_ksigning(secretkey: &str, region: &str, xamz_date: &str) -> GenericResult<[u8; 32]> {
224225
let mut ksign = [0u8; 32];
225226
circle_hmac_sha256(
226-
format!("AWS4{secretkey}").as_str(),
227+
format!("{}{}", "AWS4", secretkey).as_str(),
227228
vec![
228229
&xamz_date.as_bytes()[..8],
229230
region.as_bytes(),
@@ -285,8 +286,16 @@ impl HmacSha256CircleHasher {
285286
}
286287
let mut hsh = ans.unwrap();
287288
let tosign = format!(
288-
"AWS4-HMAC-SHA256-PAYLOAD\n{}\n{}/{}/s3/aws4_request\n{}\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n{}",
289-
self.xamz_date, self.date, self.region, self.last_hash, curr_hsh
289+
"{}\n{}\n{}/{}/{}/{}\n{}\n{}\n{}",
290+
"AWS4-HMAC-SHA256-PAYLOAD",
291+
self.xamz_date,
292+
self.date,
293+
self.region,
294+
"s3",
295+
"aws4_request",
296+
self.last_hash,
297+
EMPTY_PAYLOAD_HASH,
298+
curr_hsh
290299
);
291300
hsh.update(tosign.as_bytes());
292301
let ans = hsh.finalize().into_bytes();
@@ -331,169 +340,3 @@ impl V4Head {
331340
&mut self.circle_hasher
332341
}
333342
}
334-
335-
#[cfg(test)]
336-
mod v4test {
337-
use std::{collections::HashMap, io::Write};
338-
extern crate sha1;
339-
use self::sha1::Digest;
340-
341-
use crate::utils::{BaseKv, GenericResult};
342-
343-
use super::VHeader;
344-
impl VHeader for HashMap<String, String> {
345-
fn get_header(&self, key: &str) -> Option<String> {
346-
let ans = self.get(key);
347-
ans.cloned()
348-
}
349-
350-
fn set_header(&mut self, key: &str, val: &str) {
351-
self.insert(key.to_string(), val.to_string());
352-
}
353-
354-
fn delete_header(&mut self, key: &str) {
355-
self.remove(key);
356-
}
357-
358-
fn rng_header(&self, mut cb: impl FnMut(&str, &str) -> bool) {
359-
self.iter().all(|(k, v)| cb(k, v));
360-
}
361-
}
362-
#[test]
363-
fn v4_signature_test() -> GenericResult<()> {
364-
//case1
365-
let mut hm = HashMap::new();
366-
hm.insert("x-amz-date".to_string(), "20250407T021123Z".to_string());
367-
hm.insert(
368-
"x-amz-content-sha256".to_string(),
369-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string(),
370-
);
371-
hm.insert("host".to_string(), "127.0.0.1:9000".to_string());
372-
let (signature, _) = super::get_v4_signature(
373-
&hm,
374-
"GET",
375-
"us-east-1",
376-
"s3",
377-
"/",
378-
"root12345",
379-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
380-
&["host", "x-amz-content-sha256", "x-amz-date"],
381-
vec![],
382-
)?;
383-
assert!(
384-
signature == "2e3e50b8ab771944088edcda925d886a078ec2442e8504f58e1ac3ef8a2f40fc",
385-
"expect 2e3e50b8ab771944088edcda925d886a078ec2442e8504f58e1ac3ef8a2f40fc, get {}",
386-
signature,
387-
);
388-
//case2
389-
let mut hm = HashMap::new();
390-
hm.insert("x-amz-date".to_string(), "20250407T060526Z".to_string());
391-
hm.insert(
392-
"x-amz-content-sha256".to_string(),
393-
"STREAMING-AWS4-HMAC-SHA256-PAYLOAD".to_string(),
394-
);
395-
hm.insert("host".to_string(), "127.0.0.1:9000".to_string());
396-
hm.insert("x-amz-decoded-content-length".to_string(), "6".to_string());
397-
let (signature, _) = super::get_v4_signature(
398-
&hm,
399-
"PUT",
400-
"us-east-1",
401-
"s3",
402-
"/test/hello.txt",
403-
"root12345",
404-
"STREAMING-AWS4-HMAC-SHA256-PAYLOAD",
405-
&[
406-
"host",
407-
"x-amz-content-sha256",
408-
"x-amz-date",
409-
"x-amz-decoded-content-length",
410-
],
411-
vec![],
412-
)?;
413-
assert!(
414-
signature == "ae05fb994613c1a72e9f1d3bf14de119155587b955ca7d5589a056e7ffab680f",
415-
"expect ae05fb994613c1a72e9f1d3bf14de119155587b955ca7d5589a056e7ffab680f,get {}",
416-
signature
417-
);
418-
//case3
419-
let mut hm = HashMap::new();
420-
hm.insert("x-amz-date".to_string(), "20250410T124056Z".to_string());
421-
hm.insert(
422-
"x-amz-content-sha256".to_string(),
423-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string(),
424-
);
425-
hm.insert("host".to_string(), "127.0.0.1:9000".to_string());
426-
let (signature, _) = super::get_v4_signature(
427-
&hm,
428-
"GET",
429-
"us-east-1",
430-
"s3",
431-
"/test/",
432-
"root12345",
433-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
434-
&["host", "x-amz-content-sha256", "x-amz-date"],
435-
vec![BaseKv {
436-
key: "location".to_string(),
437-
val: "".to_string(),
438-
}],
439-
)?;
440-
assert!(
441-
signature == "f51cf31bf489474692475a74706f9382c7ba0e93e0d657dc9696efa83fc3906a",
442-
"expect f51cf31bf489474692475a74706f9382c7ba0e93e0d657dc9696efa83fc3906a, get {}",
443-
signature,
444-
);
445-
Ok(())
446-
}
447-
#[test]
448-
fn v4_chunk_signature_test() -> Result<(), Box<dyn std::error::Error>> {
449-
let mut hm = HashMap::new();
450-
hm.insert("x-amz-date".to_string(), "20250407T060526Z".to_string());
451-
hm.insert(
452-
"x-amz-content-sha256".to_string(),
453-
"STREAMING-AWS4-HMAC-SHA256-PAYLOAD".to_string(),
454-
);
455-
hm.insert("host".to_string(), "127.0.0.1:9000".to_string());
456-
hm.insert("x-amz-decoded-content-length".to_string(), "6".to_string());
457-
let (headersignature, _) = super::get_v4_signature(
458-
&hm,
459-
"PUT",
460-
"us-east-1",
461-
"s3",
462-
"/test/hello.txt",
463-
"root12345",
464-
"STREAMING-AWS4-HMAC-SHA256-PAYLOAD",
465-
&[
466-
"host",
467-
"x-amz-content-sha256",
468-
"x-amz-date",
469-
"x-amz-decoded-content-length",
470-
],
471-
vec![],
472-
)?;
473-
let ksigning = super::get_v4_ksigning("root12345", "us-east-1", "20250407T060526Z")?;
474-
475-
let mut hsch = super::HmacSha256CircleHasher::new(
476-
ksigning,
477-
headersignature,
478-
"20250407T060526Z".to_string(),
479-
"us-east-1".to_string(),
480-
);
481-
let mut hsh = sha2::Sha256::default();
482-
let _ = hsh.write_all("hello\n".as_bytes());
483-
let ans = hsh.finalize();
484-
let hsh = hsch.next(hex::encode(ans).as_str())?;
485-
assert!(
486-
hsh == "fe78329ef4be9a33af1ffb23c435cf9d985c79dc65911ac78a66317f5a0521bb",
487-
"expect fe78329ef4be9a33af1ffb23c435cf9d985c79dc65911ac78a66317f5a0521bb,get {}",
488-
hsh
489-
);
490-
let final_chunk_hsh =
491-
hsch.next("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")?;
492-
assert!(
493-
final_chunk_hsh == "9095844b0da3ae2e9fe65b372662c4beadfc38ebe5a709b16ea9b03d427d03ad",
494-
"expect 9095844b0da3ae2e9fe65b372662c4beadfc38ebe5a709b16ea9b03d427d03ad,get {}",
495-
final_chunk_hsh
496-
);
497-
Ok(())
498-
}
499-
}

curvine-s3-gateway/src/http/axum.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::auth::sig_v4;
2121
use crate::s3::s3_api::VRequest;
2222
use crate::s3::VRequestPlus;
2323
use axum::body;
24+
2425
// use std::sync::Arc; // Used via std::sync::Arc in code
2526

2627
pub struct Request {

curvine-s3-gateway/src/s3/s3_api.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl std::fmt::Display for ArchiveStatus {
8585
}
8686
}
8787

88-
static OWNER_ID: &str = "ffffffffffffffff";
88+
static OWNER_ID: &str = DEFAULT_OWNER_ID;
8989
pub type DateTime = chrono::DateTime<chrono::Utc>;
9090

9191
pub trait VRequest: crate::auth::sig_v4::VHeader {
@@ -258,6 +258,7 @@ use serde::Serialize;
258258
use sha1::Digest;
259259
use tokio::io::AsyncSeekExt;
260260

261+
use crate::utils::consts::*;
261262
use crate::utils::io::{PollRead, PollWrite};
262263

263264
#[derive(Debug, Serialize)]
@@ -1174,7 +1175,7 @@ pub async fn handle_put_object<T: VRequest + BodyReader, F: VResponse>(
11741175
.write(true)
11751176
.read(true)
11761177
.mode(0o644)
1177-
.open(format!(".sys_bws/{}", cs))
1178+
.open(format!("{}{}", ".sys_bws/", cs))
11781179
.await
11791180
{
11801181
Ok(mut fd) => match parse_body(r, &mut fd, &cs, content_length).await {
@@ -1219,7 +1220,7 @@ pub async fn handle_put_object<T: VRequest + BodyReader, F: VResponse>(
12191220
}
12201221
ContentSha256::Streaming => {
12211222
let file_name = uuid::Uuid::new_v4().to_string()[..8].to_string();
1222-
let file_name = format!(".sys_bws/{}", file_name);
1223+
let file_name = format!("{}{}", ".sys_bws/", file_name);
12231224
let ret = match tokio::fs::OpenOptions::new()
12241225
.create_new(true)
12251226
.write(true)
@@ -1287,7 +1288,7 @@ pub async fn handle_put_object<T: VRequest + BodyReader, F: VResponse>(
12871288
ContentSha256::Unsigned => {
12881289
// No hash verification; stream body into a temp file, then pass to handler
12891290
let file_name = uuid::Uuid::new_v4().to_string()[..8].to_string();
1290-
let file_name = format!(".sys_bws/{}", file_name);
1291+
let file_name = format!("{}{}", ".sys_bws/", file_name);
12911292
let ret = match tokio::fs::OpenOptions::new()
12921293
.create_new(true)
12931294
.write(true)
@@ -2174,7 +2175,8 @@ async fn get_body_stream<T: crate::utils::io::PollRead + Send, H: crate::auth::s
21742175
None,
21752176
));
21762177
} else {
2177-
let file_name = format!(".sys_bws/{}", &uuid::Uuid::new_v4().to_string()[..8]);
2178+
let file_name =
2179+
format!("{}{}", ".sys_bws/", &uuid::Uuid::new_v4().to_string()[..8]);
21782180
let mut fd = tokio::fs::OpenOptions::new()
21792181
.create_new(true)
21802182
.write(true)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2025 OPPO.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
pub const EMPTY_PAYLOAD_HASH: &str =
16+
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
17+
18+
pub const DEFAULT_OWNER_ID: &str = "ffffffffffffffff";

curvine-s3-gateway/src/utils/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use std::io::Write;
1717
use bytes::BytesMut;
1818
use sha1::Digest;
1919

20+
use crate::utils::consts::*;
21+
2022
pub type GenericResult<T> = Result<T, String>;
23+
pub mod consts;
2124
pub mod s3_utils;
2225
#[derive(Debug)]
2326
pub struct BaseKv<K: PartialOrd, V> {
@@ -123,15 +126,13 @@ async fn parse_buff<W: tokio::io::AsyncWrite + Send + Unpin>(
123126
})?);
124127
if let Some(hdr) = head {
125128
if hdr.content_size == 0 {
126-
let next=circle_hasher.next(
127-
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
128-
).unwrap();
129+
let next = circle_hasher.next(EMPTY_PAYLOAD_HASH).unwrap();
129130
if hdr.signature.as_str() == next.as_str() {
130131
log::info!("all signature verify pass");
131132
state = ParseProcessState::End;
132133
return Ok(state);
133134
} else {
134-
log::info!("hash no match expect {next} got {}", hdr.signature);
135+
log::info!("hash no match expect {} got {}", next, hdr.signature);
135136
return Err(ChunkParseError::HashNoMatch);
136137
}
137138
}

curvine-s3-gateway/src/utils/s3_utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ pub fn create_metadata_map(file_status: &FileStatus) -> HashMap<String, String>
117117
// Add custom attributes from x_attr
118118
for (key, value) in &file_status.x_attr {
119119
if let Ok(value_str) = String::from_utf8(value.clone()) {
120-
metadata.insert(format!("x-amz-meta-{}", key.to_lowercase()), value_str);
120+
metadata.insert(
121+
format!("{}{}", "x-amz-meta-", key.to_lowercase()),
122+
value_str,
123+
);
121124
}
122125
}
123126

0 commit comments

Comments
 (0)