s3
Portable S3-compatible client library layered on top of the normalized
http_client stack. The current implementation focuses on
general-purpose bucket operations and AWS Signature Version 4 request
signing.
The library depends on the contributed xml_parser parser to decode
S3 XML responses and wraps it behind the s3_xml adapter so the
public API exposes stable S3-specific terms instead of generic XML parse
trees.
This library can be used with backend Prolog systems that support
unbound integer arithmetic and the sockets library: ECLiPSe, SICStus
Prolog, SWI-Prolog, Trealla Prolog, and XVM.
Loading
To load the library, load the loader.lgt file:
| ?- logtalk_load(s3(loader)).
Testing
To test this library, load the tester.lgt file:
| ?- logtalk_load(s3(tester)).
Current scope
list_buckets/2head_bucket/3list_objects_v2/4head_object/4get_object/5presigned_get_object/4put_object/6presigned_put_object/4presigned_post_object/4delete_object/4copy_object/5explicit session wrapper via
s3_session(_HTTPSocket_)AWS Signature Version 4 request signing for service
s3virtual-hosted and path-style endpoint generation
direct support for custom S3-compatible endpoints such as MinIO
Basic usage
For typical file transfers, prefer the file-based arities:
get_object/5downloads an object to a local file path and returns response metadata separately.put_object/6uploads a local file path and returns the object ETag and response metadata separately.
The presigned_get_object/4, presigned_put_object/4, and
presigned_post_object/4 predicates generate portable SigV4
query-string URLs for external HTTP clients. They default to
UNSIGNED-PAYLOAD, accept expires(Seconds) with a maximum of
604800 seconds, support signed payloads using
payload_hash_mode(signed) plus payload_hash(Hash), and sign any
extra request headers supplied using headers/1.
Result terms for the predicates returning a Result argument are:
delete_object/4->delete_result(Properties)copy_object/5->copy_result(ETag, Properties)
List buckets using the default TLS-capable transport:
| ?- s3_client::list_buckets(
Buckets,
[
credentials(access_key_id('AKIDEXAMPLE'), secret_access_key('secret')),
amz_date('20240627T120000Z')
]
).
Download report.txt from a custom S3-compatible endpoint into a
local file:
| ?- s3_client::get_object(
photos,
'report.txt',
'report.txt',
Properties,
[
endpoint('http://127.0.0.1:9000'),
addressing_style(path),
credentials(access_key_id('minioadmin'), secret_access_key('minioadmin')),
amz_date('20240627T120000Z')
]
).
Upload the same local report.txt file to the same custom endpoint:
| ?- s3_client::put_object(
photos,
'report.txt',
'report.txt',
ETag,
Properties,
[
endpoint('http://127.0.0.1:9000'),
addressing_style(path),
credentials(access_key_id('minioadmin'), secret_access_key('minioadmin')),
amz_date('20240627T120000Z')
]
).
Use an explicit session handle to carry defaults:
| ?- s3_session(http_socket_process)::open(
Session,
[
region('eu-west-1'),
credentials(access_key_id('AKIDEXAMPLE'), secret_access_key('secret')),
amz_date('20240627T120000Z')
]
),
s3_session(http_socket_process)::list_buckets(Session, Buckets, []),
s3_session(http_socket_process)::close(Session).
Generate a presigned download URL for report.txt:
| ?- s3_client::presigned_get_object(
photos,
'report.txt',
URL,
[
region('eu-west-1'),
credentials(access_key_id('AKIDEXAMPLE'), secret_access_key('secret')),
amz_date('20240627T120000Z'),
expires(600)
]
).
Generate a presigned upload URL for the same report.txt object:
| ?- s3_client::presigned_put_object(
photos,
'report.txt',
URL,
[
endpoint('http://127.0.0.1:9000'),
addressing_style(path),
credentials(access_key_id('minioadmin'), secret_access_key('minioadmin')),
headers([content_type-'text/plain']),
amz_date('20240627T120000Z'),
expires(300)
]
).
Generate a presigned POST URL for the same report.txt object:
| ?- s3_client::presigned_post_object(
photos,
'report.txt',
URL,
[
endpoint('http://127.0.0.1:9000'),
addressing_style(path),
credentials(access_key_id('minioadmin'), secret_access_key('minioadmin')),
amz_date('20240627T120000Z'),
expires(300)
]
).
Generate a presigned URL that signs a precomputed SHA-256 payload hash:
| ?- s3_client::presigned_put_object(
photos,
'report.txt',
URL,
[
region('eu-west-1'),
credentials(access_key_id('AKIDEXAMPLE'), secret_access_key('secret')),
amz_date('20240627T120000Z'),
payload_hash_mode(signed),
payload_hash('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824')
]
).
When using signed extra headers such as content_type-'text/plain',
the eventual HTTP client must send the same headers when dereferencing
the URL.
Current limitations
Time signing defaults derive UTC from the local system clock plus the configurable
utc_offset_seconds/1option. For deterministic use and tests, prefer passingamz_date/1orrequest_time/1.Multipart uploads are not implemented yet.
S3 Express / directory bucket APIs are outside the current scope.