Skip to content

Commit 19bb4bd

Browse files
authored
Updates the S3 PresignedUrl example to better standards. Also includes tests and improvements to AwsUtilities. (#6500)
1 parent 8d8e33d commit 19bb4bd

File tree

9 files changed

+366
-42
lines changed

9 files changed

+366
-42
lines changed

.doc_gen/metadata/s3_metadata.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -2534,6 +2534,13 @@ s3_Scenario_PresignedUrl:
25342534
- description: Upload using libcurl.
25352535
snippet_tags:
25362536
- cpp.example_code.s3.presigned.PutObjectUpload
2537+
PHP:
2538+
versions:
2539+
- sdk_version: 3
2540+
github: php/example_code/s3
2541+
excerpts:
2542+
- snippet_tags:
2543+
- s3.php.presigned_url.complete
25372544
services:
25382545
s3: {}
25392546
s3_Scenario_ObjectVersioningUsage:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<?php
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
namespace AwsUtilities;
6+
7+
use Aws\CommandInterface;
8+
use Aws\S3\S3Client;
9+
10+
/**
11+
* This class allows you to mock any AWSClient even when PHPUnit fails due to hidden, dynamic, or private
12+
* method calls which cannot be mocked normally.
13+
*
14+
* WARNING: This class *does not* do any type checking, so if you set the return values to an incompatible data type,
15+
* your tests will fail spectacularly.
16+
*/
17+
class MockS3Client extends S3Client {
18+
19+
protected array $returnValues = [];
20+
21+
public function set($methodName, $returnValue){
22+
$this->returnValues[$methodName] = $returnValue;
23+
}
24+
25+
public function __construct()
26+
{
27+
28+
}
29+
30+
public function __call($name, array $arguments)
31+
{
32+
return $this->returnValues[__FUNCTION__];
33+
}
34+
35+
public function getCommand($name, array $args = [])
36+
{
37+
return $this->returnValues[__FUNCTION__];
38+
}
39+
40+
public function execute(CommandInterface $command)
41+
{
42+
return $this->returnValues[__FUNCTION__];
43+
}
44+
45+
public function executeAsync(CommandInterface $command)
46+
{
47+
return $this->returnValues[__FUNCTION__];
48+
}
49+
50+
public function getCredentials()
51+
{
52+
return $this->returnValues[__FUNCTION__];
53+
}
54+
55+
public function getRegion()
56+
{
57+
return $this->returnValues[__FUNCTION__];
58+
}
59+
60+
public function getEndpoint()
61+
{
62+
return $this->returnValues[__FUNCTION__];
63+
}
64+
65+
public function getApi()
66+
{
67+
return $this->returnValues[__FUNCTION__];
68+
}
69+
70+
public function getConfig($option = null)
71+
{
72+
return $this->returnValues[__FUNCTION__];
73+
}
74+
75+
public function getHandlerList()
76+
{
77+
return $this->returnValues[__FUNCTION__];
78+
}
79+
80+
public function getIterator($name, array $args = [])
81+
{
82+
return $this->returnValues[__FUNCTION__];
83+
}
84+
85+
public function getPaginator($name, array $args = [])
86+
{
87+
return $this->returnValues[__FUNCTION__];
88+
}
89+
90+
public function waitUntil($name, array $args = [])
91+
{
92+
return $this->returnValues[__FUNCTION__];
93+
}
94+
95+
public function getWaiter($name, array $args = [])
96+
{
97+
return $this->returnValues[__FUNCTION__];
98+
}
99+
100+
public function createPresignedRequest(CommandInterface $command, $expires, array $options = [])
101+
{
102+
return $this->returnValues[__FUNCTION__];
103+
}
104+
105+
public function getObjectUrl($bucket, $key)
106+
{
107+
return $this->returnValues[__FUNCTION__];
108+
}
109+
110+
public function doesBucketExist($bucket)
111+
{
112+
return $this->returnValues[__FUNCTION__];
113+
}
114+
115+
public function doesBucketExistV2($bucket, $accept403 = false)
116+
{
117+
return $this->returnValues[__FUNCTION__];
118+
}
119+
120+
public function doesObjectExist($bucket, $key, array $options = [])
121+
{
122+
return $this->returnValues[__FUNCTION__];
123+
}
124+
125+
public function doesObjectExistV2($bucket, $key, $includeDeleteMarkers = false, array $options = [])
126+
{
127+
return $this->returnValues[__FUNCTION__];
128+
}
129+
130+
public function registerStreamWrapper()
131+
{
132+
return $this->returnValues[__FUNCTION__];
133+
}
134+
135+
public function registerStreamWrapperV2()
136+
{
137+
return $this->returnValues[__FUNCTION__];
138+
}
139+
140+
public function deleteMatchingObjects($bucket, $prefix = '', $regex = '', array $options = [])
141+
{
142+
return $this->returnValues[__FUNCTION__];
143+
}
144+
145+
public function deleteMatchingObjectsAsync($bucket, $prefix = '', $regex = '', array $options = [])
146+
{
147+
return $this->returnValues[__FUNCTION__];
148+
}
149+
150+
public function upload($bucket, $key, $body, $acl = 'private', array $options = [])
151+
{
152+
return $this->returnValues[__FUNCTION__];
153+
}
154+
155+
public function uploadAsync($bucket, $key, $body, $acl = 'private', array $options = [])
156+
{
157+
return $this->returnValues[__FUNCTION__];
158+
}
159+
160+
public function copy($fromBucket, $fromKey, $destBucket, $destKey, $acl = 'private', array $options = [])
161+
{
162+
return $this->returnValues[__FUNCTION__];
163+
}
164+
165+
public function copyAsync($fromBucket, $fromKey, $destBucket, $destKey, $acl = 'private', array $options = [])
166+
{
167+
return $this->returnValues[__FUNCTION__];
168+
}
169+
170+
public function uploadDirectory($directory, $bucket, $keyPrefix = null, array $options = [])
171+
{
172+
return $this->returnValues[__FUNCTION__];
173+
}
174+
175+
public function uploadDirectoryAsync($directory, $bucket, $keyPrefix = null, array $options = [])
176+
{
177+
return $this->returnValues[__FUNCTION__];
178+
}
179+
180+
public function downloadBucket($directory, $bucket, $keyPrefix = '', array $options = [])
181+
{
182+
return $this->returnValues[__FUNCTION__];
183+
}
184+
185+
public function downloadBucketAsync($directory, $bucket, $keyPrefix = '', array $options = [])
186+
{
187+
return $this->returnValues[__FUNCTION__];
188+
}
189+
190+
public function determineBucketRegion($bucketName)
191+
{
192+
return $this->returnValues[__FUNCTION__];
193+
}
194+
195+
public function determineBucketRegionAsync($bucketName)
196+
{
197+
return $this->returnValues[__FUNCTION__];
198+
}
199+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
namespace AwsUtilities;
6+
7+
trait PrintableLineBreak {
8+
public function getLineBreak(): string {
9+
return "--------------------------------------\n";
10+
}
11+
}

php/example_code/aws_utilities/TestableReadline.php

+11
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,14 @@ function testable_readline($prompt)
2424
}
2525
return readline($prompt);
2626
}
27+
28+
trait TestableReadline {
29+
function testable_readline($prompt)
30+
{
31+
global $LINES;
32+
if ($LINES && count($LINES) > 0) {
33+
return array_shift($LINES);
34+
}
35+
return readline($prompt);
36+
}
37+
}

php/example_code/s3/PresignedURL.php

+46-42
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,56 @@
22
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
// SPDX-License-Identifier: Apache-2.0
44

5-
/*
6-
* ABOUT THIS PHP SAMPLE: This sample is part of the SDK for PHP Developer Guide topic at
7-
* https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/service/s3-presigned-url.html
8-
*
9-
*/
105
// snippet-start:[s3.php.presigned_url.complete]
6+
namespace S3;
117
// snippet-start:[s3.php.presigned_url.import]
8+
use Aws\Exception\AwsException;
9+
use AwsUtilities\PrintableLineBreak;
10+
use AwsUtilities\TestableReadline;
11+
use DateTime;
1212

1313
require 'vendor/autoload.php';
14-
1514
// snippet-end:[s3.php.presigned_url.import]
1615

17-
//Creating a presigned request
18-
// snippet-start:[s3.php.presigned_url.main]
19-
// snippet-start:[s3.php.presigned_url.get_object]
20-
$s3Client = new Aws\S3\S3Client([
21-
'profile' => 'default',
22-
'region' => 'us-east-2',
23-
'version' => '2006-03-01',
24-
]);
25-
26-
$cmd = $s3Client->getCommand('GetObject', [
27-
'Bucket' => 'my-bucket',
28-
'Key' => 'testKey'
29-
]);
30-
31-
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
32-
// snippet-end:[s3.php.presigned_url.get_object]
33-
34-
// snippet-start:[s3.php.presigned_url.create_url]
35-
//Creating a presigned URL
36-
$cmd = $s3Client->getCommand('GetObject', [
37-
'Bucket' => 'my-bucket',
38-
'Key' => 'testKey'
39-
]);
40-
41-
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
42-
43-
// Get the actual presigned-url
44-
$presignedUrl = (string)$request->getUri();
45-
// snippet-end:[s3.php.presigned_url.create_url]
46-
47-
// snippet-start:[s3.php.presigned_url.get_url]
48-
//Getting the URL to an object
49-
$url = $s3Client->getObjectUrl('my-bucket', 'my-key');
50-
// snippet-end:[s3.php.presigned_url.get_url]
51-
52-
// snippet-end:[s3.php.presigned_url.main]
16+
class PresignedURL
17+
{
18+
use PrintableLineBreak;
19+
use TestableReadline;
20+
21+
public function run()
22+
{
23+
// snippet-start:[s3.php.presigned_url.main]
24+
$s3Service = new S3Service();
25+
26+
$expiration = new DateTime("+20 minutes");
27+
$linebreak = $this->getLineBreak();
28+
29+
echo $linebreak;
30+
echo ("Welcome to the Amazon S3 presigned URL demo.\n");
31+
echo $linebreak;
32+
33+
$bucket = $this->testable_readline("First, please enter the name of the S3 bucket to use: ");
34+
$key = $this->testable_readline("Next, provide the key of an object in the given bucket: ");
35+
echo $linebreak;
36+
$command = $s3Service->getClient()->getCommand('GetObject', [
37+
'Bucket' => $bucket,
38+
'Key' => $key,
39+
]);
40+
try {
41+
$preSignedUrl = $s3Service->preSignedUrl($command, $expiration);
42+
echo "Your preSignedUrl is \n$preSignedUrl\nand will be good for the next 20 minutes.\n";
43+
echo $linebreak;
44+
echo "Thanks for trying the Amazon S3 presigned URL demo.\n";
45+
} catch (AwsException $exception) {
46+
echo $linebreak;
47+
echo "Something went wrong: $exception";
48+
die();
49+
}
50+
// snippet-end:[s3.php.presigned_url.main]
51+
}
52+
}
53+
54+
$runner = new PresignedURL();
55+
$runner->run();
56+
5357
// snippet-end:[s3.php.presigned_url.complete]

php/example_code/s3/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Code excerpts that show you how to call individual service functions.
5151
Code examples that show you how to accomplish a specific task by calling multiple
5252
functions within the same service.
5353

54+
- [Create a presigned URL](PresignedURL.php)
5455
- [Get started with buckets and objects](GettingStartedWithS3.php)
5556

5657
### Cross-service examples
@@ -77,6 +78,18 @@ This example shows you how to get started using Amazon S3.
7778

7879

7980

81+
#### Create a presigned URL
82+
83+
This example shows you how to create a presigned URL for Amazon S3 and upload an object.
84+
85+
86+
<!--custom.scenario_prereqs.s3_Scenario_PresignedUrl.start-->
87+
<!--custom.scenario_prereqs.s3_Scenario_PresignedUrl.end-->
88+
89+
90+
<!--custom.scenarios.s3_Scenario_PresignedUrl.start-->
91+
<!--custom.scenarios.s3_Scenario_PresignedUrl.end-->
92+
8093
#### Get started with buckets and objects
8194

8295
This example shows you how to do the following:

0 commit comments

Comments
 (0)