Documentation

S3 proxy operations

What the proxy recognises, where the routing decision lives, and which operations are forwarded vs synthesised vs rejected.

Source: internal/s3proxy/server.go::classifyOperation.

#Classification table

The proxy maps the inbound HTTP method + query string to an operation name. Unknown shapes get Unknown (returns 400).

#GET

ConditionOperation
Bucket emptyListBuckets (synthesised)
Key empty AND ?locationGetBucketLocation
Key empty AND ?uploadsListMultipartUploads
Key emptyListObjects
?uploadIdListParts
elseGetObject

#PUT

ConditionOperation
Key emptyPutBucket (rejected — admin-only)
?partNumber AND ?uploadIdUploadPart
elsePutObject
ConditionOperation
Key emptyHeadBucket
elseHeadObject

#DELETE

ConditionOperation
Key emptyDeleteBucket (rejected — admin-only)
?uploadIdAbortMultipart
elseDeleteObject

#POST

ConditionOperation
?uploadsCreateMultipartUpload
?uploadIdCompleteMultipartUpload
?deleteDeleteObjects
elseUnknown

#What gets forwarded

All recognised operations except PutBucket and DeleteBucket. Those return 403 — bucket lifecycle is admin-only and goes via the dashboard's /api/backends/{bid}/buckets handlers, not the proxy.

#ListBuckets synthesis

ListBuckets is built from the credential's bucket-scope list. The upstream is never called. The XML response carries one <Bucket> entry per scope.

#CopyObject

PUT /<dst-bucket>/<dst-key> with x-amz-copy-source headed at the source. Stowage forwards it as-is. The source bucket must also be in the credential's scope — otherwise 403.

#Anonymous fast-path

When the request has no Authorization header and the target bucket has an active anonymous binding, the proxy bypasses SigV4 verification and applies the per-binding allowlist:

  • GET /<bucket>/<key>GetObject
  • HEAD /<bucket>/<key>HeadObject
  • GET /<bucket>?...ListObjectsV2

Everything else returns 401.

#Failure paths

PhasePossible result
Routing400 InvalidRequest if classification fails.
Authentication401 InvalidAccessKey, 401 SignatureDoesNotMatch.
Authorization403 AccessDenied (scope violation), 429 SlowDown (RPS limit).
Quota507 EntityTooLarge.
ForwardWhatever the upstream returns.

#Source files