snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
This commit is contained in:
464
weed/s3api/s3_constants/header.go
Normal file
464
weed/s3api/s3_constants/header.go
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* MinIO Cloud Storage, (C) 2019 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.
|
||||
*/
|
||||
|
||||
package s3_constants
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// S3 XML namespace
|
||||
const (
|
||||
S3Namespace = "http://s3.amazonaws.com/doc/2006-03-01/"
|
||||
)
|
||||
|
||||
// S3 object key limits
|
||||
const (
|
||||
MaxS3ObjectKeyLength = 1024
|
||||
)
|
||||
|
||||
// Standard S3 HTTP request constants
|
||||
const (
|
||||
// S3 storage class
|
||||
AmzStorageClass = "X-Amz-Storage-Class"
|
||||
|
||||
// S3 user-defined metadata
|
||||
AmzUserMetaPrefix = "X-Amz-Meta-"
|
||||
AmzUserMetaDirective = "X-Amz-Metadata-Directive"
|
||||
AmzUserMetaMtime = "X-Amz-Meta-Mtime"
|
||||
|
||||
// S3 object tagging
|
||||
AmzObjectTagging = "X-Amz-Tagging"
|
||||
AmzObjectTaggingPrefix = "X-Amz-Tagging-"
|
||||
AmzObjectTaggingDirective = "X-Amz-Tagging-Directive"
|
||||
AmzTagCount = "x-amz-tagging-count"
|
||||
|
||||
// GetObjectAttributes headers
|
||||
AmzObjectAttributes = "X-Amz-Object-Attributes"
|
||||
AmzMaxParts = "X-Amz-Max-Parts"
|
||||
AmzPartNumberMarker = "X-Amz-Part-Number-Marker"
|
||||
AmzDeleteMarker = "X-Amz-Delete-Marker"
|
||||
|
||||
SeaweedFSUploadId = "X-Seaweedfs-Upload-Id"
|
||||
SeaweedFSMultipartPartsCount = "X-Seaweedfs-Multipart-Parts-Count"
|
||||
SeaweedFSMultipartPartBoundaries = "X-Seaweedfs-Multipart-Part-Boundaries" // JSON: [{part:1,start:0,end:2,etag:"abc"},{part:2,start:2,end:3,etag:"def"}]
|
||||
SeaweedFSExpiresS3 = "X-Seaweedfs-Expires-S3"
|
||||
AmzMpPartsCount = "x-amz-mp-parts-count"
|
||||
|
||||
// S3 ACL headers
|
||||
AmzCannedAcl = "X-Amz-Acl"
|
||||
AmzAclFullControl = "X-Amz-Grant-Full-Control"
|
||||
AmzAclRead = "X-Amz-Grant-Read"
|
||||
AmzAclWrite = "X-Amz-Grant-Write"
|
||||
AmzAclReadAcp = "X-Amz-Grant-Read-Acp"
|
||||
AmzAclWriteAcp = "X-Amz-Grant-Write-Acp"
|
||||
|
||||
// S3 Object Lock headers
|
||||
AmzBucketObjectLockEnabled = "X-Amz-Bucket-Object-Lock-Enabled"
|
||||
AmzObjectLockMode = "X-Amz-Object-Lock-Mode"
|
||||
AmzObjectLockRetainUntilDate = "X-Amz-Object-Lock-Retain-Until-Date"
|
||||
AmzObjectLockLegalHold = "X-Amz-Object-Lock-Legal-Hold"
|
||||
|
||||
// S3 checksum headers
|
||||
AmzChecksumAlgorithm = "X-Amz-Checksum-Algorithm"
|
||||
AmzChecksumCRC32 = "X-Amz-Checksum-Crc32"
|
||||
AmzChecksumCRC32C = "X-Amz-Checksum-Crc32c"
|
||||
AmzChecksumCRC64NVME = "X-Amz-Checksum-Crc64nvme"
|
||||
AmzChecksumSHA1 = "X-Amz-Checksum-Sha1"
|
||||
AmzChecksumSHA256 = "X-Amz-Checksum-Sha256"
|
||||
AmzTrailer = "X-Amz-Trailer"
|
||||
AmzSdkChecksumAlgorithm = "X-Amz-Sdk-Checksum-Algorithm"
|
||||
AmzChecksumType = "X-Amz-Checksum-Type"
|
||||
|
||||
// S3 checksum type values (x-amz-checksum-type). A COMPOSITE checksum is a
|
||||
// checksum-of-per-part-checksums ("base64-N"); a FULL_OBJECT checksum is the
|
||||
// checksum of the whole object as if uploaded in a single request ("base64").
|
||||
ChecksumTypeComposite = "COMPOSITE"
|
||||
ChecksumTypeFullObject = "FULL_OBJECT"
|
||||
|
||||
// S3 conditional headers
|
||||
IfMatch = "If-Match"
|
||||
IfNoneMatch = "If-None-Match"
|
||||
IfModifiedSince = "If-Modified-Since"
|
||||
IfUnmodifiedSince = "If-Unmodified-Since"
|
||||
|
||||
// S3 conditional copy headers
|
||||
AmzCopySourceIfMatch = "X-Amz-Copy-Source-If-Match"
|
||||
AmzCopySourceIfNoneMatch = "X-Amz-Copy-Source-If-None-Match"
|
||||
AmzCopySourceIfModifiedSince = "X-Amz-Copy-Source-If-Modified-Since"
|
||||
AmzCopySourceIfUnmodifiedSince = "X-Amz-Copy-Source-If-Unmodified-Since"
|
||||
|
||||
// RenameObject
|
||||
// AmzClientToken makes a rename idempotent. The AWS SDKs fill it in on every
|
||||
// call, so it arrives on requests that were never written with it in mind.
|
||||
AmzClientToken = "X-Amz-Client-Token"
|
||||
AmzRenameSource = "X-Amz-Rename-Source"
|
||||
AmzRenameSourceIfMatch = "X-Amz-Rename-Source-If-Match"
|
||||
AmzRenameSourceIfNoneMatch = "X-Amz-Rename-Source-If-None-Match"
|
||||
AmzRenameSourceIfModifiedSince = "X-Amz-Rename-Source-If-Modified-Since"
|
||||
AmzRenameSourceIfUnmodifiedSince = "X-Amz-Rename-Source-If-Unmodified-Since"
|
||||
|
||||
// S3 Server-Side Encryption with Customer-provided Keys (SSE-C)
|
||||
AmzServerSideEncryptionCustomerAlgorithm = "X-Amz-Server-Side-Encryption-Customer-Algorithm"
|
||||
AmzServerSideEncryptionCustomerKey = "X-Amz-Server-Side-Encryption-Customer-Key"
|
||||
AmzServerSideEncryptionCustomerKeyMD5 = "X-Amz-Server-Side-Encryption-Customer-Key-MD5"
|
||||
AmzServerSideEncryptionContext = "X-Amz-Server-Side-Encryption-Context"
|
||||
|
||||
// S3 Server-Side Encryption with KMS (SSE-KMS)
|
||||
AmzServerSideEncryption = "X-Amz-Server-Side-Encryption"
|
||||
AmzServerSideEncryptionAwsKmsKeyId = "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id"
|
||||
AmzServerSideEncryptionBucketKeyEnabled = "X-Amz-Server-Side-Encryption-Bucket-Key-Enabled"
|
||||
|
||||
// S3 SSE-C copy source headers
|
||||
AmzCopySourceServerSideEncryptionCustomerAlgorithm = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm"
|
||||
AmzCopySourceServerSideEncryptionCustomerKey = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key"
|
||||
AmzCopySourceServerSideEncryptionCustomerKeyMD5 = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-MD5"
|
||||
)
|
||||
|
||||
// Metadata keys for internal storage
|
||||
const (
|
||||
// SSE-KMS metadata keys
|
||||
AmzEncryptedDataKey = "x-amz-encrypted-data-key"
|
||||
AmzEncryptionContextMeta = "x-amz-encryption-context"
|
||||
|
||||
// SeaweedFS internal metadata prefix (used to filter internal headers from client responses)
|
||||
SeaweedFSInternalPrefix = "x-seaweedfs-"
|
||||
|
||||
// SeaweedFSPrefixObject marks a directory entry that also holds the object named by
|
||||
// its path without a trailing slash. S3 keys are flat, so "a/b" and "a/b/c" are
|
||||
// independent keys, and the filer stores the first one on the directory the second
|
||||
// one lives under.
|
||||
SeaweedFSPrefixObject = "x-seaweedfs-prefix-object"
|
||||
|
||||
// SeaweedFS internal metadata keys for encryption (prefixed to avoid automatic HTTP header conversion)
|
||||
SeaweedFSSSEKMSKey = "x-seaweedfs-sse-kms-key" // Key for storing serialized SSE-KMS metadata
|
||||
SeaweedFSSSES3Key = "x-seaweedfs-sse-s3-key" // Key for storing serialized SSE-S3 metadata
|
||||
SeaweedFSSSEIV = "x-seaweedfs-sse-c-iv" // Key for storing SSE-C IV
|
||||
|
||||
// Multipart upload metadata keys for SSE-KMS (consistent with internal metadata key pattern)
|
||||
SeaweedFSSSEKMSKeyID = "x-seaweedfs-sse-kms-key-id" // Key ID for multipart upload SSE-KMS inheritance
|
||||
SeaweedFSSSEKMSEncryption = "x-seaweedfs-sse-kms-encryption" // Encryption type for multipart upload SSE-KMS inheritance
|
||||
SeaweedFSSSEKMSBucketKeyEnabled = "x-seaweedfs-sse-kms-bucket-key-enabled" // Bucket key setting for multipart upload SSE-KMS inheritance
|
||||
SeaweedFSSSEKMSEncryptionContext = "x-seaweedfs-sse-kms-encryption-context" // Encryption context for multipart upload SSE-KMS inheritance
|
||||
SeaweedFSSSEKMSBaseIV = "x-seaweedfs-sse-kms-base-iv" // Base IV for multipart upload SSE-KMS (for IV offset calculation)
|
||||
|
||||
// SeaweedFSRenameToken records the x-amz-client-token of the rename that put an
|
||||
// object at its key, together with the source that rename named. It rides on the
|
||||
// object itself, so every gateway reads the same answer for a retry of that
|
||||
// rename, and it is dropped whenever the key is written again.
|
||||
SeaweedFSRenameToken = "x-seaweedfs-rename-token"
|
||||
|
||||
// Multipart upload metadata keys for SSE-S3
|
||||
SeaweedFSSSES3Encryption = "x-seaweedfs-sse-s3-encryption" // Encryption type for multipart upload SSE-S3 inheritance
|
||||
SeaweedFSSSES3BaseIV = "x-seaweedfs-sse-s3-base-iv" // Base IV for multipart upload SSE-S3 (for IV offset calculation)
|
||||
SeaweedFSSSES3KeyData = "x-seaweedfs-sse-s3-key-data" // Encrypted key data for multipart upload SSE-S3 inheritance
|
||||
)
|
||||
|
||||
// SeaweedFS internal headers for filer communication
|
||||
const (
|
||||
SeaweedFSSSEKMSKeyHeader = "X-SeaweedFS-SSE-KMS-Key" // Header for passing SSE-KMS metadata to filer
|
||||
SeaweedFSSSEIVHeader = "X-SeaweedFS-SSE-IV" // Header for passing SSE-C IV to filer (SSE-C only)
|
||||
SeaweedFSSSEKMSBaseIVHeader = "X-SeaweedFS-SSE-KMS-Base-IV" // Header for passing base IV for multipart SSE-KMS
|
||||
SeaweedFSSSES3BaseIVHeader = "X-SeaweedFS-SSE-S3-Base-IV" // Header for passing base IV for multipart SSE-S3
|
||||
SeaweedFSSSES3KeyDataHeader = "X-SeaweedFS-SSE-S3-Key-Data" // Header for passing key data for multipart SSE-S3
|
||||
|
||||
// SeaweedFSPrincipalHeader and SeaweedFSSessionTokenHeader carry the
|
||||
// server-derived principal ARN and session token from the auth layer to
|
||||
// downstream authorization (IAM policy evaluation, S3Tables IAM checks).
|
||||
// These headers are trusted: callers of AuthSignatureOnly /
|
||||
// authenticateRequestInternal must scrub any client-supplied values at the
|
||||
// very start of authentication to prevent privilege escalation via header
|
||||
// injection. Prefer these constants over literals so that any future scrub
|
||||
// or consumer cannot drift by typo.
|
||||
SeaweedFSPrincipalHeader = "X-SeaweedFS-Principal"
|
||||
SeaweedFSSessionTokenHeader = "X-SeaweedFS-Session-Token"
|
||||
)
|
||||
|
||||
// Non-Standard S3 HTTP request constants
|
||||
const (
|
||||
AmzIdentityId = "s3-identity-id"
|
||||
AmzAccountId = "s3-account-id"
|
||||
AmzAuthType = "s3-auth-type"
|
||||
)
|
||||
|
||||
func GetBucketAndObject(r *http.Request) (bucket, object string) {
|
||||
vars := mux.Vars(r)
|
||||
bucket = vars["bucket"]
|
||||
object = NormalizeObjectKey(vars["object"])
|
||||
return
|
||||
}
|
||||
|
||||
// IsValidObjectKey rejects S3 object keys that — after normalization
|
||||
// (backslash→slash, slash collapse) — contain a `.` or `..` path segment, or
|
||||
// embed a NUL byte. Such keys are collapsed by filepath.Join inside the filer
|
||||
// and would escape the bucket directory, so they must not reach the gRPC layer.
|
||||
// Gorilla mux URL-decodes captured vars before this runs, so `%2e%2e` is
|
||||
// already `..` here.
|
||||
func IsValidObjectKey(object string) bool {
|
||||
if object == "" {
|
||||
return true
|
||||
}
|
||||
if strings.ContainsRune(object, '\x00') {
|
||||
return false
|
||||
}
|
||||
object = strings.ReplaceAll(object, "\\", "/")
|
||||
for _, seg := range strings.Split(object, "/") {
|
||||
if seg == "." || seg == ".." {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsValidBucketName rejects bucket names captured from the URL path that are
|
||||
// unsafe to use in filer path construction (`.`, `..`, contain `/` or `\`, or
|
||||
// embed NUL). This is a path-safety check, not a full S3 naming-rule check.
|
||||
func IsValidBucketName(bucket string) bool {
|
||||
if bucket == "" {
|
||||
return true
|
||||
}
|
||||
if bucket == "." || bucket == ".." {
|
||||
return false
|
||||
}
|
||||
return !strings.ContainsAny(bucket, "/\\\x00")
|
||||
}
|
||||
|
||||
// IsValidPathSegment reports whether value is safe to use as one filer path
|
||||
// component. It intentionally does not enforce any application-specific
|
||||
// format; callers can layer stricter checks on top.
|
||||
func IsValidPathSegment(value string) bool {
|
||||
if value == "" || value == "." || value == ".." {
|
||||
return false
|
||||
}
|
||||
return !strings.ContainsAny(value, "/\\\x00")
|
||||
}
|
||||
|
||||
// NormalizeObjectKey normalizes object keys by removing duplicate slashes and converting backslashes.
|
||||
// This normalizes keys from various sources (URL path, form values, etc.) to a consistent format.
|
||||
// It also converts Windows-style backslashes to forward slashes for cross-platform compatibility.
|
||||
// Returns keys WITHOUT leading slash to match S3 API format (e.g., "foo/bar" not "/foo/bar").
|
||||
// Preserves trailing slash if present (e.g., "foo/" stays "foo/").
|
||||
func NormalizeObjectKey(object string) string {
|
||||
// Preserve trailing slash if present
|
||||
hasTrailingSlash := strings.HasSuffix(object, "/")
|
||||
|
||||
// Convert Windows-style backslashes to forward slashes
|
||||
object = strings.ReplaceAll(object, "\\", "/")
|
||||
object = removeDuplicateSlashes(object)
|
||||
// Remove leading slash to match S3 API format
|
||||
object = strings.TrimPrefix(object, "/")
|
||||
|
||||
// Restore trailing slash if it was present and result is not empty
|
||||
if hasTrailingSlash && object != "" && !strings.HasSuffix(object, "/") {
|
||||
object = object + "/"
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
// removeDuplicateSlashes removes consecutive slashes from a path
|
||||
func removeDuplicateSlashes(s string) string {
|
||||
var result strings.Builder
|
||||
result.Grow(len(s))
|
||||
|
||||
lastWasSlash := false
|
||||
for _, r := range s {
|
||||
if r == '/' {
|
||||
if !lastWasSlash {
|
||||
result.WriteRune(r)
|
||||
}
|
||||
lastWasSlash = true
|
||||
} else {
|
||||
result.WriteRune(r)
|
||||
lastWasSlash = false
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func GetPrefix(r *http.Request) string {
|
||||
query := r.URL.Query()
|
||||
prefix := query.Get("prefix")
|
||||
prefix = removeDuplicateSlashes(prefix)
|
||||
return prefix
|
||||
}
|
||||
|
||||
var PassThroughHeaders = map[string]string{
|
||||
"response-cache-control": "Cache-Control",
|
||||
"response-content-disposition": "Content-Disposition",
|
||||
"response-content-encoding": "Content-Encoding",
|
||||
"response-content-language": "Content-Language",
|
||||
"response-content-type": "Content-Type",
|
||||
"response-expires": "Expires",
|
||||
}
|
||||
|
||||
// IsSeaweedFSInternalHeader checks if a header key is a SeaweedFS internal header
|
||||
// that should be filtered from client responses.
|
||||
// Header names are case-insensitive in HTTP, so this function normalizes to lowercase.
|
||||
func IsSeaweedFSInternalHeader(headerKey string) bool {
|
||||
return strings.HasPrefix(strings.ToLower(headerKey), SeaweedFSInternalPrefix)
|
||||
}
|
||||
|
||||
// Context keys for storing authenticated identity information
|
||||
type contextKey string
|
||||
|
||||
const (
|
||||
contextKeyIdentityName contextKey = "s3-identity-name"
|
||||
contextKeyIdentityObject contextKey = "s3-identity-object"
|
||||
contextKeyIdentityHolder contextKey = "s3-identity-holder"
|
||||
contextKeyPrincipalArn contextKey = "s3-principal-arn"
|
||||
contextKeyIdentityClaim contextKey = "s3-identity-claim"
|
||||
)
|
||||
|
||||
// identityHolder is a mutable container for the authenticated identity name,
|
||||
// stored by pointer in the request context. Authentication runs as an inner
|
||||
// handler that records the identity with r.WithContext, which returns a request
|
||||
// copy; that copy's new context values are invisible to outer middleware (e.g.
|
||||
// the audit logger) holding an earlier copy of the request. A pointer to a
|
||||
// holder installed before authentication is shared across all copies, so the
|
||||
// name written by the inner handler is readable by the outer middleware.
|
||||
type identityHolder struct {
|
||||
name atomic.Pointer[string]
|
||||
principalArn atomic.Pointer[string]
|
||||
identityClaim atomic.Pointer[string]
|
||||
}
|
||||
|
||||
// EnsureIdentityHolder attaches a mutable identity holder to the request context
|
||||
// if one is not already present, returning the (possibly new) request. Install
|
||||
// it before authentication so the authenticated requester remains recoverable
|
||||
// from the original request, e.g. when emitting an audit entry for a handler
|
||||
// that does not log the requester itself.
|
||||
func EnsureIdentityHolder(r *http.Request) *http.Request {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
if h, ok := r.Context().Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
return r
|
||||
}
|
||||
return r.WithContext(context.WithValue(r.Context(), contextKeyIdentityHolder, &identityHolder{}))
|
||||
}
|
||||
|
||||
// SetIdentityNameInContext stores the authenticated identity name in the request context
|
||||
// This is the secure way to propagate identity - headers can be spoofed, context cannot
|
||||
func SetIdentityNameInContext(ctx context.Context, identityName string) context.Context {
|
||||
if identityName == "" {
|
||||
return ctx
|
||||
}
|
||||
// Also record into the mutable holder (if installed) so the name survives the
|
||||
// request-context copy and stays visible to outer middleware such as the
|
||||
// audit logger.
|
||||
if h, ok := ctx.Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
h.name.Store(&identityName)
|
||||
}
|
||||
return context.WithValue(ctx, contextKeyIdentityName, identityName)
|
||||
}
|
||||
|
||||
// GetIdentityNameFromContext retrieves the authenticated identity name from the request context
|
||||
// Returns empty string if no identity is set (unauthenticated request)
|
||||
// This is the secure way to retrieve identity - never read from headers directly
|
||||
func GetIdentityNameFromContext(r *http.Request) string {
|
||||
// Prefer the per-request context value; fall back to the mutable holder for
|
||||
// callers (e.g. the audit middleware) that hold a copy of the request taken
|
||||
// before authentication set the identity.
|
||||
if name, ok := r.Context().Value(contextKeyIdentityName).(string); ok && name != "" {
|
||||
return name
|
||||
}
|
||||
if h, ok := r.Context().Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
if name := h.name.Load(); name != nil {
|
||||
return *name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetPrincipalArnInContext stores the authenticated principal ARN in the request
|
||||
// context. For an STS session the identity name is an opaque session subject, so
|
||||
// the ARN is the only place the assumed role and session name survive to the
|
||||
// audit log.
|
||||
func SetPrincipalArnInContext(ctx context.Context, principalArn string) context.Context {
|
||||
if principalArn == "" {
|
||||
return ctx
|
||||
}
|
||||
if h, ok := ctx.Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
h.principalArn.Store(&principalArn)
|
||||
}
|
||||
return context.WithValue(ctx, contextKeyPrincipalArn, principalArn)
|
||||
}
|
||||
|
||||
// GetPrincipalArnFromContext retrieves the authenticated principal ARN from the
|
||||
// request context, or "" when the request is unauthenticated.
|
||||
func GetPrincipalArnFromContext(r *http.Request) string {
|
||||
if arn, ok := r.Context().Value(contextKeyPrincipalArn).(string); ok && arn != "" {
|
||||
return arn
|
||||
}
|
||||
if h, ok := r.Context().Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
if arn := h.principalArn.Load(); arn != nil {
|
||||
return *arn
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetIdentityClaimInContext stores the authoritative OIDC identity claim (e.g.
|
||||
// preferred_username, email, sub) for the audit log. For an STS-assumed OIDC
|
||||
// session the requester name is an opaque session subject, so the claim is the
|
||||
// only place a stable, human-readable federated identity survives to the audit
|
||||
// log. Empty for non-federated sessions, where the requester name already
|
||||
// carries the real username.
|
||||
func SetIdentityClaimInContext(ctx context.Context, identityClaim string) context.Context {
|
||||
if identityClaim == "" {
|
||||
return ctx
|
||||
}
|
||||
if h, ok := ctx.Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
h.identityClaim.Store(&identityClaim)
|
||||
}
|
||||
return context.WithValue(ctx, contextKeyIdentityClaim, identityClaim)
|
||||
}
|
||||
|
||||
// GetIdentityClaimFromContext retrieves the authoritative OIDC identity claim
|
||||
// from the request context, or "" when the request is unauthenticated or not
|
||||
// federated.
|
||||
func GetIdentityClaimFromContext(r *http.Request) string {
|
||||
if claim, ok := r.Context().Value(contextKeyIdentityClaim).(string); ok && claim != "" {
|
||||
return claim
|
||||
}
|
||||
if h, ok := r.Context().Value(contextKeyIdentityHolder).(*identityHolder); ok && h != nil {
|
||||
if claim := h.identityClaim.Load(); claim != nil {
|
||||
return *claim
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetIdentityInContext stores the full authenticated identity object in the request context
|
||||
// This is used to pass the full identity (including for JWT users) to handlers
|
||||
func SetIdentityInContext(ctx context.Context, identity interface{}) context.Context {
|
||||
if identity != nil {
|
||||
return context.WithValue(ctx, contextKeyIdentityObject, identity)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// GetIdentityFromContext retrieves the full identity object from the request context
|
||||
// Returns nil if no identity is set (unauthenticated request)
|
||||
func GetIdentityFromContext(r *http.Request) interface{} {
|
||||
return r.Context().Value(contextKeyIdentityObject)
|
||||
}
|
||||
Reference in New Issue
Block a user