s3pe
A small, dependable S3 client and command line, made for s3.pe.gov.br (the Garage object store of the State of Pernambuco, Brazil) and usable with any S3-style store.
Website: https://strategicprojects.github.io/s3pe/ · API reference: https://docs.rs/s3pe
Install
Rust 1.85 or later. TLS by rustls with bundled roots: no system OpenSSL.
Library
use ;
// credentials and endpoint come from the environment
let manifest = read_s3?;
write_s3?;
for object in list_s3?
# Ok::
With an explicit client:
let s3 = builder
.endpoint
.credentials
.bucket
.build?;
let bytes = s3.read?;
s3.upload?; // streaming
s3.download?; // streaming, .s3pe-part then rename
if let Some = s3.head?
s3.delete?;
# Ok::
Configuration
| Setting | Environment | Default |
|---|---|---|
| endpoint | S3PE_ENDPOINT, then AWS_ENDPOINT_URL |
https://s3.pe.gov.br |
| region | AWS_REGION, then AWS_DEFAULT_REGION |
us-east-1 |
| credentials | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY (AWS_SESSION_TOKEN) |
required |
| bucket | S3PE_BUCKET |
none: use s3://bucket/key |
Path-style URLs always. Keys are bare (relative to the bucket) or full
s3://bucket/key URLs.
What "dependable" means
- AWS Signature V4 over the real SHA-256 of the payload: no
UNSIGNED-PAYLOAD, noaws-chunked(which Garage 2.4 rejects). - Connection failures and HTTP 429/500/502/503/504 are retried twice, with
a 1 s then 2 s pause. Other errors come back at once, typed:
Error::NotFound,Error::AccessDenied,Error::Http { status, code, .. },Error::Transport,Error::Config,Error::Integrity. - After an upload the server's ETag is compared with the local MD5; after a
download the byte count with
Content-Lengthand, when the ETag is an MD5, the MD5 of what arrived. - One line per transfer through the
logfacade (targets3pe):↑ s3://iaempe/etl/painel.parquet (12.3 MB, 0.8 s).
Command line
# or ~/.Renviron, .env, ...
|
Exit codes: 0 ok, 2 not found, 3 access denied, 4 configuration, 1 anything
else. -q or S3PE_QUIET=1 keeps stderr to errors.
The family
The same package exists for Python (pip install s3pe), R
(install.packages("s3pe")) and Go (go get github.com/StrategicProjects/s3pe),
all in one repository, with one
version and one changelog. The Python package is a binding on this crate.