Skip to content

Commit 8b2e137

Browse files
update design after surface API Review (#6292)
1 parent 1133ea0 commit 8b2e137

File tree

2 files changed

+44
-67
lines changed

2 files changed

+44
-67
lines changed

docs/design/core/presignedURL-Get/DecisionLog.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# S3 Pre-signed URL GET - Decision Log
33

44
## Review Meeting: 06/17/2025
5-
**Attendees**: Alban, John, Zoe, Dongie, Bole, Ran, Saranya
5+
**Attendees**: Alban Gicquel, John Viegas, Zoe Wang, Dongie Agnir, Bole Yi, Ran Vaknin, Saranya Somepalli
66

77
### Closed Decisions
88

@@ -21,7 +21,7 @@
2121
3. What should we name the Helper API? Options include PresignedURLManager or PresignedUrlExtension. Will be addressed in the Surface API Review.
2222

2323
## Review Meeting: 06/23/2025
24-
**Attendees**: John, Zoe, Dongie, Bole, Ran, Saranya, Alex, David
24+
**Attendees**: John Viegas, Zoe Wang, Dongie Agnir, Bole Yi, Ran Vaknin, Saranya Somepalli, David Ho
2525

2626
### Decisions Addressed
2727

@@ -32,7 +32,24 @@
3232
3. Use separate rangeStart/rangeEnd fields vs single range string parameter. Decided to use separate rangeStart and rangeEnd Long fields for better user experience, as start/end is more intuitive than string parsing.
3333

3434
## Decision Poll Meeting: 06/30/2025
35-
**Attendees**: John, Zoe, Dongie, Bole, Ran, Saranya, Alex
35+
**Attendees**: John Viegas, Zoe Wang, Dongie Agnir, Bole Yi, Ran Vaknin, Saranya Somepalli, David Ho, Alex Woods
3636

3737
### Decision Addressed
3838
Decided to use String range field for Request object to support all RFC 7233 formats including suffix ranges (bytes=-100) and future multi-range support, since S3 currently doesn't support multiple ranges but may in the future without requiring SDK changes.
39+
40+
## Post-standup Meeting: 07/14/2025
41+
**Attendees**: Alban Gicquel, John Viegas, Zoe Wang, Dongie Agnir, Bole Yi, Ran Vaknin, Saranya Somepalli, David Ho, Alex Woods
42+
43+
### Decision Addressed
44+
The team has decided to implement functionality only for S3 async client and defer S3 sync client implementation for now. This decision was made because implementing S3 sync client would require supporting multipart download capabilities.
45+
46+
## API Surface Area Review: 07/21/2025
47+
**Attendees**: John Viegas, Zoe Wang, Dongie Agnir, Bole Yi, Ran Vaknin, Saranya Somepalli, David Ho, Alex Woods
48+
49+
### Decisions Addressed
50+
51+
1. Decided on the naming for the surface APIs - AsyncPresignedUrlExtension for the new core API, presignedUrlExtension() for the method to call from the AsyncS3Client and PresignedUrlDownloadRequest for the Get Object Request. Also decided to have PresignedUrlDownload as the Operation Name for metric collection.
52+
53+
2. Remove the consumer builder pattern from Get Request Model.
54+
55+
3. throw UnsupportedOperationException for Multipart S3 Client and S3 CRT Client for now.

docs/design/core/presignedURL-Get/Design.md

Lines changed: 24 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,52 @@ This document proposes how this functionality should be implemented in the Java
1010

1111
Look at decision log here: [Decision Log Section](DecisionLog.md)
1212

13-
The Java SDK team has decided to implement a separate `PresignedUrlManager`. The team chose the helper API pattern over direct `S3Client` integration to maintain clean separation of concerns while preserving SDK functionality.
13+
The Java SDK team has decided to implement a separate `AsyncPresignedUrlExtension`. The team chose the helper API pattern over direct `S3AsyncClient` integration to maintain clean separation of concerns while preserving SDK functionality.
1414

1515
## Overview
1616

17-
The design introduces new helper APIs `AsyncPresignedUrlManager` and `PresignedUrlManager` which can be instantiated via the existing `S3AsyncClient` and `S3Client` respectively. These managers provide a clean abstraction layer that preserves SDK benefits while handling the unique requirements of pre-signed URL requests.
17+
The design introduces a new helper API `AsyncPresignedUrlExtension` which can be instantiated via the existing `S3AsyncClient`. This extension provides a clean abstraction layer that preserves SDK benefits while handling the unique requirements of pre-signed URL requests.
1818

19-
This design will implement only the GET /download function for presigned URLs.
19+
This design will implement only the GET /download function for presigned URLs for the S3AsyncClient. The synchronous S3Client implementation is deferred to future work.
2020

2121

2222

2323
## Proposed APIs
2424

25-
The v2 SDK will support a presigned URL manager for both sync and async clients that can leverage pre-signed URL downloads.
25+
The v2 SDK will support a presigned URL extension for the async client that can leverage pre-signed URL downloads.
2626

2727
### Instantiation
2828
Instantiating from existing client:
2929

3030
```java
31-
// Async Presigned URL Manager
31+
// Async Presigned URL Extension
3232
S3AsyncClient s3Client = S3AsyncClient.create();
33-
AsyncPresignedUrlManager presignManager = s3Client.presignedManager();
34-
35-
// Sync Presigned URL Manager
36-
S3Client s3Client = S3Client.create();
37-
PresignedUrlManager presignManager = s3Client.presignedManager();
33+
AsyncPresignedUrlExtension presignExtension = s3Client.presignedUrlExtension();
3834
```
3935

4036
### General Usage Examples
4137

4238
```java
4339
// Create presigned URL request
44-
PresignedUrlGetObjectRequest request = PresignedUrlGetObjectRequest.builder()
40+
PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder()
4541
.presignedUrl(presignedUrl)
4642
.range("range=0-1024")
4743
.build();
4844

4945
// Async usage
5046
S3AsyncClient s3Client = S3AsyncClient.create();
51-
AsyncPresignedUrlManager presignManager = s3Client.presignedManager();
52-
CompletableFuture<GetObjectResponse> response = presignManager.getObject(request);
53-
54-
// Sync usage
55-
S3Client s3Client = S3Client.create();
56-
PresignedUrlManager presignManager = s3Client.presignedManager();
57-
GetObjectResponse response = presignManager.getObject(request);
47+
AsyncPresignedUrlExtension presignedUrlExtension = s3Client.presignedUrlExtension();
48+
CompletableFuture<GetObjectResponse> response = presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes());
5849
```
5950

60-
### AsyncPresignedUrlManager Interface
51+
### AsyncPresignedUrlExtension Interface
6152

6253
```java
6354
/**
6455
* Interface for presigned URL operations used by Async clients.
6556
*/
6657
@SdkPublicApi
67-
public interface AsyncPresignedUrlManager {
58+
public interface AsyncPresignedUrlExtension {
6859

6960
/**
7061
* Downloads S3 objects using pre-signed URLs with custom response transformation.
@@ -73,60 +64,26 @@ public interface AsyncPresignedUrlManager {
7364
* @param responseTransformer custom transformer for processing the response.
7465
* @return a CompletableFuture of the transformed response.
7566
*/
76-
<T> CompletableFuture<T> getObject(PresignedUrlGetObjectRequest request,
67+
<T> CompletableFuture<T> getObject(PresignedUrlDownloadRequest request,
7768
AsyncResponseTransformer<GetObjectResponse, T> responseTransformer);
7869

7970
// Additional getObject() overloads for file downloads, byte arrays, etc.
8071
// Standard Builder interface with client() and overrideConfiguration() methods
8172
}
8273
```
8374

84-
### PresignedUrlManager Interface
85-
86-
```java
87-
/**
88-
* Interface for presigned URL operations used by Sync clients.
89-
*/
90-
@SdkPublicApi
91-
public interface PresignedUrlManager {
92-
93-
/**
94-
* Downloads S3 objects using pre-signed URLs. Bypasses normal authentication
95-
* and endpoint resolution while maintaining SDK benefits like retries and metrics.
96-
*
97-
* @param request the presigned URL request containing URL and optional range parameters.
98-
* @return the GetObjectResponse.
99-
*/
100-
GetObjectResponse getObject(PresignedUrlGetObjectRequest request);
101-
102-
/**
103-
* Downloads S3 objects using pre-signed URLs with custom response transformation.
104-
*
105-
* @param request the presigned URL request.
106-
* @param responseTransformer custom transformer for processing the response.
107-
* @return the transformed response.
108-
*/
109-
<T> T getObject(PresignedUrlGetObjectRequest request,
110-
ResponseTransformer<GetObjectResponse, T> responseTransformer);
111-
112-
// Additional getObject() overloads for file downloads, byte arrays, etc.
113-
// Standard Builder interface with client() and overrideConfiguration() methods
114-
}
115-
```
116-
117-
### PresignedUrlGetObjectRequest
75+
### PresignedUrlDownloadRequest
11876

11977
```java
12078
/**
12179
* Request object for presigned URL GET operations.
12280
*/
12381
@SdkPublicApi
124-
@Immutable
12582
@ThreadSafe
126-
public final class PresignedUrlGetObjectRequest
127-
implements ToCopyableBuilder<PresignedUrlGetObjectRequest.Builder, PresignedUrlGetObjectRequest> {
83+
public final class PresignedUrlDownloadRequest
84+
implements ToCopyableBuilder<PresignedUrlDownloadRequest.Builder, PresignedUrlDownloadRequest> {
12885

129-
private final String presignedUrl;
86+
private final URL presignedUrl;
13087
private final String range;
13188

13289
// Standard getters: presignedUrl(), range()
@@ -137,11 +94,11 @@ public final class PresignedUrlGetObjectRequest
13794

13895
## FAQ
13996

140-
### Why don't we implement presigned URL download/GET feature directly on the S3Client?
97+
### Why don't we implement presigned URL download/GET feature directly on the S3AsyncClient?
14198

14299
Three approaches were considered:
143100

144-
1. **Dedicated PresignedUrlManager (CHOSEN)**: Separate manager accessed via `s3Client.presignedManager()`
101+
1. **Dedicated AsyncPresignedUrlExtension (CHOSEN)**: Separate extension accessed via `s3AsyncClient.presignedUrlExtension()`
145102
- **Pros**: Clean separation, preserves SDK features, follows v2 patterns
146103
- **Cons**: New API surface for users to learn
147104

@@ -153,12 +110,15 @@ Three approaches were considered:
153110
- **Pros**: Logical extension of presigner concept
154111
- **Cons**: Breaks current stateless presigner patterns
155112

156-
**Decision**: Option 1 provides clean separation while preserving SDK benefits and following established v2 utility patterns.cutePresignedGetObject(presignedRequest);
113+
**Decision**: Option 1 provides clean separation while preserving SDK benefits and following established v2 utility patterns.
157114

158-
### Why doesn't PresignedUrlGetObjectRequest extend S3Request?
115+
### What about synchronous S3Client and S3 CRT Client support?
159116

160-
While extending S3Request would provide access to RequestOverrideConfiguration, many of these configurations (like credentials provider, signers) are not supported with presigned URL execution. Instead, we use a standalone request with only essential parameters (presignedUrl, range). Internally, this gets wrapped in an encapsulated class that extends S3Request for use with ClientHandler.
117+
The synchronous S3Client implementation has been deferred to future work due to complexities around multipart download requirements. Support for S3CrtAsyncClient will also be added in future work once the AWS CRT team addresses current limitations with pre-signed URL handling.
118+
119+
### Why doesn't PresignedUrlDownloadRequest extend S3Request?
161120

121+
While extending S3Request would provide access to RequestOverrideConfiguration, many of these configurations (like credentials provider, signers) are not supported with presigned URL execution. Instead, we use a standalone request with only essential parameters (presignedUrl, range). Internally, this gets wrapped in an encapsulated class that extends S3Request for use with ClientHandler.
162122

163123
## References
164124

0 commit comments

Comments
 (0)