Skip to content

Commit 5a90956

Browse files
authored
fix: update HTTP header constants to use proper capitalization (#186)
- Update all X-Amz-* headers to use capital letters after hyphens (e.g., X-Amz-Date) - Update standard HTTP headers to use proper case (e.g., If-Modified-Since) - Update X-Minio headers to follow same capitalization pattern - Aligns with AWS S3 API specification and HTTP standards
1 parent 25d424b commit 5a90956

File tree

4 files changed

+264
-36
lines changed

4 files changed

+264
-36
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

CLAUDE.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Claude Code Style Guide for MinIO Rust SDK
2+
3+
- Only provide actionable feedback.
4+
- Exclude code style comments on generated files. These will have a header signifying that.
5+
- Use github markdown folded sections for all items.
6+
- Do not use emojis.
7+
- Do not add a "feel good" section.
8+
9+
## Copyright Header
10+
11+
All source files that haven't been generated MUST include the following copyright header:
12+
13+
```rust
14+
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
15+
// Copyright 20?? MinIO, Inc.
16+
//
17+
// Licensed under the Apache License, Version 2.0 (the "License");
18+
// you may not use this file except in compliance with the License.
19+
// You may obtain a copy of the License at
20+
//
21+
// http://www.apache.org/licenses/LICENSE-2.0
22+
//
23+
// Unless required by applicable law or agreed to in writing, software
24+
// distributed under the License is distributed on an "AS IS" BASIS,
25+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26+
// See the License for the specific language governing permissions and
27+
// limitations under the License.
28+
```
29+
30+
## Code Style Guidelines
31+
32+
### Ignore files
33+
- Ignore files from processing mentioned under '.gitignore'
34+
35+
### Comments
36+
- **NO redundant comments** - Code should be self-documenting
37+
- Avoid obvious comments like `// Set x to 5` for `x := 5`
38+
- Only add comments when they explain WHY, not WHAT
39+
- Document complex algorithms or non-obvious business logic
40+
41+
## Critical Code Patterns
42+
43+
### Builder Pattern
44+
All S3 API requests MUST use the builder pattern, with the following documentation but then for the appropriate API
45+
46+
```rust
47+
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
48+
///
49+
/// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::Client::append_object) method.
50+
```
51+
52+
**Key Requirements:**
53+
1. The aws docs url must exist.
54+
55+
### Error Handling Pattern
56+
All Rust SDK methods should follow consistent error handling patterns:
57+
58+
```rust
59+
impl Client {
60+
pub async fn operation_name(&self, args: &OperationArgs) -> Result<OperationResponse, Error> {
61+
// Validate inputs early
62+
args.validate()?;
63+
64+
// Build request
65+
let request = self.build_request(args)?;
66+
67+
// Execute with proper error propagation
68+
let response = self.execute(request).await?;
69+
70+
// Parse and return
71+
OperationResponse::from_response(response)
72+
}
73+
}
74+
```
75+
76+
## Code Quality Principles
77+
78+
### Why Code Quality Standards Are Mandatory
79+
80+
Code quality standards are **critical business requirements** for MinIO Rust SDK:
81+
82+
1. **Enterprise Data Safety**: A single bug can corrupt terabytes of customer data across distributed systems
83+
2. **Code Efficiency**: MinIO Rust SDK code must be efficient and performant
84+
3. **Scalability**: MinIO Rust SDK must be able to handle thousands of concurrent requests
85+
4. **High Availability**: Systems must handle failures gracefully - unpredictable code creates cascading failures
86+
5. **Developer Velocity**: New team members must understand complex distributed systems quickly and safely
87+
88+
### Predictable Code Requirements
89+
90+
Code must exhibit **deterministic behavior** to ensure system reliability:
91+
92+
1. **Managed State**: Use Arc<Mutex<>> or Arc<RwLock<>> for shared state that needs thread-safe access across async operations
93+
2. **Explicit Dependencies**: Business logic dependencies should be passed as parameters or dependency injection
94+
3. **Deterministic Operations**: Avoid time-dependent logic, random values, or platform-specific behavior in core paths
95+
4. **Consistent Error Handling**: Same error conditions must always produce identical error responses
96+
5. **Idempotent Operations**: Operations should be safely repeatable without unintended side effects
97+
98+
### Readability Standards
99+
100+
Complex distributed systems code must remain **human-readable**:
101+
102+
1. **Self-Documenting Code**: Function and variable names should clearly express business intent
103+
2. **Consistent Patterns**: Follow established patterns (HTTP handlers, error handling, logging)
104+
3. **Logical Flow**: Code should read as a clear narrative from top to bottom
105+
4. **Minimal Cognitive Load**: Each function should have a single, well-defined responsibility
106+
5. **Clear Abstractions**: Break complex operations into well-named, focused helper functions
107+
108+
### Separation of Concerns
109+
110+
**Architectural layers must maintain clear boundaries**:
111+
112+
1. **Handler Layer**: HTTP request/response processing, input validation, context creation
113+
2. **Service Layer**: Business logic orchestration, data transformation
114+
3. **Storage Layer**: Data persistence, replication, consistency management
115+
4. **Utility Layer**: Reusable helpers with no business logic dependencies
116+
5. **Shared State Coordination**: Use thread-safe primitives (Arc, Mutex, RwLock) for components needing consistent views
117+
118+
### Functions and Methods
119+
- Keep functions focused on a single responsibility
120+
- Use descriptive names that clearly indicate purpose and business intent
121+
- Prefer early returns to reduce nesting complexity
122+
- Error handling should be immediate and explicit
123+
- **Function length guideline**: Most functions should be under 100 lines; handlers may be longer due to validation logic
124+
- **Parameter limits**: Prefer structs over long parameter lists for better maintainability
125+
126+
### Variables
127+
- Use meaningful variable names that reflect business concepts
128+
- Variable names should reflect usage frequency: frequent variables can be shorter
129+
- Constants should follow Rust patterns
130+
- Global variables should be clearly identified and documented for their system-wide purpose
131+
132+
### Developer Documentation
133+
134+
**All significant features must include developer documentation** in the `docs/` directory:
135+
136+
1. **API Documentation**: New endpoints must have usage examples in `docs/`
137+
2. **Architecture Decisions**: Complex algorithms or design patterns should be documented
138+
3. **Configuration Changes**: New config options must be documented with examples
139+
4. **Integration Guides**: External system integrations need clear setup instructions
140+
5. **Future Developer Context**: Document WHY decisions were made, not just WHAT was implemented
141+
142+
## Testing Requirements
143+
144+
### Why Unit Tests Are Mandatory
145+
146+
Unit tests are **non-negotiable** in this project for critical business reasons:
147+
148+
1. **Data Integrity**: MinIO Rust SDK handles enterprise-critical data. A single bug can cause data loss affecting thousands of users
149+
2. **Security Compliance**: Financial and healthcare customers require verifiable code quality. Tests provide audit trails
150+
3. **Multi-tenant Reliability**: One customer's workload cannot impact another's. Tests ensure proper isolation
151+
4. **Performance SLAs**: Enterprise customers have strict performance requirements. Tests validate behavior under load
152+
5. **API Stability**: Breaking changes can affect thousands of applications. Tests prevent regressions
153+
6. **Distributed System Complexity**: Complex interactions between storage nodes require comprehensive testing
154+
155+
### Mandatory Unit Tests
156+
**EVERY implementation MUST include unit tests** without being explicitly asked. Follow these patterns:
157+
158+
1. Test functions must use `#[test]` or `#[tokio::test]` attributes
159+
2. Use parameterized tests or loop through test cases for multiple scenarios
160+
3. Cover both success and error cases, including edge conditions
161+
4. Mock external dependencies appropriately
162+
5. **Test coverage guideline**: Aim for comprehensive coverage of new code paths
163+
6. Include negative tests for error conditions and boundary cases
164+
7. Add benchmarks for performance-critical code paths
165+
166+
## Improvement Suggestions
167+
168+
Claude will periodically analyze the codebase and suggest:
169+
- Missing test coverage areas
170+
- Performance optimizations
171+
- Code refactoring opportunities
172+
- Security improvements
173+
- Documentation gaps
174+
175+
## Testing Commands
176+
177+
### Pre-commit Checklist
178+
179+
Before any code changes:
180+
1. ✅ Run `cargo fmt --all` to check and fix code formatting
181+
2. ✅ Run `cargo test` to ensure all tests pass
182+
3. ✅ Run `cargo clippy` to check for common mistakes
183+
4. ✅ Ensure new code has appropriate test coverage
184+
5. ✅ Verify no redundant comments are added
185+
186+
## Directory Structure Conventions
187+
188+
- `/src` - Main library source code
189+
- `/tests` - Integration tests
190+
- `/examples` - Example usage code
191+
- `/docs` - Documentation
192+
- `/benches` - Performance benchmarks
193+
194+
## Common Patterns to Follow
195+
196+
### Logging
197+
Use the log crate with appropriate macros:
198+
199+
```rust
200+
use log::{debug, error, info, trace, warn};
201+
202+
// Examples:
203+
info!("Starting operation: {}", operation_name);
204+
debug!("Request details: {:?}", request);
205+
error!("Operation failed: {}", err);
206+
```
207+
208+
### Error Handling
209+
Use the `Result` type with proper error propagation:
210+
211+
```rust
212+
use crate::s3::error::Error;
213+
214+
fn operation() -> Result<Response, Error> {
215+
let result = risky_operation()?;
216+
Ok(process(result))
217+
}
218+
```
219+
220+
## Quick Reference
221+
222+
- **Fix formatting**: `cargo fmt --all`
223+
- **Run tests**: `cargo test`
224+
- **Run specific test**: `cargo test test_name`
225+
- **Check code**: `cargo clippy`
226+
- **Build project**: `cargo build --release`
227+
- **Generate docs**: `cargo doc --open`

src/s3/header_constants.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
pub const IF_MATCH: &str = "if-match";
17-
pub const IF_NONE_MATCH: &str = "if-none-match";
18-
pub const IF_MODIFIED_SINCE: &str = "if-modified-since";
19-
pub const IF_UNMODIFIED_SINCE: &str = "if-unmodified-since";
16+
pub const IF_MATCH: &str = "If-Match";
17+
pub const IF_NONE_MATCH: &str = "If-None-Match";
18+
pub const IF_MODIFIED_SINCE: &str = "If-Modified-Since";
19+
pub const IF_UNMODIFIED_SINCE: &str = "If-Unmodified-Since";
2020
pub const CONTENT_MD5: &str = "Content-MD5";
2121
pub const CONTENT_TYPE: &str = "Content-Type";
2222
pub const AUTHORIZATION: &str = "Authorization";
@@ -26,61 +26,61 @@ pub const CONTENT_LENGTH: &str = "Content-Length";
2626

2727
pub const POLICY: &str = "policy";
2828

29-
pub const X_MINIO_DEPLOYMENT_ID: &str = "x-minio-deployment-id";
29+
pub const X_MINIO_DEPLOYMENT_ID: &str = "X-Minio-Deployment-Id";
3030

31-
pub const X_AMZ_VERSION_ID: &str = "x-amz-version-id";
32-
pub const X_AMZ_ID_2: &str = "x-amz-id-2";
33-
pub const X_AMZ_WRITE_OFFSET_BYTES: &str = "x-amz-write-offset-bytes";
31+
pub const X_AMZ_VERSION_ID: &str = "X-Amz-Version-Id";
32+
pub const X_AMZ_ID_2: &str = "X-Amz-Id-2";
33+
pub const X_AMZ_WRITE_OFFSET_BYTES: &str = "X-Amz-Write-Offset-Bytes";
3434

35-
pub const X_AMZ_OBJECT_SIZE: &str = "x-amz-object-size";
36-
pub const X_AMZ_TAGGING: &str = "x-amz-tagging";
35+
pub const X_AMZ_OBJECT_SIZE: &str = "X-Amz-Object-Size";
36+
pub const X_AMZ_TAGGING: &str = "X-Amz-Tagging";
3737

38-
pub const X_AMZ_BUCKET_REGION: &str = "x-amz-bucket-region";
38+
pub const X_AMZ_BUCKET_REGION: &str = "X-Amz-Bucket-Region";
3939

40-
pub const X_AMZ_OBJECT_LOCK_MODE: &str = "x-amz-object-lock-mode";
40+
pub const X_AMZ_OBJECT_LOCK_MODE: &str = "X-Amz-Object-Lock-Mode";
4141

42-
pub const X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE: &str = "x-amz-object-lock-retain-until-date";
42+
pub const X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE: &str = "X-Amz-Object-Lock-Retain-Until-Date";
4343

44-
pub const X_AMZ_OBJECT_LOCK_LEGAL_HOLD: &str = "x-amz-object-lock-legal-hold";
44+
pub const X_AMZ_OBJECT_LOCK_LEGAL_HOLD: &str = "X-Amz-Object-Lock-Legal-Hold";
4545

46-
pub const X_AMZ_METADATA_DIRECTIVE: &str = "x-amz-metadata-directive";
46+
pub const X_AMZ_METADATA_DIRECTIVE: &str = "X-Amz-Metadata-Directive";
4747

48-
pub const X_AMZ_TAGGING_DIRECTIVE: &str = "x-amz-tagging-directive";
48+
pub const X_AMZ_TAGGING_DIRECTIVE: &str = "X-Amz-Tagging-Directive";
4949

50-
pub const X_AMZ_COPY_SOURCE: &str = "x-amz-copy-source";
50+
pub const X_AMZ_COPY_SOURCE: &str = "X-Amz-Copy-Source";
5151

52-
pub const X_AMZ_COPY_SOURCE_RANGE: &str = "x-amz-copy-source-range";
52+
pub const X_AMZ_COPY_SOURCE_RANGE: &str = "X-Amz-Copy-Source-Range";
5353

54-
pub const X_AMZ_COPY_SOURCE_IF_MATCH: &str = "x-amz-copy-source-if-match";
54+
pub const X_AMZ_COPY_SOURCE_IF_MATCH: &str = "X-Amz-Copy-Source-If-Match";
5555

56-
pub const X_AMZ_COPY_SOURCE_IF_NONE_MATCH: &str = "x-amz-copy-source-if-none-match";
56+
pub const X_AMZ_COPY_SOURCE_IF_NONE_MATCH: &str = "X-Amz-Copy-Source-If-None-Match";
5757

58-
pub const X_AMZ_COPY_SOURCE_IF_UNMODIFIED_SINCE: &str = "x-amz-copy-source-if-unmodified-since";
58+
pub const X_AMZ_COPY_SOURCE_IF_UNMODIFIED_SINCE: &str = "X-Amz-Copy-Source-If-Unmodified-Since";
5959

60-
pub const X_AMZ_COPY_SOURCE_IF_MODIFIED_SINCE: &str = "x-amz-copy-source-if-modified-since";
60+
pub const X_AMZ_COPY_SOURCE_IF_MODIFIED_SINCE: &str = "X-Amz-Copy-Source-If-Modified-Since";
6161

62-
pub const X_AMZ_BUCKET_OBJECT_LOCK_ENABLED: &str = "x-amz-bucket-object-lock-enabled";
62+
pub const X_AMZ_BUCKET_OBJECT_LOCK_ENABLED: &str = "X-Amz-Bucket-Object-Lock-Enabled";
6363

64-
pub const X_AMZ_BYPASS_GOVERNANCE_RETENTION: &str = "x-amz-bypass-governance-retention";
64+
pub const X_AMZ_BYPASS_GOVERNANCE_RETENTION: &str = "X-Amz-Bypass-Governance-Retention";
6565

66-
pub const X_AMZ_DATE: &str = "x-amz-date";
66+
pub const X_AMZ_DATE: &str = "X-Amz-Date";
6767

68-
pub const X_AMZ_DELETE_MARKER: &str = "x-amz-delete-marker";
69-
pub const X_AMZ_ALGORITHM: &str = "x-amz-algorithm";
68+
pub const X_AMZ_DELETE_MARKER: &str = "X-Amz-Delete-Marker";
69+
pub const X_AMZ_ALGORITHM: &str = "X-Amz-Algorithm";
7070

71-
pub const X_AMZ_CREDENTIAL: &str = "x-amz-credential";
71+
pub const X_AMZ_CREDENTIAL: &str = "X-Amz-Credential";
7272

73-
pub const X_AMZ_SIGNATURE: &str = "x-amz-signature";
73+
pub const X_AMZ_SIGNATURE: &str = "X-Amz-Signature";
7474

75-
pub const X_AMZ_REQUEST_ID: &str = "x-amz-request-id";
75+
pub const X_AMZ_REQUEST_ID: &str = "X-Amz-Request-Id";
7676

77-
pub const X_AMZ_EXPIRES: &str = "x-amz-expires";
77+
pub const X_AMZ_EXPIRES: &str = "X-Amz-Expires";
7878

79-
pub const X_AMZ_SIGNED_HEADERS: &str = "x-amz-signedheaders";
79+
pub const X_AMZ_SIGNED_HEADERS: &str = "X-Amz-SignedHeaders";
8080

81-
pub const X_AMZ_CONTENT_SHA256: &str = "x-amz-content-sha256";
81+
pub const X_AMZ_CONTENT_SHA256: &str = "X-Amz-Content-SHA256";
8282

83-
pub const X_AMZ_SECURITY_TOKEN: &str = "x-amz-security-token";
83+
pub const X_AMZ_SECURITY_TOKEN: &str = "X-Amz-Security-Token";
8484

8585
pub const X_AMZ_SERVER_SIDE_ENCRYPTION: &str = "X-Amz-Server-Side-Encryption";
8686

tests/run-tests-windows.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Set environment variables to run tests on play.min.io
22
$Env:SERVER_ENDPOINT = "http://localhost:9000/"
3-
$Env:ACCESS_KEY = "minioadmin"
4-
$Env:SECRET_KEY = "minioadmin"
3+
$Env:ACCESS_KEY = if ($Env:MINIO_ROOT_USER) { $Env:MINIO_ROOT_USER } else { "minioadmin" }
4+
$Env:SECRET_KEY = if ($Env:MINIO_ROOT_PASSWORD) { $Env:MINIO_ROOT_PASSWORD } else { "minioadmin" }
55
$Env:ENABLE_HTTPS = "false"
66
$Env:MINIO_SSL_CERT_FILE = "./tests/public.crt"
77
$Env:IGNORE_CERT_CHECK = "false"

0 commit comments

Comments
 (0)