mirror of
https://github.com/minio/minio-rs.git
synced 2025-12-06 15:26:51 +08:00
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
This commit is contained in:
parent
25d424b97f
commit
5a90956db8
227
CLAUDE.md
Normal file
227
CLAUDE.md
Normal file
@ -0,0 +1,227 @@
|
||||
# Claude Code Style Guide for MinIO Rust SDK
|
||||
|
||||
- Only provide actionable feedback.
|
||||
- Exclude code style comments on generated files. These will have a header signifying that.
|
||||
- Use github markdown folded sections for all items.
|
||||
- Do not use emojis.
|
||||
- Do not add a "feel good" section.
|
||||
|
||||
## Copyright Header
|
||||
|
||||
All source files that haven't been generated MUST include the following copyright header:
|
||||
|
||||
```rust
|
||||
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
|
||||
// Copyright 20?? MinIO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### Ignore files
|
||||
- Ignore files from processing mentioned under '.gitignore'
|
||||
|
||||
### Comments
|
||||
- **NO redundant comments** - Code should be self-documenting
|
||||
- Avoid obvious comments like `// Set x to 5` for `x := 5`
|
||||
- Only add comments when they explain WHY, not WHAT
|
||||
- Document complex algorithms or non-obvious business logic
|
||||
|
||||
## Critical Code Patterns
|
||||
|
||||
### Builder Pattern
|
||||
All S3 API requests MUST use the builder pattern, with the following documentation but then for the appropriate API
|
||||
|
||||
```rust
|
||||
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
|
||||
///
|
||||
/// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::Client::append_object) method.
|
||||
```
|
||||
|
||||
**Key Requirements:**
|
||||
1. The aws docs url must exist.
|
||||
|
||||
### Error Handling Pattern
|
||||
All Rust SDK methods should follow consistent error handling patterns:
|
||||
|
||||
```rust
|
||||
impl Client {
|
||||
pub async fn operation_name(&self, args: &OperationArgs) -> Result<OperationResponse, Error> {
|
||||
// Validate inputs early
|
||||
args.validate()?;
|
||||
|
||||
// Build request
|
||||
let request = self.build_request(args)?;
|
||||
|
||||
// Execute with proper error propagation
|
||||
let response = self.execute(request).await?;
|
||||
|
||||
// Parse and return
|
||||
OperationResponse::from_response(response)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Code Quality Principles
|
||||
|
||||
### Why Code Quality Standards Are Mandatory
|
||||
|
||||
Code quality standards are **critical business requirements** for MinIO Rust SDK:
|
||||
|
||||
1. **Enterprise Data Safety**: A single bug can corrupt terabytes of customer data across distributed systems
|
||||
2. **Code Efficiency**: MinIO Rust SDK code must be efficient and performant
|
||||
3. **Scalability**: MinIO Rust SDK must be able to handle thousands of concurrent requests
|
||||
4. **High Availability**: Systems must handle failures gracefully - unpredictable code creates cascading failures
|
||||
5. **Developer Velocity**: New team members must understand complex distributed systems quickly and safely
|
||||
|
||||
### Predictable Code Requirements
|
||||
|
||||
Code must exhibit **deterministic behavior** to ensure system reliability:
|
||||
|
||||
1. **Managed State**: Use Arc<Mutex<>> or Arc<RwLock<>> for shared state that needs thread-safe access across async operations
|
||||
2. **Explicit Dependencies**: Business logic dependencies should be passed as parameters or dependency injection
|
||||
3. **Deterministic Operations**: Avoid time-dependent logic, random values, or platform-specific behavior in core paths
|
||||
4. **Consistent Error Handling**: Same error conditions must always produce identical error responses
|
||||
5. **Idempotent Operations**: Operations should be safely repeatable without unintended side effects
|
||||
|
||||
### Readability Standards
|
||||
|
||||
Complex distributed systems code must remain **human-readable**:
|
||||
|
||||
1. **Self-Documenting Code**: Function and variable names should clearly express business intent
|
||||
2. **Consistent Patterns**: Follow established patterns (HTTP handlers, error handling, logging)
|
||||
3. **Logical Flow**: Code should read as a clear narrative from top to bottom
|
||||
4. **Minimal Cognitive Load**: Each function should have a single, well-defined responsibility
|
||||
5. **Clear Abstractions**: Break complex operations into well-named, focused helper functions
|
||||
|
||||
### Separation of Concerns
|
||||
|
||||
**Architectural layers must maintain clear boundaries**:
|
||||
|
||||
1. **Handler Layer**: HTTP request/response processing, input validation, context creation
|
||||
2. **Service Layer**: Business logic orchestration, data transformation
|
||||
3. **Storage Layer**: Data persistence, replication, consistency management
|
||||
4. **Utility Layer**: Reusable helpers with no business logic dependencies
|
||||
5. **Shared State Coordination**: Use thread-safe primitives (Arc, Mutex, RwLock) for components needing consistent views
|
||||
|
||||
### Functions and Methods
|
||||
- Keep functions focused on a single responsibility
|
||||
- Use descriptive names that clearly indicate purpose and business intent
|
||||
- Prefer early returns to reduce nesting complexity
|
||||
- Error handling should be immediate and explicit
|
||||
- **Function length guideline**: Most functions should be under 100 lines; handlers may be longer due to validation logic
|
||||
- **Parameter limits**: Prefer structs over long parameter lists for better maintainability
|
||||
|
||||
### Variables
|
||||
- Use meaningful variable names that reflect business concepts
|
||||
- Variable names should reflect usage frequency: frequent variables can be shorter
|
||||
- Constants should follow Rust patterns
|
||||
- Global variables should be clearly identified and documented for their system-wide purpose
|
||||
|
||||
### Developer Documentation
|
||||
|
||||
**All significant features must include developer documentation** in the `docs/` directory:
|
||||
|
||||
1. **API Documentation**: New endpoints must have usage examples in `docs/`
|
||||
2. **Architecture Decisions**: Complex algorithms or design patterns should be documented
|
||||
3. **Configuration Changes**: New config options must be documented with examples
|
||||
4. **Integration Guides**: External system integrations need clear setup instructions
|
||||
5. **Future Developer Context**: Document WHY decisions were made, not just WHAT was implemented
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Why Unit Tests Are Mandatory
|
||||
|
||||
Unit tests are **non-negotiable** in this project for critical business reasons:
|
||||
|
||||
1. **Data Integrity**: MinIO Rust SDK handles enterprise-critical data. A single bug can cause data loss affecting thousands of users
|
||||
2. **Security Compliance**: Financial and healthcare customers require verifiable code quality. Tests provide audit trails
|
||||
3. **Multi-tenant Reliability**: One customer's workload cannot impact another's. Tests ensure proper isolation
|
||||
4. **Performance SLAs**: Enterprise customers have strict performance requirements. Tests validate behavior under load
|
||||
5. **API Stability**: Breaking changes can affect thousands of applications. Tests prevent regressions
|
||||
6. **Distributed System Complexity**: Complex interactions between storage nodes require comprehensive testing
|
||||
|
||||
### Mandatory Unit Tests
|
||||
**EVERY implementation MUST include unit tests** without being explicitly asked. Follow these patterns:
|
||||
|
||||
1. Test functions must use `#[test]` or `#[tokio::test]` attributes
|
||||
2. Use parameterized tests or loop through test cases for multiple scenarios
|
||||
3. Cover both success and error cases, including edge conditions
|
||||
4. Mock external dependencies appropriately
|
||||
5. **Test coverage guideline**: Aim for comprehensive coverage of new code paths
|
||||
6. Include negative tests for error conditions and boundary cases
|
||||
7. Add benchmarks for performance-critical code paths
|
||||
|
||||
## Improvement Suggestions
|
||||
|
||||
Claude will periodically analyze the codebase and suggest:
|
||||
- Missing test coverage areas
|
||||
- Performance optimizations
|
||||
- Code refactoring opportunities
|
||||
- Security improvements
|
||||
- Documentation gaps
|
||||
|
||||
## Testing Commands
|
||||
|
||||
### Pre-commit Checklist
|
||||
|
||||
Before any code changes:
|
||||
1. ✅ Run `cargo fmt --all` to check and fix code formatting
|
||||
2. ✅ Run `cargo test` to ensure all tests pass
|
||||
3. ✅ Run `cargo clippy` to check for common mistakes
|
||||
4. ✅ Ensure new code has appropriate test coverage
|
||||
5. ✅ Verify no redundant comments are added
|
||||
|
||||
## Directory Structure Conventions
|
||||
|
||||
- `/src` - Main library source code
|
||||
- `/tests` - Integration tests
|
||||
- `/examples` - Example usage code
|
||||
- `/docs` - Documentation
|
||||
- `/benches` - Performance benchmarks
|
||||
|
||||
## Common Patterns to Follow
|
||||
|
||||
### Logging
|
||||
Use the log crate with appropriate macros:
|
||||
|
||||
```rust
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
// Examples:
|
||||
info!("Starting operation: {}", operation_name);
|
||||
debug!("Request details: {:?}", request);
|
||||
error!("Operation failed: {}", err);
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
Use the `Result` type with proper error propagation:
|
||||
|
||||
```rust
|
||||
use crate::s3::error::Error;
|
||||
|
||||
fn operation() -> Result<Response, Error> {
|
||||
let result = risky_operation()?;
|
||||
Ok(process(result))
|
||||
}
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
- **Fix formatting**: `cargo fmt --all`
|
||||
- **Run tests**: `cargo test`
|
||||
- **Run specific test**: `cargo test test_name`
|
||||
- **Check code**: `cargo clippy`
|
||||
- **Build project**: `cargo build --release`
|
||||
- **Generate docs**: `cargo doc --open`
|
||||
@ -13,10 +13,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub const IF_MATCH: &str = "if-match";
|
||||
pub const IF_NONE_MATCH: &str = "if-none-match";
|
||||
pub const IF_MODIFIED_SINCE: &str = "if-modified-since";
|
||||
pub const IF_UNMODIFIED_SINCE: &str = "if-unmodified-since";
|
||||
pub const IF_MATCH: &str = "If-Match";
|
||||
pub const IF_NONE_MATCH: &str = "If-None-Match";
|
||||
pub const IF_MODIFIED_SINCE: &str = "If-Modified-Since";
|
||||
pub const IF_UNMODIFIED_SINCE: &str = "If-Unmodified-Since";
|
||||
pub const CONTENT_MD5: &str = "Content-MD5";
|
||||
pub const CONTENT_TYPE: &str = "Content-Type";
|
||||
pub const AUTHORIZATION: &str = "Authorization";
|
||||
@ -26,61 +26,61 @@ pub const CONTENT_LENGTH: &str = "Content-Length";
|
||||
|
||||
pub const POLICY: &str = "policy";
|
||||
|
||||
pub const X_MINIO_DEPLOYMENT_ID: &str = "x-minio-deployment-id";
|
||||
pub const X_MINIO_DEPLOYMENT_ID: &str = "X-Minio-Deployment-Id";
|
||||
|
||||
pub const X_AMZ_VERSION_ID: &str = "x-amz-version-id";
|
||||
pub const X_AMZ_ID_2: &str = "x-amz-id-2";
|
||||
pub const X_AMZ_WRITE_OFFSET_BYTES: &str = "x-amz-write-offset-bytes";
|
||||
pub const X_AMZ_VERSION_ID: &str = "X-Amz-Version-Id";
|
||||
pub const X_AMZ_ID_2: &str = "X-Amz-Id-2";
|
||||
pub const X_AMZ_WRITE_OFFSET_BYTES: &str = "X-Amz-Write-Offset-Bytes";
|
||||
|
||||
pub const X_AMZ_OBJECT_SIZE: &str = "x-amz-object-size";
|
||||
pub const X_AMZ_TAGGING: &str = "x-amz-tagging";
|
||||
pub const X_AMZ_OBJECT_SIZE: &str = "X-Amz-Object-Size";
|
||||
pub const X_AMZ_TAGGING: &str = "X-Amz-Tagging";
|
||||
|
||||
pub const X_AMZ_BUCKET_REGION: &str = "x-amz-bucket-region";
|
||||
pub const X_AMZ_BUCKET_REGION: &str = "X-Amz-Bucket-Region";
|
||||
|
||||
pub const X_AMZ_OBJECT_LOCK_MODE: &str = "x-amz-object-lock-mode";
|
||||
pub const X_AMZ_OBJECT_LOCK_MODE: &str = "X-Amz-Object-Lock-Mode";
|
||||
|
||||
pub const X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE: &str = "x-amz-object-lock-retain-until-date";
|
||||
pub const X_AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE: &str = "X-Amz-Object-Lock-Retain-Until-Date";
|
||||
|
||||
pub const X_AMZ_OBJECT_LOCK_LEGAL_HOLD: &str = "x-amz-object-lock-legal-hold";
|
||||
pub const X_AMZ_OBJECT_LOCK_LEGAL_HOLD: &str = "X-Amz-Object-Lock-Legal-Hold";
|
||||
|
||||
pub const X_AMZ_METADATA_DIRECTIVE: &str = "x-amz-metadata-directive";
|
||||
pub const X_AMZ_METADATA_DIRECTIVE: &str = "X-Amz-Metadata-Directive";
|
||||
|
||||
pub const X_AMZ_TAGGING_DIRECTIVE: &str = "x-amz-tagging-directive";
|
||||
pub const X_AMZ_TAGGING_DIRECTIVE: &str = "X-Amz-Tagging-Directive";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE: &str = "x-amz-copy-source";
|
||||
pub const X_AMZ_COPY_SOURCE: &str = "X-Amz-Copy-Source";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE_RANGE: &str = "x-amz-copy-source-range";
|
||||
pub const X_AMZ_COPY_SOURCE_RANGE: &str = "X-Amz-Copy-Source-Range";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE_IF_MATCH: &str = "x-amz-copy-source-if-match";
|
||||
pub const X_AMZ_COPY_SOURCE_IF_MATCH: &str = "X-Amz-Copy-Source-If-Match";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE_IF_NONE_MATCH: &str = "x-amz-copy-source-if-none-match";
|
||||
pub const X_AMZ_COPY_SOURCE_IF_NONE_MATCH: &str = "X-Amz-Copy-Source-If-None-Match";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE_IF_UNMODIFIED_SINCE: &str = "x-amz-copy-source-if-unmodified-since";
|
||||
pub const X_AMZ_COPY_SOURCE_IF_UNMODIFIED_SINCE: &str = "X-Amz-Copy-Source-If-Unmodified-Since";
|
||||
|
||||
pub const X_AMZ_COPY_SOURCE_IF_MODIFIED_SINCE: &str = "x-amz-copy-source-if-modified-since";
|
||||
pub const X_AMZ_COPY_SOURCE_IF_MODIFIED_SINCE: &str = "X-Amz-Copy-Source-If-Modified-Since";
|
||||
|
||||
pub const X_AMZ_BUCKET_OBJECT_LOCK_ENABLED: &str = "x-amz-bucket-object-lock-enabled";
|
||||
pub const X_AMZ_BUCKET_OBJECT_LOCK_ENABLED: &str = "X-Amz-Bucket-Object-Lock-Enabled";
|
||||
|
||||
pub const X_AMZ_BYPASS_GOVERNANCE_RETENTION: &str = "x-amz-bypass-governance-retention";
|
||||
pub const X_AMZ_BYPASS_GOVERNANCE_RETENTION: &str = "X-Amz-Bypass-Governance-Retention";
|
||||
|
||||
pub const X_AMZ_DATE: &str = "x-amz-date";
|
||||
pub const X_AMZ_DATE: &str = "X-Amz-Date";
|
||||
|
||||
pub const X_AMZ_DELETE_MARKER: &str = "x-amz-delete-marker";
|
||||
pub const X_AMZ_ALGORITHM: &str = "x-amz-algorithm";
|
||||
pub const X_AMZ_DELETE_MARKER: &str = "X-Amz-Delete-Marker";
|
||||
pub const X_AMZ_ALGORITHM: &str = "X-Amz-Algorithm";
|
||||
|
||||
pub const X_AMZ_CREDENTIAL: &str = "x-amz-credential";
|
||||
pub const X_AMZ_CREDENTIAL: &str = "X-Amz-Credential";
|
||||
|
||||
pub const X_AMZ_SIGNATURE: &str = "x-amz-signature";
|
||||
pub const X_AMZ_SIGNATURE: &str = "X-Amz-Signature";
|
||||
|
||||
pub const X_AMZ_REQUEST_ID: &str = "x-amz-request-id";
|
||||
pub const X_AMZ_REQUEST_ID: &str = "X-Amz-Request-Id";
|
||||
|
||||
pub const X_AMZ_EXPIRES: &str = "x-amz-expires";
|
||||
pub const X_AMZ_EXPIRES: &str = "X-Amz-Expires";
|
||||
|
||||
pub const X_AMZ_SIGNED_HEADERS: &str = "x-amz-signedheaders";
|
||||
pub const X_AMZ_SIGNED_HEADERS: &str = "X-Amz-SignedHeaders";
|
||||
|
||||
pub const X_AMZ_CONTENT_SHA256: &str = "x-amz-content-sha256";
|
||||
pub const X_AMZ_CONTENT_SHA256: &str = "X-Amz-Content-SHA256";
|
||||
|
||||
pub const X_AMZ_SECURITY_TOKEN: &str = "x-amz-security-token";
|
||||
pub const X_AMZ_SECURITY_TOKEN: &str = "X-Amz-Security-Token";
|
||||
|
||||
pub const X_AMZ_SERVER_SIDE_ENCRYPTION: &str = "X-Amz-Server-Side-Encryption";
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Set environment variables to run tests on play.min.io
|
||||
$Env:SERVER_ENDPOINT = "http://localhost:9000/"
|
||||
$Env:ACCESS_KEY = "minioadmin"
|
||||
$Env:SECRET_KEY = "minioadmin"
|
||||
$Env:ACCESS_KEY = if ($Env:MINIO_ROOT_USER) { $Env:MINIO_ROOT_USER } else { "minioadmin" }
|
||||
$Env:SECRET_KEY = if ($Env:MINIO_ROOT_PASSWORD) { $Env:MINIO_ROOT_PASSWORD } else { "minioadmin" }
|
||||
$Env:ENABLE_HTTPS = "false"
|
||||
$Env:MINIO_SSL_CERT_FILE = "./tests/public.crt"
|
||||
$Env:IGNORE_CERT_CHECK = "false"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user