Skip to content

Commit 5dc3e91

Browse files
authored
Merge branch 'main' into dotnet-version-updates-pt1
2 parents 9ffaf84 + 054c03e commit 5dc3e91

File tree

45 files changed

+6093
-29
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+6093
-29
lines changed

.doc_gen/metadata/s3-directory-buckets_metadata.yaml

Lines changed: 414 additions & 2 deletions
Large diffs are not rendered by default.

.doc_gen/metadata/s3_metadata.yaml

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,7 +2704,25 @@ s3_Scenario_PresignedUrl:
27042704
github: javav2/example_code/s3
27052705
sdkguide:
27062706
excerpts:
2707-
- description: Generate a pre-signed URL for an object, then download it (GET request).
2707+
- description: >-
2708+
<para>The following shows three example of how to create presigned URLs and use the URLs with
2709+
HTTP client libraries:</para>
2710+
<itemizedlist>
2711+
<listitem>
2712+
<para>An HTTP GET request that uses the URL with three HTTP client libraries</para>
2713+
</listitem>
2714+
<listitem>
2715+
<para>An HTTP PUT request with metadata in headers that uses the URL with three HTTP client
2716+
libraries</para>
2717+
</listitem>
2718+
<listitem>
2719+
<para>An HTTP PUT request with query parameters that uses the URL with one HTTP client
2720+
library</para>
2721+
</listitem>
2722+
</itemizedlist>
2723+
<para>
2724+
<emphasis role="bold">Generate a pre-signed URL for an object, then download it (GET request).</emphasis>
2725+
</para>
27082726
- description: Imports.
27092727
snippet_tags:
27102728
- presigned.java2.generatepresignedgeturlandretrieve.import
@@ -2722,7 +2740,7 @@ s3_Scenario_PresignedUrl:
27222740
snippet_tags:
27232741
- presigned.java2.generatepresignedgeturlandretrieve.sdkhttpclient
27242742

2725-
- description: Generate a pre-signed URL for an upload, then upload a file (PUT request).
2743+
- description: <emphasis role="bold">Generate a pre-signed URL with metadata in headers for an upload, then upload a file (PUT request).</emphasis>
27262744
- description: Imports.
27272745
snippet_tags:
27282746
- presigned.java2.generatepresignedurlandputfilewithmetadata.import
@@ -2739,6 +2757,17 @@ s3_Scenario_PresignedUrl:
27392757
- description: Use the &AWS; for Java V2 <code>SdkHttpClient</code> class to do the upload.
27402758
snippet_tags:
27412759
- presigned.java2.generatepresignedurlandputfilewithmetadata.sdkhttpclient
2760+
2761+
- description: <emphasis role="bold">Generate a pre-signed URL with query parameters for an upload, then upload a file (PUT request).</emphasis>
2762+
- description: Imports.
2763+
snippet_tags:
2764+
- presigned.java2.generatepresignedurlandputfilewithqueryparams.import
2765+
- description: Generate the URL.
2766+
snippet_tags:
2767+
- presigned.java2.generatepresignedurlandputfilewithqueryparams.createpresignedurl
2768+
- description: Use the &AWS; for Java V2 <code>SdkHttpClient</code> class to do the upload.
2769+
snippet_tags:
2770+
- presigned.java2.generatepresignedurlandputfilewithqueryparams.sdkhttpclient
27422771
Python:
27432772
versions:
27442773
- sdk_version: 3

.tools/readmes/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"sdk_api_ref": 'https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/{{service["name"]}}/package-summary.html',
5555
"service_folder_overrides": {
5656
"s3-control": "javav2/example_code/s3/src/main/java/com/example/s3/batch",
57+
"s3-directory-buckets": "javav2/example_code/s3/src/main/java/com/example/s3/directorybucket",
5758
"medical-imaging": "javav2/example_code/medicalimaging",
5859
},
5960
},

.tools/readmes/render.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ def render(self) -> RenderStatus:
304304
customs=customs,
305305
unsupported=unsupported,
306306
)
307+
self.readme_text += "\n" # Jinja is the worst and strips trailing new lines
307308
[text, errors] = expand_all_entities(self.readme_text, self.scanner.doc_gen.entities)
308309
if errors:
309310
raise errors
@@ -332,7 +333,11 @@ def write(self):
332333
def read_current(self):
333334
try:
334335
with self.readme_filename.open("r", encoding="utf-8") as f:
335-
return f.read()
336+
current = f.read()
337+
if current[-1] != "\n":
338+
# Ensure there's always an ending newline
339+
current += "\n"
340+
return current
336341
except FileNotFoundError:
337342
return ""
338343

javascriptv3/example_code/cross-services/wkflw-pools-triggers/tests/scenario-auto-confirm.integration.test.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,18 @@ describe("Scenario - AutoConfirm", () => {
3434
Capabilities: [Capability.CAPABILITY_NAMED_IAM],
3535
}),
3636
);
37-
await retry({ intervalInMs: 2000, maxRetries: 60 }, async () => {
38-
const { Stacks } = await cloudformationClient.send(
39-
new DescribeStacksCommand({ StackName: stackName }),
40-
);
41-
const stack = Stacks[0];
42-
if (stack.StackStatus !== "CREATE_COMPLETE") {
43-
throw new Error("Stack creation incomplete.");
44-
}
45-
});
37+
await retry(
38+
{ intervalInMs: 2000, maxRetries: 60, backoff: 1000 },
39+
async () => {
40+
const { Stacks } = await cloudformationClient.send(
41+
new DescribeStacksCommand({ StackName: stackName }),
42+
);
43+
const stack = Stacks[0];
44+
if (stack.StackStatus !== "CREATE_COMPLETE") {
45+
throw new Error("Stack creation incomplete.");
46+
}
47+
},
48+
);
4649
});
4750

4851
afterAll(async () => {

javascriptv3/example_code/libs/utils/util-timers.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ const wait = (seconds) =>
1010

1111
/**
1212
* @template T
13-
* @param {{ intervalInMs: number, maxRetries: number, swallowError?: boolean, quiet?: boolean }} config
13+
* @param {{ intervalInMs: number, maxRetries: number, backoff?: number, swallowError?: boolean, quiet?: boolean }} config
1414
* @param {() => Promise<T>} fn
1515
* @returns {Promise<T>}
1616
*/
1717
const retry = (config, fn) =>
1818
new Promise((resolve, reject) => {
19-
const { intervalInMs = 500, maxRetries = 10 } = config;
19+
const { intervalInMs = 500, maxRetries = 10, backoff = 0 } = config;
2020
fn()
2121
.then(resolve)
2222
.catch((err) => {
@@ -32,10 +32,14 @@ const retry = (config, fn) =>
3232
config.swallowError ? resolve() : reject(err);
3333
} else {
3434
setTimeout(() => {
35-
retry({ ...config, maxRetries: maxRetries - 1 }, fn).then(
36-
resolve,
37-
reject,
38-
);
35+
retry(
36+
{
37+
...config,
38+
intervalInMs: intervalInMs + backoff,
39+
maxRetries: maxRetries - 1,
40+
},
41+
fn,
42+
).then(resolve, reject);
3943
}, intervalInMs);
4044
}
4145
});

javav2/example_code/s3/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ functions within the same service.
9898

9999
<!--custom.examples.start-->
100100
- [Create a presigned URL for download](src/main/java/com/example/s3/GeneratePresignedGetUrlAndRetrieve.java)
101-
- [Create a presigned URL for upload](src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java)
101+
- [Create a presigned URL with metadata in headers for upload](src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java)
102+
- [Create a presigned URL with query parameters for upload](src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithQueryParams.java)
102103
<!--custom.examples.end-->
103104

104105
## Run the examples

javav2/example_code/s3/checkstyle.xml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
<?xml version="1.0" ?>
22

33
<!DOCTYPE module PUBLIC
4-
"-//Checkstyle//DTD Checkstyle Configuration 1.2//EN"
5-
"https://checkstyle.org/dtds/configuration_1_2.dtd">
4+
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
5+
"https://checkstyle.org/dtds/configuration_1_3.dtd">
66

77
<module name="Checker">
88
<module name="TreeWalker">
99

10-
<module name="IllegalCatch"/>
10+
<module name="IllegalCatch">
11+
<property name="illegalClassNames" value="Error,Exception,Throwable,java.lang.Error,java.lang.Exception,java.lang.Throwable"/>
12+
</module>
1113
<module name="EmptyStatement"/>
1214
<module name="AvoidStarImport"/>
1315
<module name="UnusedImports"/>
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.example.s3;
5+
6+
// snippet-start:[presigned.java2.generatepresignedurlandputfilewithqueryparams.import]
7+
import com.example.s3.util.PresignUrlUtils;
8+
import org.slf4j.Logger;
9+
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
10+
import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider;
11+
import software.amazon.awssdk.http.HttpExecuteRequest;
12+
import software.amazon.awssdk.http.HttpExecuteResponse;
13+
import software.amazon.awssdk.http.SdkHttpClient;
14+
import software.amazon.awssdk.http.SdkHttpMethod;
15+
import software.amazon.awssdk.http.SdkHttpRequest;
16+
import software.amazon.awssdk.http.apache.ApacheHttpClient;
17+
import software.amazon.awssdk.services.s3.S3Client;
18+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
19+
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
20+
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
21+
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;
22+
23+
import java.io.File;
24+
import java.io.IOException;
25+
import java.net.URISyntaxException;
26+
import java.net.URL;
27+
import java.nio.file.Paths;
28+
import java.time.Duration;
29+
import java.util.Map;
30+
import java.util.UUID;
31+
// snippet-end:[presigned.java2.generatepresignedurlandputfilewithqueryparams.import]
32+
33+
/**
34+
* Before running this Java V2 code example, set up your development environment.
35+
* <p>
36+
* For more information, see the following documentation topic:
37+
* <p>
38+
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
39+
*/
40+
41+
public class GeneratePresignedUrlAndPutFileWithQueryParams {
42+
private static final Logger logger = org.slf4j.LoggerFactory.getLogger(GeneratePresignedUrlAndPutFileWithQueryParams.class);
43+
private final static S3Client s3Client = S3Client.create();
44+
45+
public static void main(String[] args) {
46+
String bucketName = "amzn-s3-demo-bucket" + UUID.randomUUID(); // Change bucket name.
47+
String keyName = "key" + UUID.randomUUID();
48+
String resourcePath = "uploadDirectory/file1.txt";
49+
// Uncomment the following two lines and comment out the previous two lines to use an image file instead of a PDF file.
50+
//String resourcePath = "image.png";
51+
//String contentType = "image/png";
52+
53+
Map<String, String> queryParams = Map.of(
54+
"x-amz-meta-author", "Bob",
55+
"x-amz-meta-version", "1.0.0.0",
56+
"x-amz-acl", "private",
57+
"x-amz-server-side-encryption", "AES256"
58+
);
59+
60+
PresignUrlUtils.createBucket(bucketName, s3Client);
61+
GeneratePresignedUrlAndPutFileWithQueryParams presign = new GeneratePresignedUrlAndPutFileWithQueryParams();
62+
try {
63+
String presignedUrlString = presign.createPresignedUrl(bucketName, keyName, queryParams);
64+
presign.useSdkHttpClientToPut(presignedUrlString, getFileForForClasspathResource(resourcePath));
65+
66+
} finally {
67+
PresignUrlUtils.deleteObject(bucketName, keyName, s3Client);
68+
PresignUrlUtils.deleteBucket(bucketName, s3Client);
69+
}
70+
}
71+
72+
// snippet-start:[presigned.java2.generatepresignedurlandputfilewithqueryparams.main]
73+
// snippet-start:[presigned.java2.generatepresignedurlandputfilewithqueryparams.createpresignedurl]
74+
/**
75+
* Creates a presigned URL to use in a subsequent HTTP PUT request. The code adds query parameters
76+
* to the request instead of using headers. By using query parameters, you do not need to add the
77+
* the parameters as headers when the PUT request is eventually sent.
78+
*
79+
* @param bucketName Bucket name where the object will be uploaded.
80+
* @param keyName Key name of the object that will be uploaded.
81+
* @param queryParams Query string parameters to be added to the presigned URL.
82+
* @return
83+
*/
84+
public String createPresignedUrl(String bucketName, String keyName, Map<String, String> queryParams) {
85+
try (S3Presigner presigner = S3Presigner.create()) {
86+
// Create an override configuration to store the query parameters.
87+
AwsRequestOverrideConfiguration.Builder overrideConfigurationBuilder = AwsRequestOverrideConfiguration.builder();
88+
89+
queryParams.forEach(overrideConfigurationBuilder::putRawQueryParameter);
90+
91+
PutObjectRequest objectRequest = PutObjectRequest.builder()
92+
.bucket(bucketName)
93+
.key(keyName)
94+
.overrideConfiguration(overrideConfigurationBuilder.build()) // Add the override configuration.
95+
.build();
96+
97+
PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
98+
.signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes.
99+
.putObjectRequest(objectRequest)
100+
.build();
101+
102+
103+
PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);
104+
String myURL = presignedRequest.url().toString();
105+
logger.info("Presigned URL to upload a file to: [{}]", myURL);
106+
logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method());
107+
108+
return presignedRequest.url().toExternalForm();
109+
}
110+
}
111+
// snippet-end:[presigned.java2.generatepresignedurlandputfilewithqueryparams.createpresignedurl]
112+
113+
// snippet-start:[presigned.java2.generatepresignedurlandputfilewithqueryparams.sdkhttpclient]
114+
/**
115+
* Use the AWS SDK for Java V2 SdkHttpClient class to execute the PUT request. Since the
116+
* URL contains the query parameters, no headers are needed for metadata, SSE settings, or ACL settings.
117+
*
118+
* @param presignedUrlString The URL for the PUT request.
119+
* @param fileToPut File to uplaod
120+
*/
121+
public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut) {
122+
logger.info("Begin [{}] upload", fileToPut.toString());
123+
124+
try {
125+
URL presignedUrl = new URL(presignedUrlString);
126+
127+
SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder()
128+
.method(SdkHttpMethod.PUT)
129+
.uri(presignedUrl.toURI());
130+
131+
SdkHttpRequest request = requestBuilder.build();
132+
133+
HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
134+
.request(request)
135+
.contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath()))
136+
.build();
137+
138+
try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
139+
HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
140+
logger.info("Response code: {}", response.httpResponse().statusCode());
141+
}
142+
} catch (URISyntaxException | IOException e) {
143+
logger.error(e.getMessage(), e);
144+
}
145+
}
146+
// snippet-end:[presigned.java2.generatepresignedurlandputfilewithqueryparams.sdkhttpclient]
147+
// snippet-end:[presigned.java2.generatepresignedurlandputfilewithqueryparams.main]
148+
149+
public static File getFileForForClasspathResource(String resourcePath) {
150+
try {
151+
URL resource = GeneratePresignedUrlAndUploadObject.class.getClassLoader().getResource(resourcePath);
152+
return Paths.get(resource.toURI()).toFile();
153+
} catch (URISyntaxException e) {
154+
logger.error(e.getMessage(), e);
155+
}
156+
return null;
157+
}
158+
}

0 commit comments

Comments
 (0)