Version Description
Download this release
Release Info
Developer | FolioVision |
Plugin | FV Flowplayer Video Player |
Version | 7.2.1.727 |
Comparing to | |
See all releases |
Code changes from version 7.1.15.727 to 7.2.1.727
- controller/backend.php +1 -18
- controller/editor.php +1 -1
- controller/settings.php +22 -0
- css/bigplay.svg +50 -1
- css/controls.svg +172 -1
- css/flowplayer.css +1 -0
- css/s3-browser.css +456 -0
- css/shortcode-editor.css +4 -0
- flowplayer.php +16 -11
- flowplayer/fv-flowplayer.min.js +2 -1
- includes/aws/Aws/Api/AbstractModel.php +67 -0
- includes/aws/Aws/Api/ApiProvider.php +241 -0
- includes/aws/Aws/Api/DateTimeResult.php +41 -0
- includes/aws/Aws/Api/DocModel.php +128 -0
- includes/aws/Aws/Api/ErrorParser/JsonParserTrait.php +26 -0
- includes/aws/Aws/Api/ErrorParser/JsonRpcErrorParser.php +31 -0
- includes/aws/Aws/Api/ErrorParser/RestJsonErrorParser.php +35 -0
- includes/aws/Aws/Api/ErrorParser/XmlErrorParser.php +82 -0
- includes/aws/Aws/Api/ListShape.php +35 -0
- includes/aws/Aws/Api/MapShape.php +54 -0
- includes/aws/Aws/Api/Operation.php +97 -0
- includes/aws/Aws/Api/Parser/AbstractParser.php +35 -0
- includes/aws/Aws/Api/Parser/AbstractRestParser.php +154 -0
- includes/aws/Aws/Api/Parser/Crc32ValidatingParser.php +47 -0
- includes/aws/Aws/Api/Parser/Exception/ParserException.php +4 -0
- includes/aws/Aws/Api/Parser/JsonParser.php +58 -0
- includes/aws/Aws/Api/Parser/JsonRpcParser.php +40 -0
- includes/aws/Aws/Api/Parser/PayloadParserTrait.php +51 -0
- includes/aws/Aws/Api/Parser/QueryParser.php +52 -0
- includes/aws/Aws/Api/Parser/RestJsonParser.php +39 -0
- includes/aws/Aws/Api/Parser/RestXmlParser.php +36 -0
- includes/aws/Aws/Api/Parser/XmlParser.php +134 -0
- includes/aws/Aws/Api/Serializer/Ec2ParamBuilder.php +40 -0
- includes/aws/Aws/Api/Serializer/JsonBody.php +90 -0
- includes/aws/Aws/Api/Serializer/JsonRpcSerializer.php +69 -0
- includes/aws/Aws/Api/Serializer/QueryParamBuilder.php +154 -0
- includes/aws/Aws/Api/Serializer/QuerySerializer.php +69 -0
- includes/aws/Aws/Api/Serializer/RestJsonSerializer.php +39 -0
- includes/aws/Aws/Api/Serializer/RestSerializer.php +193 -0
- includes/aws/Aws/Api/Serializer/RestXmlSerializer.php +34 -0
- includes/aws/Aws/Api/Serializer/XmlBody.php +217 -0
- includes/aws/Aws/Api/Service.php +404 -0
- includes/aws/Aws/Api/Shape.php +69 -0
- includes/aws/Aws/Api/ShapeMap.php +66 -0
- includes/aws/Aws/Api/StructureShape.php +79 -0
- includes/aws/Aws/Api/TimestampShape.php +48 -0
- includes/aws/Aws/Api/Validator.php +236 -0
- includes/aws/Aws/ApiGateway/ApiGatewayClient.php +166 -0
- includes/aws/Aws/ApiGateway/Exception/ApiGatewayException.php +9 -0
- includes/aws/Aws/AwsClient.php +351 -0
- includes/aws/Aws/AwsClientInterface.php +169 -0
- includes/aws/Aws/CacheInterface.php +34 -0
- includes/aws/Aws/ClientResolver.php +548 -0
- includes/aws/Aws/CloudFront/CloudFrontClient.php +142 -0
- includes/aws/Aws/CloudFront/CookieSigner.php +65 -0
- includes/aws/Aws/CloudFront/Exception/CloudFrontException.php +9 -0
- includes/aws/Aws/CloudFront/Signer.php +108 -0
- includes/aws/Aws/CloudFront/UrlSigner.php +119 -0
- includes/aws/Aws/Command.php +57 -0
- includes/aws/Aws/CommandInterface.php +42 -0
- includes/aws/Aws/CommandPool.php +144 -0
- includes/aws/Aws/ConfigService/ConfigServiceClient.php +56 -0
- includes/aws/Aws/ConfigService/Exception/ConfigServiceException.php +9 -0
- includes/aws/Aws/Credentials/CredentialProvider.php +324 -0
- includes/aws/Aws/Credentials/Credentials.php +91 -0
- includes/aws/Aws/Credentials/CredentialsInterface.php +52 -0
- includes/aws/Aws/Credentials/InstanceProfileProvider.php +102 -0
- includes/aws/Aws/DataPipeline/DataPipelineClient.php +48 -0
- includes/aws/Aws/DataPipeline/Exception/DataPipelineException.php +9 -0
- includes/aws/Aws/DirectConnect/DirectConnectClient.php +48 -0
- includes/aws/Aws/DirectConnect/Exception/DirectConnectException.php +9 -0
- includes/aws/Aws/DirectoryService/DirectoryServiceClient.php +54 -0
- includes/aws/Aws/DirectoryService/Exception/DirectoryServiceException.php +9 -0
- includes/aws/Aws/DoctrineCacheAdapter.php +55 -0
- includes/aws/Aws/Endpoint/EndpointProvider.php +96 -0
- includes/aws/Aws/Endpoint/PatternEndpointProvider.php +51 -0
- includes/aws/Aws/Exception/AwsException.php +160 -0
- includes/aws/Aws/Exception/CouldNotCreateChecksumException.php +19 -0
- includes/aws/Aws/Exception/CredentialsException.php +4 -0
- includes/aws/Aws/Exception/MultipartUploadException.php +57 -0
- includes/aws/Aws/Exception/UnresolvedApiException.php +4 -0
- includes/aws/Aws/Exception/UnresolvedEndpointException.php +4 -0
- includes/aws/Aws/Exception/UnresolvedSignatureException.php +4 -0
- includes/aws/Aws/Firehose/Exception/FirehoseException.php +9 -0
- includes/aws/Aws/Firehose/FirehoseClient.php +24 -0
- includes/aws/Aws/Glacier/Exception/GlacierException.php +9 -0
- includes/aws/Aws/Glacier/GlacierClient.php +247 -0
- includes/aws/Aws/Glacier/MultipartUploader.php +281 -0
- includes/aws/Aws/Glacier/TreeHash.php +118 -0
- includes/aws/Aws/Handler/GuzzleV5/GuzzleHandler.php +181 -0
- includes/aws/Aws/Handler/GuzzleV5/GuzzleStream.php +24 -0
- includes/aws/Aws/Handler/GuzzleV5/PsrStream.php +34 -0
- includes/aws/Aws/Handler/GuzzleV6/GuzzleHandler.php +59 -0
- includes/aws/Aws/HandlerList.php +424 -0
- includes/aws/Aws/HasDataTrait.php +60 -0
- includes/aws/Aws/HashInterface.php +27 -0
- includes/aws/Aws/HashingStream.php +60 -0
- includes/aws/Aws/History.php +152 -0
- includes/aws/Aws/Iam/Exception/IamException.php +9 -0
- includes/aws/Aws/Iam/IamClient.php +236 -0
- includes/aws/Aws/Inspector/Exception/InspectorException.php +9 -0
- includes/aws/Aws/Inspector/InspectorClient.php +82 -0
- includes/aws/Aws/Iot/Exception/IotException.php +9 -0
- includes/aws/Aws/Iot/IotClient.php +88 -0
- includes/aws/Aws/IotDataPlane/Exception/IotDataPlaneException.php +9 -0
- includes/aws/Aws/IotDataPlane/IotDataPlaneClient.php +18 -0
- includes/aws/Aws/JsonCompiler.php +25 -0
- includes/aws/Aws/LruArrayCache.php +74 -0
- includes/aws/Aws/Middleware.php +308 -0
- includes/aws/Aws/MockHandler.php +131 -0
- includes/aws/Aws/Multipart/AbstractUploadManager.php +297 -0
- includes/aws/Aws/Multipart/AbstractUploader.php +129 -0
- includes/aws/Aws/Multipart/UploadState.php +145 -0
- includes/aws/Aws/PhpHash.php +81 -0
- includes/aws/Aws/Result.php +56 -0
- includes/aws/Aws/ResultInterface.php +54 -0
- includes/aws/Aws/ResultPaginator.php +179 -0
- includes/aws/Aws/RetryMiddleware.php +125 -0
- includes/aws/Aws/S3/AmbiguousSuccessParser.php +60 -0
- includes/aws/Aws/S3/ApplyChecksumMiddleware.php +74 -0
- includes/aws/Aws/S3/BatchDelete.php +237 -0
- includes/aws/Aws/S3/BucketEndpointMiddleware.php +75 -0
- includes/aws/Aws/S3/Exception/DeleteMultipleObjectsException.php +62 -0
- includes/aws/Aws/S3/Exception/PermanentRedirectException.php +4 -0
- includes/aws/Aws/S3/Exception/S3Exception.php +9 -0
- includes/aws/Aws/S3/GetBucketLocationParser.php +42 -0
- includes/aws/Aws/S3/MultipartCopy.php +167 -0
- includes/aws/Aws/S3/MultipartUploader.php +144 -0
- includes/aws/Aws/S3/MultipartUploadingTrait.php +126 -0
- includes/aws/Aws/S3/PermanentRedirectMiddleware.php +62 -0
- includes/aws/Aws/S3/PostObject.php +159 -0
- includes/aws/Aws/S3/PutObjectUrlMiddleware.php +57 -0
- includes/aws/Aws/S3/RetryableMalformedResponseParser.php +48 -0
- includes/aws/Aws/S3/S3Client.php +855 -0
- includes/aws/Aws/S3/S3UriParser.php +110 -0
- includes/aws/Aws/S3/SSECMiddleware.php +75 -0
- includes/aws/Aws/S3/StreamWrapper.php +949 -0
- includes/aws/Aws/S3/Transfer.php +379 -0
- includes/aws/Aws/Sdk.php +149 -0
- includes/aws/Aws/Signature/AnonymousSignature.php +26 -0
- includes/aws/Aws/Signature/S3SignatureV4.php +45 -0
- includes/aws/Aws/Signature/SignatureInterface.php +44 -0
- includes/aws/Aws/Signature/SignatureProvider.php +123 -0
- includes/aws/Aws/Signature/SignatureV4.php +368 -0
- includes/aws/Aws/StorageGateway/Exception/StorageGatewayException.php +9 -0
- includes/aws/Aws/StorageGateway/StorageGatewayClient.php +116 -0
- includes/aws/Aws/Support/Exception/SupportException.php +9 -0
- includes/aws/Aws/Support/SupportClient.php +38 -0
- includes/aws/Aws/TraceMiddleware.php +302 -0
- includes/aws/Aws/Waiter.php +266 -0
- includes/aws/Aws/WorkSpaces/Exception/WorkSpacesException.php +9 -0
- includes/aws/Aws/WorkSpaces/WorkSpacesClient.php +24 -0
- includes/aws/Aws/WrappedHttpHandler.php +171 -0
- includes/aws/Aws/data/cloudfront/2015-09-17/api-2.json.php +3 -0
- includes/aws/Aws/data/cloudfront/2015-09-17/examples-1.json.php +3 -0
- includes/aws/Aws/data/cloudfront/2015-09-17/paginators-1.json.php +3 -0
- includes/aws/Aws/data/cloudfront/2015-09-17/waiters-2.json.php +3 -0
- includes/aws/Aws/data/config/2014-11-12/api-2.json.php +3 -0
- includes/aws/Aws/data/config/2014-11-12/paginators-1.json.php +3 -0
- includes/aws/Aws/data/endpoints.json.php +3 -0
- includes/aws/Aws/data/manifest.json.php +3 -0
- includes/aws/Aws/data/s3/2006-03-01/api-2.json.php +3 -0
- includes/aws/Aws/data/s3/2006-03-01/paginators-1.json.php +3 -0
- includes/aws/Aws/data/s3/2006-03-01/waiters-2.json.php +3 -0
- includes/aws/Aws/functions.php +351 -0
- includes/aws/CHANGELOG.md +1387 -0
- includes/aws/GuzzleHttp/Client.php +397 -0
- includes/aws/GuzzleHttp/ClientInterface.php +84 -0
- includes/aws/GuzzleHttp/Cookie/CookieJar.php +277 -0
- includes/aws/GuzzleHttp/Cookie/CookieJarInterface.php +84 -0
- includes/aws/GuzzleHttp/Cookie/FileCookieJar.php +87 -0
- includes/aws/GuzzleHttp/Cookie/SessionCookieJar.php +72 -0
- includes/aws/GuzzleHttp/Cookie/SetCookie.php +404 -0
- includes/aws/GuzzleHttp/Exception/BadResponseException.php +7 -0
- includes/aws/GuzzleHttp/Exception/ClientException.php +7 -0
- includes/aws/GuzzleHttp/Exception/ConnectException.php +37 -0
- includes/aws/GuzzleHttp/Exception/GuzzleException.php +4 -0
- includes/aws/GuzzleHttp/Exception/RequestException.php +188 -0
- includes/aws/GuzzleHttp/Exception/SeekException.php +27 -0
- includes/aws/GuzzleHttp/Exception/ServerException.php +7 -0
- includes/aws/GuzzleHttp/Exception/TooManyRedirectsException.php +4 -0
- includes/aws/GuzzleHttp/Exception/TransferException.php +4 -0
- includes/aws/GuzzleHttp/Handler/CurlFactory.php +531 -0
- includes/aws/GuzzleHttp/Handler/CurlFactoryInterface.php +27 -0
- includes/aws/GuzzleHttp/Handler/CurlHandler.php +45 -0
- includes/aws/GuzzleHttp/Handler/CurlMultiHandler.php +197 -0
- includes/aws/GuzzleHttp/Handler/EasyHandle.php +87 -0
- includes/aws/GuzzleHttp/Handler/MockHandler.php +176 -0
- includes/aws/GuzzleHttp/Handler/Proxy.php +55 -0
- includes/aws/GuzzleHttp/Handler/StreamHandler.php +458 -0
- includes/aws/GuzzleHttp/HandlerStack.php +273 -0
- includes/aws/GuzzleHttp/MessageFormatter.php +182 -0
- includes/aws/GuzzleHttp/Middleware.php +249 -0
- includes/aws/GuzzleHttp/Pool.php +123 -0
- includes/aws/GuzzleHttp/PrepareBodyMiddleware.php +50 -0
controller/backend.php
CHANGED
@@ -608,23 +608,6 @@ function fv_wp_flowplayer_admin_notice() {
|
|
608 |
</div>';
|
609 |
}
|
610 |
|
611 |
-
global $FV_Player_Pro;
|
612 |
-
if( $FV_Player_Pro && version_compare($FV_Player_Pro->version,'0.5') == -1 ) :
|
613 |
-
?>
|
614 |
-
<div class="error">
|
615 |
-
<p><?php _e( 'FV Player: Your pro extension is installed, but it\'s not compatible with FV Player 6! Make sure you upgrade your FV Player Pro to version 0.5 or above.', 'my-text-domain' ); ?></p>
|
616 |
-
</div>
|
617 |
-
<?php
|
618 |
-
endif;
|
619 |
-
|
620 |
-
/*if( isset($_GET['page']) && $_GET['page'] == 'backend.php' ) {
|
621 |
-
$options = get_option( 'fvwpflowplayer' );
|
622 |
-
if( $options['key'] == 'false' ) {
|
623 |
-
echo '<div class="updated"><p>';
|
624 |
-
printf(__('Brand new version of Flowplayer for HTML5. <a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/buy">Licenses half price</a> in May.' ) );
|
625 |
-
echo "</p></div>";
|
626 |
-
}
|
627 |
-
}*/
|
628 |
}
|
629 |
|
630 |
|
@@ -803,7 +786,7 @@ function fv_player_pro_version_check() {
|
|
803 |
if( isset($FV_Player_Pro) && !empty($FV_Player_Pro->version) && version_compare( str_replace('.beta','',$FV_Player_Pro->version),'7.1.14.727' ) == -1 ) :
|
804 |
?>
|
805 |
<div class="error">
|
806 |
-
<p><?php _e( 'FV Player: Please upgrade to FV Player Pro version 7.1.14.727 or above!', 'fv-
|
807 |
</div>
|
808 |
<?php
|
809 |
endif;
|
608 |
</div>';
|
609 |
}
|
610 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
611 |
}
|
612 |
|
613 |
|
786 |
if( isset($FV_Player_Pro) && !empty($FV_Player_Pro->version) && version_compare( str_replace('.beta','',$FV_Player_Pro->version),'7.1.14.727' ) == -1 ) :
|
787 |
?>
|
788 |
<div class="error">
|
789 |
+
<p><?php _e( 'FV Player: Please upgrade to FV Player Pro version 7.1.14.727 or above!', 'fv-wordpress-flowplayer' ); ?></p>
|
790 |
</div>
|
791 |
<?php
|
792 |
endif;
|
controller/editor.php
CHANGED
@@ -254,4 +254,4 @@ function fv_wp_flowplayer_save_to_media_library( $image_url, $post_id ) {
|
|
254 |
|
255 |
return $attach_id;
|
256 |
|
257 |
-
}
|
254 |
|
255 |
return $attach_id;
|
256 |
|
257 |
+
}
|
controller/settings.php
CHANGED
@@ -350,3 +350,25 @@ function flowplayer_admin_footer_wp_js_restore() {
|
|
350 |
</script>
|
351 |
<?php
|
352 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
350 |
</script>
|
351 |
<?php
|
352 |
}
|
353 |
+
|
354 |
+
|
355 |
+
|
356 |
+
function fv_player_get_aws_regions($translation_domain = 'fv-wordpress-flowplayer') {
|
357 |
+
|
358 |
+
return array(
|
359 |
+
'us-east-1' => __('US East (N. Virginia)', $translation_domain),
|
360 |
+
'us-east-2' => __('US East (Ohio)', $translation_domain),
|
361 |
+
'us-west-1' => __('US West (N. California)', $translation_domain),
|
362 |
+
'us-west-2' => __('US West (Oregon)', $translation_domain),
|
363 |
+
'ca-central-1' => __('Canada (Central)', $translation_domain),
|
364 |
+
'ap-south-1' => __('Asia Pacific (Mumbai)', $translation_domain),
|
365 |
+
'ap-northeast-2' => __('Asia Pacific (Seoul)', $translation_domain),
|
366 |
+
'ap-southeast-1' => __('Asia Pacific (Singapore)', $translation_domain),
|
367 |
+
'ap-southeast-2' => __('Asia Pacific (Sydney)', $translation_domain),
|
368 |
+
'ap-northeast-1' => __('Asia Pacific (Tokyo)', $translation_domain),
|
369 |
+
'eu-central-1' => __('EU (Frankfurt)', $translation_domain),
|
370 |
+
'eu-west-1' => __('EU (Ireland)', $translation_domain),
|
371 |
+
'eu-west-2' => __('EU (London)', $translation_domain),
|
372 |
+
'sa-east-1' => __('South America (São Paulo)', $translation_domain),
|
373 |
+
);
|
374 |
+
}
|
css/bigplay.svg
CHANGED
@@ -1 +1,50 @@
|
|
1 |
-
<?xml version="1.0" standalone="no"?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" standalone="no"?>
|
2 |
+
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
|
3 |
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
4 |
+
<svg id="bigplay-gradient.fw-Page%201" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1"
|
5 |
+
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
|
6 |
+
x="0px" y="0px" width="100px" height="200px"
|
7 |
+
>
|
8 |
+
<defs>
|
9 |
+
<radialGradient id="gradient1" cx="50%" cy="50%" r="50%">
|
10 |
+
<stop stop-color="#222222" stop-opacity="0" offset="70%"/>
|
11 |
+
<stop stop-color="#222222" stop-opacity="0.0118" offset="70.202%"/>
|
12 |
+
<stop stop-color="#333333" stop-opacity="1" offset="85%"/>
|
13 |
+
<stop stop-color="#333333" stop-opacity="0" offset="100%"/>
|
14 |
+
</radialGradient>
|
15 |
+
<radialGradient id="gradient2" cx="50%" cy="50%" r="50%">
|
16 |
+
<stop stop-color="#bbbbbb" stop-opacity="0" offset="70%"/>
|
17 |
+
<stop stop-color="#bbbbbb" stop-opacity="0.0118" offset="70.202%"/>
|
18 |
+
<stop stop-color="#bbbbbb" stop-opacity="1" offset="85%"/>
|
19 |
+
<stop stop-color="#bbbbbb" stop-opacity="0" offset="100%"/>
|
20 |
+
</radialGradient>
|
21 |
+
<filter id="filter1" x="-100%" y="-100%" width="300%" height="300%">
|
22 |
+
<!-- Glow -->
|
23 |
+
<feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0"/>
|
24 |
+
<feMorphology result="out" in="out" operator="dilate" radius="3"/>
|
25 |
+
<feGaussianBlur result="out" in="out" stdDeviation="1.5"/>
|
26 |
+
<feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow1"/>
|
27 |
+
</filter>
|
28 |
+
<filter id="filter2" x="-100%" y="-100%" width="300%" height="300%">
|
29 |
+
<!-- Glow -->
|
30 |
+
<feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.251 0"/>
|
31 |
+
<feMorphology result="out" in="out" operator="dilate" radius="3"/>
|
32 |
+
<feGaussianBlur result="out" in="out" stdDeviation="1.5"/>
|
33 |
+
<feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow2"/>
|
34 |
+
</filter>
|
35 |
+
</defs>
|
36 |
+
<g id="Background">
|
37 |
+
</g>
|
38 |
+
<g id="dark%20shadow">
|
39 |
+
<path d="M 22 50 C 22 34.5358 34.5358 22 50 22 C 65.4642 22 78 34.5358 78 50 C 78 65.4642 65.4642 78 50 78 C 34.5358 78 22 65.4642 22 50 ZM 5 50 C 5 74.8531 25.1469 95 50 95 C 74.8531 95 95 74.8531 95 50 C 95 25.1469 74.8531 5 50 5 C 25.1469 5 5 25.1469 5 50 Z" fill="url(#gradient1)"/>
|
40 |
+
<path d="M 22 150 C 22 134.5358 34.5358 122 50 122 C 65.4642 122 78 134.5358 78 150 C 78 165.4642 65.4642 178 50 178 C 34.5358 178 22 165.4642 22 150 ZM 5 150 C 5 174.8531 25.1469 195 50 195 C 74.8531 195 95 174.8531 95 150 C 95 125.1469 74.8531 105 50 105 C 25.1469 105 5 125.1469 5 150 Z" fill="url(#gradient2)"/>
|
41 |
+
</g>
|
42 |
+
<g id="dark">
|
43 |
+
<path id="Polygon" filter="url(#filter1)" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff"/>
|
44 |
+
<path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>
|
45 |
+
</g>
|
46 |
+
<g id="light">
|
47 |
+
<path id="Polygon2" filter="url(#filter2)" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff"/>
|
48 |
+
<path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/>
|
49 |
+
</g>
|
50 |
+
</svg>
|
css/controls.svg
CHANGED
@@ -1 +1,172 @@
|
|
1 |
-
<?xml version="1.0" standalone="no"?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" standalone="no"?>
|
2 |
+
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
|
3 |
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
4 |
+
<svg id="controls.fw-Page%201" viewBox="0 0 144 32" style="background-color:#ffffff00" version="1.1"
|
5 |
+
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
|
6 |
+
x="0px" y="0px" width="144px" height="32px"
|
7 |
+
>
|
8 |
+
<defs>
|
9 |
+
<radialGradient id="gradient1" cx="50%" cy="50%" r="50%">
|
10 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
11 |
+
<stop stop-color="#f2f2f2" stop-opacity="0.2" offset="100%"/>
|
12 |
+
</radialGradient>
|
13 |
+
<linearGradient id="gradient2" x1="50%" y1="-7.8652%" x2="50%" y2="249.6629%">
|
14 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
15 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
16 |
+
</linearGradient>
|
17 |
+
<linearGradient id="gradient3" x1="50%" y1="0%" x2="50%" y2="238.75%">
|
18 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
19 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
20 |
+
</linearGradient>
|
21 |
+
<linearGradient id="gradient4" x1="50%" y1="0%" x2="50%" y2="100%">
|
22 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
23 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
24 |
+
</linearGradient>
|
25 |
+
<linearGradient id="gradient5" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%">
|
26 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
27 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
28 |
+
</linearGradient>
|
29 |
+
<linearGradient id="gradient6" x1="50%" y1="0%" x2="50%" y2="100%">
|
30 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
31 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
32 |
+
</linearGradient>
|
33 |
+
<linearGradient id="gradient7" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%">
|
34 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
35 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
36 |
+
</linearGradient>
|
37 |
+
<linearGradient id="gradient8" x1="50%" y1="0%" x2="50%" y2="100%">
|
38 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
39 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
40 |
+
</linearGradient>
|
41 |
+
<linearGradient id="gradient9" x1="50%" y1="0%" x2="50%" y2="100%">
|
42 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
43 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
44 |
+
</linearGradient>
|
45 |
+
<linearGradient id="gradient10" x1="50%" y1="0%" x2="50%" y2="100%">
|
46 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
47 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
48 |
+
</linearGradient>
|
49 |
+
<linearGradient id="gradient11" x1="50%" y1="0%" x2="50%" y2="100%">
|
50 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
51 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
52 |
+
</linearGradient>
|
53 |
+
<linearGradient id="gradient12" x1="50%" y1="0%" x2="50%" y2="238.75%">
|
54 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
55 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
56 |
+
</linearGradient>
|
57 |
+
<linearGradient id="gradient13" x1="40%" y1="-140%" x2="40%" y2="98.75%">
|
58 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
59 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
60 |
+
</linearGradient>
|
61 |
+
<linearGradient id="gradient14" x1="50%" y1="0%" x2="50%" y2="238.75%">
|
62 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
63 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
64 |
+
</linearGradient>
|
65 |
+
<linearGradient id="gradient15" x1="60%" y1="-140%" x2="60%" y2="98.75%">
|
66 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
67 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
68 |
+
</linearGradient>
|
69 |
+
<linearGradient id="gradient16" x1="50%" y1="0%" x2="50%" y2="298.4375%">
|
70 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
71 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
72 |
+
</linearGradient>
|
73 |
+
<linearGradient id="gradient17" x1="50%" y1="0%" x2="50%" y2="238.75%">
|
74 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
75 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
76 |
+
</linearGradient>
|
77 |
+
<linearGradient id="gradient18" x1="50%" y1="-200%" x2="50%" y2="100%">
|
78 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
79 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
80 |
+
</linearGradient>
|
81 |
+
<linearGradient id="gradient19" x1="50%" y1="-200%" x2="50%" y2="110.9375%">
|
82 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
83 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
84 |
+
</linearGradient>
|
85 |
+
<linearGradient id="gradient20" x1="55%" y1="0%" x2="55%" y2="100%">
|
86 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
87 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/>
|
88 |
+
</linearGradient>
|
89 |
+
<linearGradient id="gradient21" x1="50%" y1="0%" x2="50%" y2="100%">
|
90 |
+
<stop stop-color="#ffffff" stop-opacity="1" offset="0%"/>
|
91 |
+
<stop stop-color="#c8c8c8" stop-opacity="1" offset="99.4444%"/>
|
92 |
+
</linearGradient>
|
93 |
+
</defs>
|
94 |
+
<g id="BG">
|
95 |
+
</g>
|
96 |
+
<g id="controls">
|
97 |
+
<path id="Line" d="M 98.5 7.5 L 109.5 7.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
98 |
+
<path id="Line2" d="M 98.5 3.5 L 109.5 3.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
99 |
+
<path id="Line3" d="M 98.5 11.5 L 109.5 11.5 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
100 |
+
<path id="Ellipse" d="M 108 11.5 C 108 10.6716 108.4477 10 109 10 C 109.5523 10 110 10.6716 110 11.5 C 110 12.3284 109.5523 13 109 13 C 108.4477 13 108 12.3284 108 11.5 Z" fill="#ffffff"/>
|
101 |
+
<path id="Ellipse2" d="M 104 7.5 C 104 6.6716 104.4477 6 105 6 C 105.5523 6 106 6.6716 106 7.5 C 106 8.3284 105.5523 9 105 9 C 104.4477 9 104 8.3284 104 7.5 Z" fill="#ffffff"/>
|
102 |
+
<path id="Ellipse3" d="M 108 3.5 C 108 2.6716 108.4477 2 109 2 C 109.5523 2 110 2.6716 110 3.5 C 110 4.3284 109.5523 5 109 5 C 108.4477 5 108 4.3284 108 3.5 Z" fill="#ffffff"/>
|
103 |
+
</g>
|
104 |
+
<g id="backlight">
|
105 |
+
<g id="off">
|
106 |
+
<rect x="83" y="21" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/>
|
107 |
+
</g>
|
108 |
+
<g id="on">
|
109 |
+
<path id="Ellipse4" d="M 81 8 C 81 5.2385 84.134 3 88 3 C 91.866 3 95 5.2385 95 8 C 95 10.7615 91.866 13 88 13 C 84.134 13 81 10.7615 81 8 Z" fill="url(#gradient1)"/>
|
110 |
+
<rect x="83" y="5" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/>
|
111 |
+
</g>
|
112 |
+
</g>
|
113 |
+
<g id="loop">
|
114 |
+
<g id="on2">
|
115 |
+
<path d="M 73.795 4.205 C 75.2155 4.8785 76.2 6.3234 76.2 8 C 76.2 10.3196 74.3196 12.2 72 12.2 C 69.6804 12.2 67.8 10.3196 67.8 8 C 67.8 6.3234 68.7845 4.8785 70.205 4.205 L 68.875 2.875 C 67.1501 3.9289 66 5.8306 66 8 C 66 11.3138 68.6862 14 72 14 C 75.3138 14 78 11.3138 78 8 C 78 5.8306 76.8499 3.9289 75.125 2.875 L 73.795 4.205 Z" fill="url(#gradient2)"/>
|
116 |
+
<path d="M 71 2 L 66 2 L 71 7 L 71 2 Z" fill="url(#gradient3)"/>
|
117 |
+
</g>
|
118 |
+
<g id="off2">
|
119 |
+
<path d="M 73.795 20.205 C 75.2155 20.8785 76.2 22.3234 76.2 24 C 76.2 26.3196 74.3196 28.2 72 28.2 C 69.6804 28.2 67.8 26.3196 67.8 24 C 67.8 22.3234 68.7845 20.8785 70.205 20.205 L 68.875 18.875 C 67.1501 19.9289 66 21.8306 66 24 C 66 27.3138 68.6862 30 72 30 C 75.3138 30 78 27.3138 78 24 C 78 21.8306 76.8499 19.9289 75.125 18.875 L 73.795 20.205 Z" fill="#a8a8b7"/>
|
120 |
+
<path d="M 71 18 L 66 18 L 71 23 L 71 18 Z" fill="#a8a8b7"/>
|
121 |
+
</g>
|
122 |
+
</g>
|
123 |
+
<g id="cc">
|
124 |
+
<rect visibility="hidden" x="49" y="2" width="14" height="12" stroke="#b0b0b0" stroke-width="1" fill="none"/>
|
125 |
+
<text visibility="hidden" x="49" y="17" width="14" fill="#ffffff" style="font-size: 10px; color: #ffffff; font-family: Arial; text-align: center; "><tspan><![CDATA[cc]]></tspan></text>
|
126 |
+
<path d="M 55 7 C 50.2813 3.7813 50.063 12.9405 55 10 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
127 |
+
<path d="M 60 7 C 55.2813 3.7813 55.063 12.9405 60 10 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
128 |
+
<path d="M 50 3 L 62 3 L 62 13 L 50 13 L 50 3 ZM 49 2 L 49 14 L 63 14 L 63 2 L 49 2 Z" fill="url(#gradient4)"/>
|
129 |
+
<rect x="49" y="2" width="14" height="12" fill="none"/>
|
130 |
+
</g>
|
131 |
+
<g id="volume">
|
132 |
+
<g id="no%20sound">
|
133 |
+
<rect x="17" y="5" width="5" height="6" fill="url(#gradient5)"/>
|
134 |
+
<path d="M 21 5 L 25 2 L 25 14 L 21 11.0625 L 21 5 Z" fill="url(#gradient6)"/>
|
135 |
+
</g>
|
136 |
+
<g id="sound%20bars">
|
137 |
+
<rect x="17" y="21" width="5" height="6" fill="url(#gradient7)"/>
|
138 |
+
<path d="M 21 21 L 25 18 L 25 30 L 21 27.0625 L 21 21 Z" fill="url(#gradient8)"/>
|
139 |
+
<path d="M 27 18 C 27 18 30.0625 17.375 30 24 C 29.9375 30.625 27 30 27 30 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
140 |
+
<path d="M 26 21.0079 C 26 21.0079 28.041 20.6962 27.9994 24 C 27.9577 27.3038 26 26.9921 26 26.9921 " stroke="#ffffff" stroke-width="1" fill="none"/>
|
141 |
+
</g>
|
142 |
+
</g>
|
143 |
+
<g id="play/pause">
|
144 |
+
<g id="play">
|
145 |
+
<path id="Polygon" d="M 14 8.5 L 3 14 L 3 3 L 14 8.5 Z" fill="url(#gradient9)"/>
|
146 |
+
</g>
|
147 |
+
<g id="pause">
|
148 |
+
<rect x="3" y="18" width="3" height="12" fill="url(#gradient10)"/>
|
149 |
+
<rect x="10" y="18" width="3" height="12" fill="url(#gradient11)"/>
|
150 |
+
</g>
|
151 |
+
</g>
|
152 |
+
<g id="fullscreen">
|
153 |
+
<g id="enter%201">
|
154 |
+
<path d="M 34 2 L 39 2 L 34 7 L 34 2 Z" fill="url(#gradient12)"/>
|
155 |
+
<path d="M 34 14 L 39 14 L 34 9 L 34 14 Z" fill="url(#gradient13)"/>
|
156 |
+
<path d="M 46 2 L 41 2 L 46 7 L 46 2 Z" fill="url(#gradient14)"/>
|
157 |
+
<path d="M 46 14 L 41 14 L 46 9 L 46 14 Z" fill="url(#gradient15)"/>
|
158 |
+
</g>
|
159 |
+
<g id="exit">
|
160 |
+
<path d="M 42 22 L 46 22 L 42 18 L 42 22 Z" fill="url(#gradient16)"/>
|
161 |
+
<path d="M 38 22 L 38 18 L 34 22 L 38 22 Z" fill="url(#gradient17)"/>
|
162 |
+
<path d="M 38 26 L 34 26 L 38 30 L 38 26 Z" fill="url(#gradient18)"/>
|
163 |
+
<path d="M 42 26 L 42 30 L 46 26 L 42 26 Z" fill="url(#gradient19)"/>
|
164 |
+
</g>
|
165 |
+
</g>
|
166 |
+
<g id="stop">
|
167 |
+
<rect x="115" y="3" width="10" height="10" fill="url(#gradient20)"/>
|
168 |
+
</g>
|
169 |
+
<g id="chooser">
|
170 |
+
<path d="M 135.2346 6.1522 C 136.2551 5.7295 137.4251 6.2141 137.8478 7.2346 C 138.2704 8.2551 137.7859 9.425 136.7654 9.8478 C 135.7449 10.2705 134.5749 9.7859 134.1522 8.7654 C 133.7295 7.7449 134.2141 6.5749 135.2346 6.1522 ZM 133.2735 1.4176 L 136 4.0054 L 138.7265 1.4176 L 138.8246 5.1754 L 142.5824 5.2735 L 139.9946 8 L 142.5824 10.7265 L 138.8246 10.8246 L 138.7265 14.5824 L 136 11.9946 L 133.2735 14.5824 L 133.1754 10.8246 L 129.4176 10.7265 L 132.0054 8 L 129.4176 5.2735 L 133.1754 5.1754 L 133.2735 1.4176 Z" fill="url(#gradient21)"/>
|
171 |
+
</g>
|
172 |
+
</svg>
|
css/flowplayer.css
CHANGED
@@ -1095,6 +1095,7 @@
|
|
1095 |
padding: 0 !important;
|
1096 |
float: left;
|
1097 |
font-family: "Lucida Console", Monaco, monospace;
|
|
|
1098 |
}
|
1099 |
.fvp-share-bar label {
|
1100 |
text-align: center !important;
|
1095 |
padding: 0 !important;
|
1096 |
float: left;
|
1097 |
font-family: "Lucida Console", Monaco, monospace;
|
1098 |
+
list-style: none;
|
1099 |
}
|
1100 |
.fvp-share-bar label {
|
1101 |
text-align: center !important;
|
css/s3-browser.css
ADDED
@@ -0,0 +1,456 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Amazon S3 Browser */
|
2 |
+
@charset "utf-8";
|
3 |
+
|
4 |
+
|
5 |
+
.files-div .search {
|
6 |
+
|
7 |
+
margin-top: 45px;
|
8 |
+
|
9 |
+
|
10 |
+
}
|
11 |
+
|
12 |
+
.files-div {
|
13 |
+
font-size: 14px;
|
14 |
+
z-index: -4;
|
15 |
+
border-radius:20px;
|
16 |
+
min-height:440px;
|
17 |
+
padding: 10px 10px 10px 10px;
|
18 |
+
}
|
19 |
+
|
20 |
+
|
21 |
+
/* File manager */
|
22 |
+
|
23 |
+
.filemanager {
|
24 |
+
width: 95%;
|
25 |
+
max-width:1340px;
|
26 |
+
position: relative;
|
27 |
+
}
|
28 |
+
.filemanager input[type='search'] {
|
29 |
+
width:200px!important;
|
30 |
+
}
|
31 |
+
|
32 |
+
@media all and (max-width: 965px) {
|
33 |
+
.filemanager {
|
34 |
+
margin: 30px auto 0;
|
35 |
+
padding: 1px;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
|
40 |
+
/* Breadcrumps */
|
41 |
+
|
42 |
+
.filemanager .breadcrumbs {
|
43 |
+
color: #000;
|
44 |
+
font-size: 18px;
|
45 |
+
font-weight: 700;
|
46 |
+
line-height: 35px;
|
47 |
+
}
|
48 |
+
.filemanager .breadcrumbs a:link, .breadcrumbs a:visited {
|
49 |
+
color: #000;
|
50 |
+
text-decoration: none;
|
51 |
+
}
|
52 |
+
.filemanager .breadcrumbs a:hover {
|
53 |
+
text-decoration: underline;
|
54 |
+
}
|
55 |
+
.filemanager .breadcrumbs .arrow {
|
56 |
+
color: #000;
|
57 |
+
font-size: 24px;
|
58 |
+
font-weight: 700;
|
59 |
+
line-height: 20px;
|
60 |
+
}
|
61 |
+
|
62 |
+
|
63 |
+
/* Search box */
|
64 |
+
|
65 |
+
.filemanager .search {
|
66 |
+
margin-top: 0 !important;
|
67 |
+
background-color: #fff;
|
68 |
+
position: absolute;
|
69 |
+
cursor: pointer;
|
70 |
+
right: 0 !important;
|
71 |
+
font-size: 17px;
|
72 |
+
color: #ffffff !important;
|
73 |
+
display: block !important;
|
74 |
+
width: 40px !important;
|
75 |
+
height: 40px !important;
|
76 |
+
}
|
77 |
+
.filemanager .search:before {
|
78 |
+
content: '';
|
79 |
+
position: absolute;
|
80 |
+
margin-top:11px;
|
81 |
+
width: 10px;
|
82 |
+
height: 11px;
|
83 |
+
border-radius: 50%;
|
84 |
+
border: 2px solid #333;
|
85 |
+
right: 8px;
|
86 |
+
}
|
87 |
+
.filemanager .search:after {
|
88 |
+
content: '';
|
89 |
+
width: 3px;
|
90 |
+
height: 10px;
|
91 |
+
background-color: #333;
|
92 |
+
border-radius: 2px;
|
93 |
+
position: absolute;
|
94 |
+
top: 25px;
|
95 |
+
right: 6px;
|
96 |
+
-webkit-transform: rotate(-45deg);
|
97 |
+
transform: rotate(-45deg);
|
98 |
+
}
|
99 |
+
.filemanager .search input[type=search] {
|
100 |
+
color: #4D535E;
|
101 |
+
background-color: #FFF;
|
102 |
+
width: 250px;
|
103 |
+
height: 44px;
|
104 |
+
margin-left: -215px;
|
105 |
+
padding-left: 20px;
|
106 |
+
text-decoration-color: #4d535e;
|
107 |
+
font-size: 16px;
|
108 |
+
font-weight: 400;
|
109 |
+
line-height: 20px;
|
110 |
+
display: none;
|
111 |
+
outline: none;
|
112 |
+
border: none;
|
113 |
+
padding-right: 10px;
|
114 |
+
-webkit-appearance: none;
|
115 |
+
}
|
116 |
+
::-webkit-input-placeholder { /* WebKit browsers */
|
117 |
+
color: #4d535e;
|
118 |
+
}
|
119 |
+
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
|
120 |
+
color: #4d535e;
|
121 |
+
opacity: 1;
|
122 |
+
}
|
123 |
+
::-moz-placeholder { /* Mozilla Firefox 19+ */
|
124 |
+
color: #4d535e;
|
125 |
+
opacity: 1;
|
126 |
+
}
|
127 |
+
:-ms-input-placeholder { /* Internet Explorer 10+ */
|
128 |
+
color: #4d535e;
|
129 |
+
}
|
130 |
+
|
131 |
+
|
132 |
+
/* Content area */
|
133 |
+
|
134 |
+
.filemanager .data {
|
135 |
+
margin-top: 60px;
|
136 |
+
z-index: -3;
|
137 |
+
}
|
138 |
+
.filemanager .data.animated {
|
139 |
+
-webkit-animation: showSlowlyElement 700ms; /* Chrome, Safari, Opera */
|
140 |
+
animation: showSlowlyElement 700ms; /* Standard syntax */
|
141 |
+
}
|
142 |
+
.filemanager .data li {
|
143 |
+
border-radius: 3px;
|
144 |
+
background-color: #373743;
|
145 |
+
width: 11.5%;
|
146 |
+
height: 151px;
|
147 |
+
list-style-type: none;
|
148 |
+
margin: 0 1% 1% 0;
|
149 |
+
display: inline-block;
|
150 |
+
position: relative;
|
151 |
+
overflow: hidden;
|
152 |
+
padding: 0.3em;
|
153 |
+
z-index: 1;
|
154 |
+
cursor: pointer;
|
155 |
+
box-sizing: border-box;
|
156 |
+
border: 1px solid #ddd;
|
157 |
+
transition: 0.3s background-color;
|
158 |
+
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
159 |
+
}
|
160 |
+
.filemanager .data li:hover {
|
161 |
+
background-color: #42424E;
|
162 |
+
}
|
163 |
+
.filemanager .data li a {
|
164 |
+
position: absolute;
|
165 |
+
top: 0;
|
166 |
+
left: 0;
|
167 |
+
width: 100%;
|
168 |
+
height: 100%;
|
169 |
+
text-decoration: none;
|
170 |
+
display: block;
|
171 |
+
text-align: center;
|
172 |
+
background: #eee;
|
173 |
+
box-shadow: inset 0 0 15px rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.05);
|
174 |
+
z-index: 0;
|
175 |
+
color: #333;
|
176 |
+
}
|
177 |
+
.filemanager .data li:hover a {
|
178 |
+
color: #fff;
|
179 |
+
background-color: #333;
|
180 |
+
}
|
181 |
+
.filemanager .data li .name {
|
182 |
+
font-size: 14px;
|
183 |
+
font-weight: 400;
|
184 |
+
line-height: 1.2;
|
185 |
+
width: 100%;
|
186 |
+
padding: 0 6px;
|
187 |
+
display: block;
|
188 |
+
position: absolute;
|
189 |
+
overflow: hidden;
|
190 |
+
bottom: 25px;
|
191 |
+
z-index: 1;
|
192 |
+
}
|
193 |
+
.filemanager .data li .details {
|
194 |
+
color: #b6c1c9;
|
195 |
+
font-size: 13px;
|
196 |
+
font-weight: 400;
|
197 |
+
width: 100%;
|
198 |
+
height: 13px;
|
199 |
+
bottom: 10px;
|
200 |
+
white-space: nowrap;
|
201 |
+
position: absolute;
|
202 |
+
display: block;
|
203 |
+
z-index: 1;
|
204 |
+
}
|
205 |
+
.filemanager .nothingfound {
|
206 |
+
background-color: #373743;
|
207 |
+
width: 23em;
|
208 |
+
height: 21em;
|
209 |
+
margin: 0 auto;
|
210 |
+
display: none;
|
211 |
+
font-family: Arial;
|
212 |
+
-webkit-animation: showSlowlyElement 700ms; /* Chrome, Safari, Opera */
|
213 |
+
animation: showSlowlyElement 700ms; /* Standard syntax */
|
214 |
+
}
|
215 |
+
.filemanager .nothingfound .nofiles {
|
216 |
+
margin: 30px auto;
|
217 |
+
top: 3em;
|
218 |
+
border-radius: 50%;
|
219 |
+
position:relative;
|
220 |
+
background-color: #d72f6e;
|
221 |
+
width: 11em;
|
222 |
+
height: 11em;
|
223 |
+
line-height: 11.4em;
|
224 |
+
}
|
225 |
+
.filemanager .nothingfound .nofiles:after {
|
226 |
+
content: '×';
|
227 |
+
position: absolute;
|
228 |
+
color: #ffffff;
|
229 |
+
font-size: 14em;
|
230 |
+
margin-right: 0.092em;
|
231 |
+
right: 0;
|
232 |
+
}
|
233 |
+
.filemanager .nothingfound span {
|
234 |
+
margin: 0 auto auto 6.8em;
|
235 |
+
color: #ffffff;
|
236 |
+
font-size: 16px;
|
237 |
+
font-weight: 700;
|
238 |
+
line-height: 20px;
|
239 |
+
height: 13px;
|
240 |
+
position: relative;
|
241 |
+
top: 2em;
|
242 |
+
}
|
243 |
+
@media all and (max-width:965px) {
|
244 |
+
|
245 |
+
.filemanager .data li {
|
246 |
+
width: 100%;
|
247 |
+
margin: 5px 0;
|
248 |
+
}
|
249 |
+
|
250 |
+
}
|
251 |
+
|
252 |
+
/* Chrome, Safari, Opera */
|
253 |
+
@-webkit-keyframes showSlowlyElement {
|
254 |
+
100% { transform: scale(1); opacity: 1; }
|
255 |
+
0% { transform: scale(1.2); opacity: 0; }
|
256 |
+
}
|
257 |
+
/* Standard syntax */
|
258 |
+
@keyframes showSlowlyElement {
|
259 |
+
100% { transform: scale(1); opacity: 1; }
|
260 |
+
0% { transform: scale(1.2); opacity: 0; }
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
/* Icons */
|
265 |
+
|
266 |
+
.files-div .icon {
|
267 |
+
font-size: 18px;
|
268 |
+
width: 3em;
|
269 |
+
}
|
270 |
+
.files-div .icon.folder {
|
271 |
+
display: inline-block;
|
272 |
+
margin: 1em;
|
273 |
+
background-color: transparent;
|
274 |
+
overflow: hidden;
|
275 |
+
}
|
276 |
+
.files-div .icon.folder:before {
|
277 |
+
content: '';
|
278 |
+
float: left;
|
279 |
+
background-color: #7ba1ad;
|
280 |
+
width: 1.5em;
|
281 |
+
height: 0.45em;
|
282 |
+
margin-left: 0.07em;
|
283 |
+
margin-bottom: -0.07em;
|
284 |
+
border-top-left-radius: 0.1em;
|
285 |
+
border-top-right-radius: 0.1em;
|
286 |
+
box-shadow: 1.25em 0.25em 0 0em #7ba1ad;
|
287 |
+
}
|
288 |
+
.files-div .icon.folder:after {
|
289 |
+
content: '';
|
290 |
+
float: left;
|
291 |
+
clear: left;
|
292 |
+
background-color: #a0d4e4;
|
293 |
+
width: 3em;
|
294 |
+
height: 2.25em;
|
295 |
+
border-radius: 0.1em;
|
296 |
+
}
|
297 |
+
.files-div .icon.folder.full:before {
|
298 |
+
height: 0.55em;
|
299 |
+
}
|
300 |
+
.files-div .icon.folder.full:after {
|
301 |
+
height: 2.15em;
|
302 |
+
box-shadow: 0 -0.12em 0 0 #ffffff;
|
303 |
+
}
|
304 |
+
.files-div .icon.file {
|
305 |
+
width: 2.5em;
|
306 |
+
height: 3em;
|
307 |
+
line-height: 3em;
|
308 |
+
text-align: center;
|
309 |
+
border-radius: 0.25em;
|
310 |
+
color: #FFF;
|
311 |
+
display: inline-block;
|
312 |
+
margin: 0.9em 1.2em 0.8em 1.3em;
|
313 |
+
position: relative;
|
314 |
+
overflow: hidden;
|
315 |
+
box-shadow: 1.74em -2.1em 0 0 #A4A7AC inset;
|
316 |
+
}
|
317 |
+
.files-div .icon.file:first-line {
|
318 |
+
font-size: 13px;
|
319 |
+
font-weight: 700;
|
320 |
+
}
|
321 |
+
.files-div .icon.file:after {
|
322 |
+
content: '';
|
323 |
+
position: absolute;
|
324 |
+
z-index: -1;
|
325 |
+
border-width: 0;
|
326 |
+
border-bottom: 2.6em solid #c0c0c0;
|
327 |
+
border-right: 2.22em solid rgba(0, 0, 0, 0);
|
328 |
+
top: -30.5px;
|
329 |
+
right: 0;
|
330 |
+
}
|
331 |
+
.files-div .icon.file.f-avi,
|
332 |
+
.files-div .icon.file.f-flv,
|
333 |
+
.files-div .icon.file.f-mkv,
|
334 |
+
.files-div .icon.file.f-mov,
|
335 |
+
.files-div .icon.file.f-mpeg,
|
336 |
+
.files-div .icon.file.f-mpg,
|
337 |
+
.files-div .icon.file.f-mp4,
|
338 |
+
.files-div .icon.file.f-m4v,
|
339 |
+
.files-div .icon.file.f-wmv {
|
340 |
+
box-shadow: 1.74em -2.1em 0 0 #7e70ee inset;
|
341 |
+
}
|
342 |
+
.files-div .icon.file.f-avi:after,
|
343 |
+
.files-div .icon.file.f-flv:after,
|
344 |
+
.files-div .icon.file.f-mkv:after,
|
345 |
+
.files-div .icon.file.f-mov:after,
|
346 |
+
.files-div .icon.file.f-mpeg:after,
|
347 |
+
.files-div .icon.file.f-mpg:after,
|
348 |
+
.files-div .icon.file.f-mp4:after,
|
349 |
+
.files-div .icon.file.f-m4v:after,
|
350 |
+
.files-div .icon.file.f-wmv:after {
|
351 |
+
border-bottom-color: #5649c1;
|
352 |
+
}
|
353 |
+
.files-div .icon.file.f-mp2,
|
354 |
+
.files-div .icon.file.f-mp3,
|
355 |
+
.files-div .icon.file.f-m3u,
|
356 |
+
.files-div .icon.file.f-wma,
|
357 |
+
.files-div .icon.file.f-xls,
|
358 |
+
.files-div .icon.file.f-xlsx {
|
359 |
+
box-shadow: 1.74em -2.1em 0 0 #5bab6e inset;
|
360 |
+
}
|
361 |
+
.files-div .icon.file.f-mp2:after,
|
362 |
+
.files-div .icon.file.f-mp3:after,
|
363 |
+
.files-div .icon.file.f-m3u:after,
|
364 |
+
.files-div .icon.file.f-wma:after,
|
365 |
+
.files-div .icon.file.f-xls:after,
|
366 |
+
.files-div .icon.file.f-xlsx:after {
|
367 |
+
border-bottom-color: #448353;
|
368 |
+
}
|
369 |
+
.files-div .icon.file.f-doc,
|
370 |
+
.files-div .icon.file.f-docx,
|
371 |
+
.files-div .icon.file.f-psd{
|
372 |
+
box-shadow: 1.74em -2.1em 0 0 #03689b inset;
|
373 |
+
}
|
374 |
+
.files-div .icon.file.f-doc:after,
|
375 |
+
.files-div .icon.file.f-docx:after,
|
376 |
+
.files-div .icon.file.f-psd:after {
|
377 |
+
border-bottom-color: #2980b9;
|
378 |
+
}
|
379 |
+
.files-div .icon.file.f-gif,
|
380 |
+
.files-div .icon.file.f-jpg,
|
381 |
+
.files-div .icon.file.f-jpeg,
|
382 |
+
.files-div .icon.file.f-pdf,
|
383 |
+
.files-div .icon.file.f-png {
|
384 |
+
box-shadow: 1.74em -2.1em 0 0 #e15955 inset;
|
385 |
+
}
|
386 |
+
.files-div .icon.file.f-gif:after,
|
387 |
+
.files-div .icon.file.f-jpg:after,
|
388 |
+
.files-div .icon.file.f-jpeg:after,
|
389 |
+
.files-div .icon.file.f-pdf:after,
|
390 |
+
.files-div .icon.file.f-png:after {
|
391 |
+
border-bottom-color: #c6393f;
|
392 |
+
}
|
393 |
+
.files-div .icon.file.f-deb,
|
394 |
+
.files-div .icon.file.f-dmg,
|
395 |
+
.files-div .icon.file.f-gz,
|
396 |
+
.files-div .icon.file.f-rar,
|
397 |
+
.files-div .icon.file.f-zip,
|
398 |
+
.files-div .icon.file.f-7z {
|
399 |
+
box-shadow: 1.74em -2.1em 0 0 #867c75 inset;
|
400 |
+
}
|
401 |
+
.files-div .icon.file.f-deb:after,
|
402 |
+
.files-div .icon.file.f-dmg:after,
|
403 |
+
.files-div .icon.file.f-gz:after,
|
404 |
+
.files-div .icon.file.f-rar:after,
|
405 |
+
.files-div .icon.file.f-zip:after,
|
406 |
+
.files-div .icon.file.f-7z:after {
|
407 |
+
border-bottom-color: #685f58;
|
408 |
+
}
|
409 |
+
.files-div .icon.file.f-html,
|
410 |
+
.files-div .icon.file.f-rtf,
|
411 |
+
.files-div .icon.file.f-xml,
|
412 |
+
.files-div .icon.file.f-xhtml {
|
413 |
+
box-shadow: 1.74em -2.1em 0 0 #a94bb7 inset;
|
414 |
+
}
|
415 |
+
.files-div .icon.file.f-html:after,
|
416 |
+
.files-div .icon.file.f-rtf:after,
|
417 |
+
.files-div .icon.file.f-xml:after,
|
418 |
+
.files-div .icon.file.f-xhtml:after {
|
419 |
+
border-bottom-color: #d65de8;
|
420 |
+
}
|
421 |
+
.files-div .icon.file.f-js {
|
422 |
+
box-shadow: 1.74em -2.1em 0 0 #d0c54d inset;
|
423 |
+
}
|
424 |
+
.files-div .icon.file.f-js:after {
|
425 |
+
border-bottom-color: #a69f4e;
|
426 |
+
}
|
427 |
+
.files-div .icon.file.f-css,
|
428 |
+
.files-div .icon.file.f-saas,
|
429 |
+
.files-div .icon.file.f-scss {
|
430 |
+
box-shadow: 1.74em -2.1em 0 0 #44afa6 inset;
|
431 |
+
}
|
432 |
+
.files-div .icon.file.f-css:after,
|
433 |
+
.files-div .icon.file.f-saas:after,
|
434 |
+
.files-div .icon.file.f-scss:after {
|
435 |
+
border-bottom-color: #30837c;
|
436 |
+
}
|
437 |
+
|
438 |
+
@media screen and (max-width: 600px) {
|
439 |
+
.files-div .icon {
|
440 |
+
font-size:1em!important;
|
441 |
+
margin-top:2em!important;
|
442 |
+
}
|
443 |
+
.files-div .icon.file:after {
|
444 |
+
top: -27.5px!important;
|
445 |
+
}
|
446 |
+
.filemanager .data li {
|
447 |
+
|
448 |
+
width:100%!important;
|
449 |
+
}
|
450 |
+
.files-div ul.data {
|
451 |
+
|
452 |
+
margin-left:0px!important;
|
453 |
+
margin-right:0px!important;
|
454 |
+
|
455 |
+
}
|
456 |
+
}
|
css/shortcode-editor.css
CHANGED
@@ -144,4 +144,8 @@ a #add-format, a #add-rtmp {
|
|
144 |
}
|
145 |
#fv-wordpress-flowplayer-popup table td {
|
146 |
padding: 4px 2px;
|
|
|
|
|
|
|
|
|
147 |
}
|
144 |
}
|
145 |
#fv-wordpress-flowplayer-popup table td {
|
146 |
padding: 4px 2px;
|
147 |
+
}
|
148 |
+
|
149 |
+
#fv-player-shortcode-editor-editor ::placeholder {
|
150 |
+
opacity:.5;
|
151 |
}
|
flowplayer.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: FV Player
|
4 |
Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
|
5 |
Description: Formerly FV WordPress Flowplayer. Supports MP4, HLS, MPEG-DASH, WebM and OGV. Advanced features such as overlay ads or popups. Uses Flowplayer 7.2.7.
|
6 |
-
Version: 7.1.
|
7 |
Author URI: http://foliovision.com/
|
8 |
License: GPL-3.0
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
@@ -26,15 +26,17 @@ License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
|
26 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
27 |
*/
|
28 |
|
29 |
-
$fv_wp_flowplayer_ver = '7.1.
|
30 |
$fv_wp_flowplayer_core_ver = '7.2.7.1';
|
31 |
|
32 |
-
|
33 |
if( file_exists( dirname( __FILE__ ) . '/includes/module.php' ) ) {
|
34 |
-
|
35 |
}
|
36 |
|
37 |
-
|
|
|
|
|
38 |
$FV_Player_Checker = new FV_Player_Checker();
|
39 |
|
40 |
include_once(dirname( __FILE__ ) . '/models/flowplayer.php');
|
@@ -64,13 +66,16 @@ global $fv_fp;
|
|
64 |
$fv_fp = new flowplayer_frontend();
|
65 |
|
66 |
if( is_admin() ) {
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
71 |
register_deactivation_hook( __FILE__, 'flowplayer_deactivate' );
|
72 |
|
73 |
}
|
74 |
|
75 |
-
|
76 |
-
|
3 |
Plugin Name: FV Player
|
4 |
Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
|
5 |
Description: Formerly FV WordPress Flowplayer. Supports MP4, HLS, MPEG-DASH, WebM and OGV. Advanced features such as overlay ads or popups. Uses Flowplayer 7.2.7.
|
6 |
+
Version: 7.2.1.727
|
7 |
Author URI: http://foliovision.com/
|
8 |
License: GPL-3.0
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
26 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
27 |
*/
|
28 |
|
29 |
+
$fv_wp_flowplayer_ver = '7.2.1.727';
|
30 |
$fv_wp_flowplayer_core_ver = '7.2.7.1';
|
31 |
|
32 |
+
include_once( dirname( __FILE__ ) . '/includes/extra-functions.php' );
|
33 |
if( file_exists( dirname( __FILE__ ) . '/includes/module.php' ) ) {
|
34 |
+
include_once( dirname( __FILE__ ) . '/includes/module.php' );
|
35 |
}
|
36 |
|
37 |
+
include_once( dirname( __FILE__ ) . '/models/checker.php' );
|
38 |
+
|
39 |
+
global $FV_Player_Checker;
|
40 |
$FV_Player_Checker = new FV_Player_Checker();
|
41 |
|
42 |
include_once(dirname( __FILE__ ) . '/models/flowplayer.php');
|
66 |
$fv_fp = new flowplayer_frontend();
|
67 |
|
68 |
if( is_admin() ) {
|
69 |
+
include_once( dirname( __FILE__ ) . '/controller/backend.php' );
|
70 |
+
include_once( dirname( __FILE__ ) . '/controller/editor.php' );
|
71 |
+
include_once( dirname( __FILE__ ) . '/controller/settings.php' );
|
72 |
+
if( version_compare(phpversion(),'5.5.0') != -1 ) {
|
73 |
+
include_once(dirname( __FILE__ ) . '/models/media-browser.php');
|
74 |
+
include_once(dirname( __FILE__ ) . '/models/media-browser-s3.php');
|
75 |
+
}
|
76 |
register_deactivation_hook( __FILE__, 'flowplayer_deactivate' );
|
77 |
|
78 |
}
|
79 |
|
80 |
+
include_once( dirname( __FILE__ ) . '/controller/frontend.php' );
|
81 |
+
include_once( dirname( __FILE__ ) . '/controller/shortcodes.php');
|
flowplayer/fv-flowplayer.min.js
CHANGED
@@ -2701,7 +2701,7 @@ flowplayer( function(api,root) {
|
|
2701 |
});
|
2702 |
|
2703 |
api.on('ready', function() {
|
2704 |
-
if( api.video.is_fv_recoverable && api.engine.engineName == 'html5' && ( api.video.type == 'application/x-mpegurl' || api.video.type == 'video/fv-mp4' ) ) {
|
2705 |
|
2706 |
time_delay = new Date().getTime() - time_start;
|
2707 |
|
@@ -2722,6 +2722,7 @@ flowplayer( function(api,root) {
|
|
2722 |
|
2723 |
function hls_check() {
|
2724 |
if( api.ready && api.playing && !api.loading && !api.finished ) {
|
|
|
2725 |
console.log('HLS stream stale for '+time_delay+' ms, triggering error!');
|
2726 |
fv_player_notice(root,fv_flowplayer_translations.video_reload+' <a class="fv-player-reload" href="#">↻</a>','progress error unload');
|
2727 |
jQuery('.fv-player-reload').click( function() {
|
2701 |
});
|
2702 |
|
2703 |
api.on('ready', function() {
|
2704 |
+
if( api.video.is_fv_recoverable && api.engine.engineName == 'html5' && ( api.video.type == 'application/x-mpegurl' || api.video.type == 'video/fv-mp4' && api.video.src.match(/m3u8/) ) ) {
|
2705 |
|
2706 |
time_delay = new Date().getTime() - time_start;
|
2707 |
|
2722 |
|
2723 |
function hls_check() {
|
2724 |
if( api.ready && api.playing && !api.loading && !api.finished ) {
|
2725 |
+
clearInterval(no_progress);
|
2726 |
console.log('HLS stream stale for '+time_delay+' ms, triggering error!');
|
2727 |
fv_player_notice(root,fv_flowplayer_translations.video_reload+' <a class="fv-player-reload" href="#">↻</a>','progress error unload');
|
2728 |
jQuery('.fv-player-reload').click( function() {
|
includes/aws/Aws/Api/AbstractModel.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Base class that is used by most API shapes
|
6 |
+
*/
|
7 |
+
abstract class AbstractModel implements \ArrayAccess
|
8 |
+
{
|
9 |
+
/** @var array */
|
10 |
+
protected $definition;
|
11 |
+
|
12 |
+
/** @var ShapeMap */
|
13 |
+
protected $shapeMap;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param array $definition Service description
|
17 |
+
* @param ShapeMap $shapeMap Shapemap used for creating shapes
|
18 |
+
*/
|
19 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
20 |
+
{
|
21 |
+
$this->definition = $definition;
|
22 |
+
$this->shapeMap = $shapeMap;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function toArray()
|
26 |
+
{
|
27 |
+
return $this->definition;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function offsetGet($offset)
|
31 |
+
{
|
32 |
+
return isset($this->definition[$offset])
|
33 |
+
? $this->definition[$offset] : null;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function offsetSet($offset, $value)
|
37 |
+
{
|
38 |
+
$this->definition[$offset] = $value;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function offsetExists($offset)
|
42 |
+
{
|
43 |
+
return isset($this->definition[$offset]);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function offsetUnset($offset)
|
47 |
+
{
|
48 |
+
unset($this->definition[$offset]);
|
49 |
+
}
|
50 |
+
|
51 |
+
protected function shapeAt($key)
|
52 |
+
{
|
53 |
+
if (!isset($this->definition[$key])) {
|
54 |
+
throw new \InvalidArgumentException('Expected shape definition at '
|
55 |
+
. $key);
|
56 |
+
}
|
57 |
+
|
58 |
+
return $this->shapeFor($this->definition[$key]);
|
59 |
+
}
|
60 |
+
|
61 |
+
protected function shapeFor(array $definition)
|
62 |
+
{
|
63 |
+
return isset($definition['shape'])
|
64 |
+
? $this->shapeMap->resolve($definition)
|
65 |
+
: Shape::create($definition, $this->shapeMap);
|
66 |
+
}
|
67 |
+
}
|
includes/aws/Aws/Api/ApiProvider.php
ADDED
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
use Aws\Exception\UnresolvedApiException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* API providers.
|
8 |
+
*
|
9 |
+
* An API provider is a function that accepts a type, service, and version and
|
10 |
+
* returns an array of API data on success or NULL if no API data can be created
|
11 |
+
* for the provided arguments.
|
12 |
+
*
|
13 |
+
* You can wrap your calls to an API provider with the
|
14 |
+
* {@see ApiProvider::resolve} method to ensure that API data is created. If the
|
15 |
+
* API data is not created, then the resolve() method will throw a
|
16 |
+
* {@see Aws\Exception\UnresolvedApiException}.
|
17 |
+
*
|
18 |
+
* use Aws\Api\ApiProvider;
|
19 |
+
* $provider = ApiProvider::defaultProvider();
|
20 |
+
* // Returns an array or NULL.
|
21 |
+
* $data = $provider('api', 's3', '2006-03-01');
|
22 |
+
* // Returns an array or throws.
|
23 |
+
* $data = ApiProvider::resolve($provider, 'api', 'elasticfood', '2020-01-01');
|
24 |
+
*
|
25 |
+
* You can compose multiple providers into a single provider using
|
26 |
+
* {@see Aws\or_chain}. This method accepts providers as arguments and
|
27 |
+
* returns a new function that will invoke each provider until a non-null value
|
28 |
+
* is returned.
|
29 |
+
*
|
30 |
+
* $a = ApiProvider::filesystem(sys_get_temp_dir() . '/aws-beta-models');
|
31 |
+
* $b = ApiProvider::manifest();
|
32 |
+
*
|
33 |
+
* $c = \Aws\or_chain($a, $b);
|
34 |
+
* $data = $c('api', 'betaservice', '2015-08-08'); // $a handles this.
|
35 |
+
* $data = $c('api', 's3', '2006-03-01'); // $b handles this.
|
36 |
+
* $data = $c('api', 'invalid', '2014-12-15'); // Neither handles this.
|
37 |
+
*/
|
38 |
+
class ApiProvider
|
39 |
+
{
|
40 |
+
/** @var array A map of public API type names to their file suffix. */
|
41 |
+
private static $typeMap = [
|
42 |
+
'api' => 'api-2',
|
43 |
+
'paginator' => 'paginators-1',
|
44 |
+
'waiter' => 'waiters-2',
|
45 |
+
'docs' => 'docs-2',
|
46 |
+
];
|
47 |
+
|
48 |
+
/** @var array API manifest */
|
49 |
+
private $manifest;
|
50 |
+
|
51 |
+
/** @var string The directory containing service models. */
|
52 |
+
private $modelsDir;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Resolves an API provider and ensures a non-null return value.
|
56 |
+
*
|
57 |
+
* @param callable $provider Provider function to invoke.
|
58 |
+
* @param string $type Type of data ('api', 'waiter', 'paginator').
|
59 |
+
* @param string $service Service name.
|
60 |
+
* @param string $version API version.
|
61 |
+
*
|
62 |
+
* @return array
|
63 |
+
* @throws UnresolvedApiException
|
64 |
+
*/
|
65 |
+
public static function resolve(callable $provider, $type, $service, $version)
|
66 |
+
{
|
67 |
+
// Execute the provider and return the result, if there is one.
|
68 |
+
$result = $provider($type, $service, $version);
|
69 |
+
if (is_array($result)) {
|
70 |
+
return $result;
|
71 |
+
}
|
72 |
+
|
73 |
+
// Throw an exception with a message depending on the inputs.
|
74 |
+
if (!isset(self::$typeMap[$type])) {
|
75 |
+
$msg = "The type must be one of: " . implode(', ', self::$typeMap);
|
76 |
+
} elseif ($service) {
|
77 |
+
$msg = "The {$service} service does not have version: {$version}.";
|
78 |
+
} else {
|
79 |
+
$msg = "You must specify a service name to retrieve its API data.";
|
80 |
+
}
|
81 |
+
|
82 |
+
throw new UnresolvedApiException($msg);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Default SDK API provider.
|
87 |
+
*
|
88 |
+
* This provider loads pre-built manifest data from the `data` directory.
|
89 |
+
*
|
90 |
+
* @return self
|
91 |
+
*/
|
92 |
+
public static function defaultProvider()
|
93 |
+
{
|
94 |
+
return new self(__DIR__ . '/../data', \Aws\manifest());
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Loads API data after resolving the version to the latest, compatible,
|
99 |
+
* available version based on the provided manifest data.
|
100 |
+
*
|
101 |
+
* Manifest data is essentially an associative array of service names to
|
102 |
+
* associative arrays of API version aliases.
|
103 |
+
*
|
104 |
+
* [
|
105 |
+
* ...
|
106 |
+
* 'ec2' => [
|
107 |
+
* 'latest' => '2014-10-01',
|
108 |
+
* '2014-10-01' => '2014-10-01',
|
109 |
+
* '2014-09-01' => '2014-10-01',
|
110 |
+
* '2014-06-15' => '2014-10-01',
|
111 |
+
* ...
|
112 |
+
* ],
|
113 |
+
* 'ecs' => [...],
|
114 |
+
* 'elasticache' => [...],
|
115 |
+
* ...
|
116 |
+
* ]
|
117 |
+
*
|
118 |
+
* @param string $dir Directory containing service models.
|
119 |
+
* @param array $manifest The API version manifest data.
|
120 |
+
*
|
121 |
+
* @return self
|
122 |
+
*/
|
123 |
+
public static function manifest($dir, array $manifest)
|
124 |
+
{
|
125 |
+
return new self($dir, $manifest);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Loads API data from the specified directory.
|
130 |
+
*
|
131 |
+
* If "latest" is specified as the version, this provider must glob the
|
132 |
+
* directory to find which is the latest available version.
|
133 |
+
*
|
134 |
+
* @param string $dir Directory containing service models.
|
135 |
+
*
|
136 |
+
* @return self
|
137 |
+
* @throws \InvalidArgumentException if the provided `$dir` is invalid.
|
138 |
+
*/
|
139 |
+
public static function filesystem($dir)
|
140 |
+
{
|
141 |
+
return new self($dir);
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Retrieves a list of valid versions for the specified service.
|
146 |
+
*
|
147 |
+
* @param string $service Service name
|
148 |
+
*
|
149 |
+
* @return array
|
150 |
+
*/
|
151 |
+
public function getVersions($service)
|
152 |
+
{
|
153 |
+
if (!isset($this->manifest)) {
|
154 |
+
$this->buildVersionsList($service);
|
155 |
+
}
|
156 |
+
|
157 |
+
if (!isset($this->manifest[$service]['versions'])) {
|
158 |
+
return [];
|
159 |
+
}
|
160 |
+
|
161 |
+
return array_values(array_unique($this->manifest[$service]['versions']));
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Execute the the provider.
|
166 |
+
*
|
167 |
+
* @param string $type Type of data ('api', 'waiter', 'paginator').
|
168 |
+
* @param string $service Service name.
|
169 |
+
* @param string $version API version.
|
170 |
+
*
|
171 |
+
* @return array|null
|
172 |
+
*/
|
173 |
+
public function __invoke($type, $service, $version)
|
174 |
+
{
|
175 |
+
// Resolve the type or return null.
|
176 |
+
if (isset(self::$typeMap[$type])) {
|
177 |
+
$type = self::$typeMap[$type];
|
178 |
+
} else {
|
179 |
+
return null;
|
180 |
+
}
|
181 |
+
|
182 |
+
// Resolve the version or return null.
|
183 |
+
if (!isset($this->manifest)) {
|
184 |
+
$this->buildVersionsList($service);
|
185 |
+
}
|
186 |
+
|
187 |
+
if (!isset($this->manifest[$service]['versions'][$version])) {
|
188 |
+
return null;
|
189 |
+
}
|
190 |
+
|
191 |
+
$version = $this->manifest[$service]['versions'][$version];
|
192 |
+
$path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json";
|
193 |
+
|
194 |
+
try {
|
195 |
+
return \Aws\load_compiled_json($path);
|
196 |
+
} catch (\InvalidArgumentException $e) {
|
197 |
+
return null;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* @param string $modelsDir Directory containing service models.
|
203 |
+
* @param array $manifest The API version manifest data.
|
204 |
+
*/
|
205 |
+
private function __construct($modelsDir, array $manifest = null)
|
206 |
+
{
|
207 |
+
$this->manifest = $manifest;
|
208 |
+
$this->modelsDir = rtrim($modelsDir, '/');
|
209 |
+
if (!is_dir($this->modelsDir)) {
|
210 |
+
throw new \InvalidArgumentException(
|
211 |
+
"The specified models directory, {$modelsDir}, was not found."
|
212 |
+
);
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Build the versions list for the specified service by globbing the dir.
|
218 |
+
*/
|
219 |
+
private function buildVersionsList($service)
|
220 |
+
{
|
221 |
+
$dir = "{$this->modelsDir}/{$service}/";
|
222 |
+
|
223 |
+
if (!is_dir($dir)) {
|
224 |
+
return;
|
225 |
+
}
|
226 |
+
|
227 |
+
// Get versions, remove . and .., and sort in descending order.
|
228 |
+
$results = array_diff(scandir($dir, SCANDIR_SORT_DESCENDING), ['..', '.']);
|
229 |
+
|
230 |
+
if (!$results) {
|
231 |
+
$this->manifest[$service] = ['versions' => []];
|
232 |
+
} else {
|
233 |
+
$this->manifest[$service] = [
|
234 |
+
'versions' => [
|
235 |
+
'latest' => $results[0]
|
236 |
+
]
|
237 |
+
];
|
238 |
+
$this->manifest[$service]['versions'] += array_combine($results, $results);
|
239 |
+
}
|
240 |
+
}
|
241 |
+
}
|
includes/aws/Aws/Api/DateTimeResult.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* DateTime overrides that make DateTime work more seamlessly as a string,
|
6 |
+
* with JSON documents, and with JMESPath.
|
7 |
+
*/
|
8 |
+
class DateTimeResult extends \DateTime implements \JsonSerializable
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Create a new DateTimeResult from a unix timestamp.
|
12 |
+
*
|
13 |
+
* @param $unixTimestamp
|
14 |
+
*
|
15 |
+
* @return DateTimeResult
|
16 |
+
*/
|
17 |
+
public static function fromEpoch($unixTimestamp)
|
18 |
+
{
|
19 |
+
return new self(gmdate('c', $unixTimestamp));
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Serialize the DateTimeResult as an ISO 8601 date string.
|
24 |
+
*
|
25 |
+
* @return string
|
26 |
+
*/
|
27 |
+
public function __toString()
|
28 |
+
{
|
29 |
+
return $this->format('c');
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Serialize the date as an ISO 8601 date when serializing as JSON.
|
34 |
+
*
|
35 |
+
* @return mixed|string
|
36 |
+
*/
|
37 |
+
public function jsonSerialize()
|
38 |
+
{
|
39 |
+
return (string) $this;
|
40 |
+
}
|
41 |
+
}
|
includes/aws/Aws/Api/DocModel.php
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Encapsulates the documentation strings for a given service-version and
|
6 |
+
* provides methods for extracting the desired parts related to a service,
|
7 |
+
* operation, error, or shape (i.e., parameter).
|
8 |
+
*/
|
9 |
+
class DocModel
|
10 |
+
{
|
11 |
+
/** @var array */
|
12 |
+
private $docs;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param array $docs
|
16 |
+
*
|
17 |
+
* @throws \RuntimeException
|
18 |
+
*/
|
19 |
+
public function __construct(array $docs)
|
20 |
+
{
|
21 |
+
if (!extension_loaded('tidy')) {
|
22 |
+
throw new \RuntimeException('The "tidy" PHP extension is required.');
|
23 |
+
}
|
24 |
+
|
25 |
+
$this->docs = $docs;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Convert the doc model to an array.
|
30 |
+
*
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
public function toArray()
|
34 |
+
{
|
35 |
+
return $this->docs;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Retrieves documentation about the service.
|
40 |
+
*
|
41 |
+
* @return null|string
|
42 |
+
*/
|
43 |
+
public function getServiceDocs()
|
44 |
+
{
|
45 |
+
return isset($this->docs['service']) ? $this->docs['service'] : null;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Retrieves documentation about an operation.
|
50 |
+
*
|
51 |
+
* @param string $operation Name of the operation
|
52 |
+
*
|
53 |
+
* @return null|string
|
54 |
+
*/
|
55 |
+
public function getOperationDocs($operation)
|
56 |
+
{
|
57 |
+
return isset($this->docs['operations'][$operation])
|
58 |
+
? $this->docs['operations'][$operation]
|
59 |
+
: null;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Retrieves documentation about an error.
|
64 |
+
*
|
65 |
+
* @param string $error Name of the error
|
66 |
+
*
|
67 |
+
* @return null|string
|
68 |
+
*/
|
69 |
+
public function getErrorDocs($error)
|
70 |
+
{
|
71 |
+
return isset($this->docs['shapes'][$error]['base'])
|
72 |
+
? $this->docs['shapes'][$error]['base']
|
73 |
+
: null;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Retrieves documentation about a shape, specific to the context.
|
78 |
+
*
|
79 |
+
* @param string $shapeName Name of the shape.
|
80 |
+
* @param string $parentName Name of the parent/context shape.
|
81 |
+
* @param string $ref Name used by the context to reference the shape.
|
82 |
+
*
|
83 |
+
* @return null|string
|
84 |
+
*/
|
85 |
+
public function getShapeDocs($shapeName, $parentName, $ref)
|
86 |
+
{
|
87 |
+
if (!isset($this->docs['shapes'][$shapeName])) {
|
88 |
+
return '';
|
89 |
+
}
|
90 |
+
|
91 |
+
$result = '';
|
92 |
+
$d = $this->docs['shapes'][$shapeName];
|
93 |
+
if (isset($d['refs']["{$parentName}\$${ref}"])) {
|
94 |
+
$result = $d['refs']["{$parentName}\$${ref}"];
|
95 |
+
} elseif (isset($d['base'])) {
|
96 |
+
$result = $d['base'];
|
97 |
+
}
|
98 |
+
|
99 |
+
if (isset($d['append'])) {
|
100 |
+
$result .= $d['append'];
|
101 |
+
}
|
102 |
+
|
103 |
+
return $this->clean($result);
|
104 |
+
}
|
105 |
+
|
106 |
+
private function clean($content)
|
107 |
+
{
|
108 |
+
if (!$content) {
|
109 |
+
return '';
|
110 |
+
}
|
111 |
+
|
112 |
+
$tidy = new \Tidy();
|
113 |
+
$tidy->parseString($content, [
|
114 |
+
'indent' => true,
|
115 |
+
'doctype' => 'omit',
|
116 |
+
'output-html' => true,
|
117 |
+
'show-body-only' => true,
|
118 |
+
'drop-empty-paras' => true,
|
119 |
+
'drop-font-tags' => true,
|
120 |
+
'drop-proprietary-attributes' => true,
|
121 |
+
'hide-comments' => true,
|
122 |
+
'logical-emphasis' => true
|
123 |
+
]);
|
124 |
+
$tidy->cleanRepair();
|
125 |
+
|
126 |
+
return (string) $content;
|
127 |
+
}
|
128 |
+
}
|
includes/aws/Aws/Api/ErrorParser/JsonParserTrait.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\ErrorParser;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\PayloadParserTrait;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Provides basic JSON error parsing functionality.
|
9 |
+
*/
|
10 |
+
trait JsonParserTrait
|
11 |
+
{
|
12 |
+
use PayloadParserTrait;
|
13 |
+
|
14 |
+
private function genericHandler(ResponseInterface $response)
|
15 |
+
{
|
16 |
+
$code = (string) $response->getStatusCode();
|
17 |
+
|
18 |
+
return [
|
19 |
+
'request_id' => (string) $response->getHeaderLine('x-amzn-requestid'),
|
20 |
+
'code' => null,
|
21 |
+
'message' => null,
|
22 |
+
'type' => $code[0] == '4' ? 'client' : 'server',
|
23 |
+
'parsed' => $this->parseJson($response->getBody())
|
24 |
+
];
|
25 |
+
}
|
26 |
+
}
|
includes/aws/Aws/Api/ErrorParser/JsonRpcErrorParser.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\ErrorParser;
|
3 |
+
|
4 |
+
use Psr\Http\Message\ResponseInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Parsers JSON-RPC errors.
|
8 |
+
*/
|
9 |
+
class JsonRpcErrorParser
|
10 |
+
{
|
11 |
+
use JsonParserTrait;
|
12 |
+
|
13 |
+
public function __invoke(ResponseInterface $response)
|
14 |
+
{
|
15 |
+
$data = $this->genericHandler($response);
|
16 |
+
// Make the casing consistent across services.
|
17 |
+
if ($data['parsed']) {
|
18 |
+
$data['parsed'] = array_change_key_case($data['parsed']);
|
19 |
+
}
|
20 |
+
|
21 |
+
if (isset($data['parsed']['__type'])) {
|
22 |
+
$parts = explode('#', $data['parsed']['__type']);
|
23 |
+
$data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
|
24 |
+
$data['message'] = isset($data['parsed']['message'])
|
25 |
+
? $data['parsed']['message']
|
26 |
+
: null;
|
27 |
+
}
|
28 |
+
|
29 |
+
return $data;
|
30 |
+
}
|
31 |
+
}
|
includes/aws/Aws/Api/ErrorParser/RestJsonErrorParser.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\ErrorParser;
|
3 |
+
|
4 |
+
use Psr\Http\Message\ResponseInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Parses JSON-REST errors.
|
8 |
+
*/
|
9 |
+
class RestJsonErrorParser
|
10 |
+
{
|
11 |
+
use JsonParserTrait;
|
12 |
+
|
13 |
+
public function __invoke(ResponseInterface $response)
|
14 |
+
{
|
15 |
+
$data = $this->genericHandler($response);
|
16 |
+
|
17 |
+
// Merge in error data from the JSON body
|
18 |
+
if ($json = $data['parsed']) {
|
19 |
+
$data = array_replace($data, $json);
|
20 |
+
}
|
21 |
+
|
22 |
+
// Correct error type from services like Amazon Glacier
|
23 |
+
if (!empty($data['type'])) {
|
24 |
+
$data['type'] = strtolower($data['type']);
|
25 |
+
}
|
26 |
+
|
27 |
+
// Retrieve the error code from services like Amazon Elastic Transcoder
|
28 |
+
if ($code = $response->getHeaderLine('x-amzn-errortype')) {
|
29 |
+
$colon = strpos($code, ':');
|
30 |
+
$data['code'] = $colon ? substr($code, 0, $colon) : $code;
|
31 |
+
}
|
32 |
+
|
33 |
+
return $data;
|
34 |
+
}
|
35 |
+
}
|
includes/aws/Aws/Api/ErrorParser/XmlErrorParser.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\ErrorParser;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\PayloadParserTrait;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Parses XML errors.
|
9 |
+
*/
|
10 |
+
class XmlErrorParser
|
11 |
+
{
|
12 |
+
use PayloadParserTrait;
|
13 |
+
|
14 |
+
public function __invoke(ResponseInterface $response)
|
15 |
+
{
|
16 |
+
$code = (string) $response->getStatusCode();
|
17 |
+
|
18 |
+
$data = [
|
19 |
+
'type' => $code[0] == '4' ? 'client' : 'server',
|
20 |
+
'request_id' => null,
|
21 |
+
'code' => null,
|
22 |
+
'message' => null,
|
23 |
+
'parsed' => null
|
24 |
+
];
|
25 |
+
|
26 |
+
$body = $response->getBody();
|
27 |
+
if ($body->getSize() > 0) {
|
28 |
+
$this->parseBody($this->parseXml($body), $data);
|
29 |
+
} else {
|
30 |
+
$this->parseHeaders($response, $data);
|
31 |
+
}
|
32 |
+
|
33 |
+
return $data;
|
34 |
+
}
|
35 |
+
|
36 |
+
private function parseHeaders(ResponseInterface $response, array &$data)
|
37 |
+
{
|
38 |
+
if ($response->getStatusCode() == '404') {
|
39 |
+
$data['code'] = 'NotFound';
|
40 |
+
}
|
41 |
+
|
42 |
+
$data['message'] = $response->getStatusCode() . ' '
|
43 |
+
. $response->getReasonPhrase();
|
44 |
+
|
45 |
+
if ($requestId = $response->getHeaderLine('x-amz-request-id')) {
|
46 |
+
$data['request_id'] = $requestId;
|
47 |
+
$data['message'] .= " (Request-ID: $requestId)";
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
private function parseBody(\SimpleXMLElement $body, array &$data)
|
52 |
+
{
|
53 |
+
$data['parsed'] = $body;
|
54 |
+
|
55 |
+
$namespaces = $body->getDocNamespaces();
|
56 |
+
if (!isset($namespaces[''])) {
|
57 |
+
$prefix = '';
|
58 |
+
} else {
|
59 |
+
// Account for the default namespace being defined and PHP not
|
60 |
+
// being able to handle it :(.
|
61 |
+
$body->registerXPathNamespace('ns', $namespaces['']);
|
62 |
+
$prefix = 'ns:';
|
63 |
+
}
|
64 |
+
|
65 |
+
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
|
66 |
+
$data['code'] = (string) $tempXml[0];
|
67 |
+
}
|
68 |
+
|
69 |
+
if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
|
70 |
+
$data['message'] = (string) $tempXml[0];
|
71 |
+
}
|
72 |
+
|
73 |
+
$tempXml = $body->xpath("//{$prefix}RequestId[1]");
|
74 |
+
if (empty($tempXml)) {
|
75 |
+
$tempXml = $body->xpath("//{$prefix}RequestID[1]");
|
76 |
+
}
|
77 |
+
|
78 |
+
if (isset($tempXml[0])) {
|
79 |
+
$data['request_id'] = (string) $tempXml[0];
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
includes/aws/Aws/Api/ListShape.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents a list shape.
|
6 |
+
*/
|
7 |
+
class ListShape extends Shape
|
8 |
+
{
|
9 |
+
private $member;
|
10 |
+
|
11 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
12 |
+
{
|
13 |
+
$definition['type'] = 'list';
|
14 |
+
parent::__construct($definition, $shapeMap);
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @return Shape
|
19 |
+
* @throws \RuntimeException if no member is specified
|
20 |
+
*/
|
21 |
+
public function getMember()
|
22 |
+
{
|
23 |
+
if (!$this->member) {
|
24 |
+
if (!isset($this->definition['member'])) {
|
25 |
+
throw new \RuntimeException('No member attribute specified');
|
26 |
+
}
|
27 |
+
$this->member = Shape::create(
|
28 |
+
$this->definition['member'],
|
29 |
+
$this->shapeMap
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
return $this->member;
|
34 |
+
}
|
35 |
+
}
|
includes/aws/Aws/Api/MapShape.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents a map shape.
|
6 |
+
*/
|
7 |
+
class MapShape extends Shape
|
8 |
+
{
|
9 |
+
/** @var Shape */
|
10 |
+
private $value;
|
11 |
+
|
12 |
+
/** @var Shape */
|
13 |
+
private $key;
|
14 |
+
|
15 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
16 |
+
{
|
17 |
+
$definition['type'] = 'map';
|
18 |
+
parent::__construct($definition, $shapeMap);
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return Shape
|
23 |
+
* @throws \RuntimeException if no value is specified
|
24 |
+
*/
|
25 |
+
public function getValue()
|
26 |
+
{
|
27 |
+
if (!$this->value) {
|
28 |
+
if (!isset($this->definition['value'])) {
|
29 |
+
throw new \RuntimeException('No value specified');
|
30 |
+
}
|
31 |
+
|
32 |
+
$this->value = Shape::create(
|
33 |
+
$this->definition['value'],
|
34 |
+
$this->shapeMap
|
35 |
+
);
|
36 |
+
}
|
37 |
+
|
38 |
+
return $this->value;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return Shape
|
43 |
+
*/
|
44 |
+
public function getKey()
|
45 |
+
{
|
46 |
+
if (!$this->key) {
|
47 |
+
$this->key = isset($this->definition['key'])
|
48 |
+
? Shape::create($this->definition['key'], $this->shapeMap)
|
49 |
+
: new Shape(['type' => 'string'], $this->shapeMap);
|
50 |
+
}
|
51 |
+
|
52 |
+
return $this->key;
|
53 |
+
}
|
54 |
+
}
|
includes/aws/Aws/Api/Operation.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents an API operation.
|
6 |
+
*/
|
7 |
+
class Operation extends AbstractModel
|
8 |
+
{
|
9 |
+
private $input;
|
10 |
+
private $output;
|
11 |
+
private $errors;
|
12 |
+
|
13 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
14 |
+
{
|
15 |
+
$definition['type'] = 'structure';
|
16 |
+
|
17 |
+
if (!isset($definition['http']['method'])) {
|
18 |
+
$definition['http']['method'] = 'POST';
|
19 |
+
}
|
20 |
+
|
21 |
+
if (!isset($definition['http']['requestUri'])) {
|
22 |
+
$definition['http']['requestUri'] = '/';
|
23 |
+
}
|
24 |
+
|
25 |
+
parent::__construct($definition, $shapeMap);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Returns an associative array of the HTTP attribute of the operation:
|
30 |
+
*
|
31 |
+
* - method: HTTP method of the operation
|
32 |
+
* - requestUri: URI of the request (can include URI template placeholders)
|
33 |
+
*
|
34 |
+
* @return array
|
35 |
+
*/
|
36 |
+
public function getHttp()
|
37 |
+
{
|
38 |
+
return $this->definition['http'];
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Get the input shape of the operation.
|
43 |
+
*
|
44 |
+
* @return StructureShape
|
45 |
+
*/
|
46 |
+
public function getInput()
|
47 |
+
{
|
48 |
+
if (!$this->input) {
|
49 |
+
if ($input = $this['input']) {
|
50 |
+
$this->input = $this->shapeFor($input);
|
51 |
+
} else {
|
52 |
+
$this->input = new StructureShape([], $this->shapeMap);
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
return $this->input;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Get the output shape of the operation.
|
61 |
+
*
|
62 |
+
* @return StructureShape
|
63 |
+
*/
|
64 |
+
public function getOutput()
|
65 |
+
{
|
66 |
+
if (!$this->output) {
|
67 |
+
if ($output = $this['output']) {
|
68 |
+
$this->output = $this->shapeFor($output);
|
69 |
+
} else {
|
70 |
+
$this->output = new StructureShape([], $this->shapeMap);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
return $this->output;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Get an array of operation error shapes.
|
79 |
+
*
|
80 |
+
* @return Shape[]
|
81 |
+
*/
|
82 |
+
public function getErrors()
|
83 |
+
{
|
84 |
+
if ($this->errors === null) {
|
85 |
+
if ($errors = $this['errors']) {
|
86 |
+
foreach ($errors as &$error) {
|
87 |
+
$error = $this->shapeFor($error);
|
88 |
+
}
|
89 |
+
$this->errors = $errors;
|
90 |
+
} else {
|
91 |
+
$this->errors = [];
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
return $this->errors;
|
96 |
+
}
|
97 |
+
}
|
includes/aws/Aws/Api/Parser/AbstractParser.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Aws\ResultInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @internal
|
11 |
+
*/
|
12 |
+
abstract class AbstractParser
|
13 |
+
{
|
14 |
+
/** @var \Aws\Api\Service Representation of the service API*/
|
15 |
+
protected $api;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param Service $api Service description.
|
19 |
+
*/
|
20 |
+
public function __construct(Service $api)
|
21 |
+
{
|
22 |
+
$this->api = $api;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param CommandInterface $command Command that was executed.
|
27 |
+
* @param ResponseInterface $response Response that was received.
|
28 |
+
*
|
29 |
+
* @return ResultInterface
|
30 |
+
*/
|
31 |
+
abstract public function __invoke(
|
32 |
+
CommandInterface $command,
|
33 |
+
ResponseInterface $response
|
34 |
+
);
|
35 |
+
}
|
includes/aws/Aws/Api/Parser/AbstractRestParser.php
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\DateTimeResult;
|
5 |
+
use Aws\Api\Shape;
|
6 |
+
use Aws\Api\StructureShape;
|
7 |
+
use Aws\Result;
|
8 |
+
use Aws\CommandInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @internal
|
13 |
+
*/
|
14 |
+
abstract class AbstractRestParser extends AbstractParser
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* Parses a payload from a response.
|
18 |
+
*
|
19 |
+
* @param ResponseInterface $response Response to parse.
|
20 |
+
* @param StructureShape $member Member to parse
|
21 |
+
* @param array $result Result value
|
22 |
+
*
|
23 |
+
* @return mixed
|
24 |
+
*/
|
25 |
+
abstract protected function payload(
|
26 |
+
ResponseInterface $response,
|
27 |
+
StructureShape $member,
|
28 |
+
array &$result
|
29 |
+
);
|
30 |
+
|
31 |
+
public function __invoke(
|
32 |
+
CommandInterface $command,
|
33 |
+
ResponseInterface $response
|
34 |
+
) {
|
35 |
+
$output = $this->api->getOperation($command->getName())->getOutput();
|
36 |
+
$result = [];
|
37 |
+
|
38 |
+
if ($payload = $output['payload']) {
|
39 |
+
$this->extractPayload($payload, $output, $response, $result);
|
40 |
+
}
|
41 |
+
|
42 |
+
foreach ($output->getMembers() as $name => $member) {
|
43 |
+
switch ($member['location']) {
|
44 |
+
case 'header':
|
45 |
+
$this->extractHeader($name, $member, $response, $result);
|
46 |
+
break;
|
47 |
+
case 'headers':
|
48 |
+
$this->extractHeaders($name, $member, $response, $result);
|
49 |
+
break;
|
50 |
+
case 'statusCode':
|
51 |
+
$this->extractStatus($name, $response, $result);
|
52 |
+
break;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
if (!$payload && $response->getBody()->getSize() > 0) {
|
57 |
+
// if no payload was found, then parse the contents of the body
|
58 |
+
$this->payload($response, $output, $result);
|
59 |
+
}
|
60 |
+
|
61 |
+
return new Result($result);
|
62 |
+
}
|
63 |
+
|
64 |
+
private function extractPayload(
|
65 |
+
$payload,
|
66 |
+
StructureShape $output,
|
67 |
+
ResponseInterface $response,
|
68 |
+
array &$result
|
69 |
+
) {
|
70 |
+
$member = $output->getMember($payload);
|
71 |
+
|
72 |
+
if ($member instanceof StructureShape) {
|
73 |
+
// Structure members parse top-level data into a specific key.
|
74 |
+
$result[$payload] = [];
|
75 |
+
$this->payload($response, $member, $result[$payload]);
|
76 |
+
} else {
|
77 |
+
// Streaming data is just the stream from the response body.
|
78 |
+
$result[$payload] = $response->getBody();
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Extract a single header from the response into the result.
|
84 |
+
*/
|
85 |
+
private function extractHeader(
|
86 |
+
$name,
|
87 |
+
Shape $shape,
|
88 |
+
ResponseInterface $response,
|
89 |
+
&$result
|
90 |
+
) {
|
91 |
+
$value = $response->getHeaderLine($shape['locationName'] ?: $name);
|
92 |
+
|
93 |
+
switch ($shape->getType()) {
|
94 |
+
case 'float':
|
95 |
+
case 'double':
|
96 |
+
$value = (float) $value;
|
97 |
+
break;
|
98 |
+
case 'long':
|
99 |
+
$value = (int) $value;
|
100 |
+
break;
|
101 |
+
case 'boolean':
|
102 |
+
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
103 |
+
break;
|
104 |
+
case 'blob':
|
105 |
+
$value = base64_decode($value);
|
106 |
+
break;
|
107 |
+
case 'timestamp':
|
108 |
+
try {
|
109 |
+
$value = new DateTimeResult($value);
|
110 |
+
break;
|
111 |
+
} catch (\Exception $e) {
|
112 |
+
// If the value cannot be parsed, then do not add it to the
|
113 |
+
// output structure.
|
114 |
+
return;
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
$result[$name] = $value;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Extract a map of headers with an optional prefix from the response.
|
123 |
+
*/
|
124 |
+
private function extractHeaders(
|
125 |
+
$name,
|
126 |
+
Shape $shape,
|
127 |
+
ResponseInterface $response,
|
128 |
+
&$result
|
129 |
+
) {
|
130 |
+
// Check if the headers are prefixed by a location name
|
131 |
+
$result[$name] = [];
|
132 |
+
$prefix = $shape['locationName'];
|
133 |
+
$prefixLen = strlen($prefix);
|
134 |
+
|
135 |
+
foreach ($response->getHeaders() as $k => $values) {
|
136 |
+
if (!$prefixLen) {
|
137 |
+
$result[$name][$k] = implode(', ', $values);
|
138 |
+
} elseif (stripos($k, $prefix) === 0) {
|
139 |
+
$result[$name][substr($k, $prefixLen)] = implode(', ', $values);
|
140 |
+
}
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Places the status code of the response into the result array.
|
146 |
+
*/
|
147 |
+
private function extractStatus(
|
148 |
+
$name,
|
149 |
+
ResponseInterface $response,
|
150 |
+
array &$result
|
151 |
+
) {
|
152 |
+
$result[$name] = (int) $response->getStatusCode();
|
153 |
+
}
|
154 |
+
}
|
includes/aws/Aws/Api/Parser/Crc32ValidatingParser.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Aws\Exception\AwsException;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @internal Decorates a parser and validates the x-amz-crc32 header.
|
11 |
+
*/
|
12 |
+
class Crc32ValidatingParser extends AbstractParser
|
13 |
+
{
|
14 |
+
/** @var callable */
|
15 |
+
private $parser;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param callable $parser Parser to wrap.
|
19 |
+
*/
|
20 |
+
public function __construct(callable $parser)
|
21 |
+
{
|
22 |
+
$this->parser = $parser;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function __invoke(
|
26 |
+
CommandInterface $command,
|
27 |
+
ResponseInterface $response
|
28 |
+
) {
|
29 |
+
if ($expected = $response->getHeaderLine('x-amz-crc32')) {
|
30 |
+
$hash = hexdec(Psr7\hash($response->getBody(), 'crc32b'));
|
31 |
+
if ($expected != $hash) {
|
32 |
+
throw new AwsException(
|
33 |
+
"crc32 mismatch. Expected {$expected}, found {$hash}.",
|
34 |
+
$command,
|
35 |
+
[
|
36 |
+
'code' => 'ClientChecksumMismatch',
|
37 |
+
'connection_error' => true,
|
38 |
+
'response' => $response
|
39 |
+
]
|
40 |
+
);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
$fn = $this->parser;
|
45 |
+
return $fn($command, $response);
|
46 |
+
}
|
47 |
+
}
|
includes/aws/Aws/Api/Parser/Exception/ParserException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser\Exception;
|
3 |
+
|
4 |
+
class ParserException extends \RuntimeException {}
|
includes/aws/Aws/Api/Parser/JsonParser.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\DateTimeResult;
|
5 |
+
use Aws\Api\Shape;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @internal Implements standard JSON parsing.
|
9 |
+
*/
|
10 |
+
class JsonParser
|
11 |
+
{
|
12 |
+
public function parse(Shape $shape, $value)
|
13 |
+
{
|
14 |
+
if ($value === null) {
|
15 |
+
return $value;
|
16 |
+
}
|
17 |
+
|
18 |
+
switch ($shape['type']) {
|
19 |
+
case 'structure':
|
20 |
+
$target = [];
|
21 |
+
foreach ($shape->getMembers() as $name => $member) {
|
22 |
+
$locationName = $member['locationName'] ?: $name;
|
23 |
+
if (isset($value[$locationName])) {
|
24 |
+
$target[$name] = $this->parse($member, $value[$locationName]);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
return $target;
|
28 |
+
|
29 |
+
case 'list':
|
30 |
+
$member = $shape->getMember();
|
31 |
+
$target = [];
|
32 |
+
foreach ($value as $v) {
|
33 |
+
$target[] = $this->parse($member, $v);
|
34 |
+
}
|
35 |
+
return $target;
|
36 |
+
|
37 |
+
case 'map':
|
38 |
+
$values = $shape->getValue();
|
39 |
+
$target = [];
|
40 |
+
foreach ($value as $k => $v) {
|
41 |
+
$target[$k] = $this->parse($values, $v);
|
42 |
+
}
|
43 |
+
return $target;
|
44 |
+
|
45 |
+
case 'timestamp':
|
46 |
+
// The Unix epoch (or Unix time or POSIX time or Unix
|
47 |
+
// timestamp) is the number of seconds that have elapsed since
|
48 |
+
// January 1, 1970 (midnight UTC/GMT).
|
49 |
+
return DateTimeResult::fromEpoch($value);
|
50 |
+
|
51 |
+
case 'blob':
|
52 |
+
return base64_decode($value);
|
53 |
+
|
54 |
+
default:
|
55 |
+
return $value;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
}
|
includes/aws/Aws/Api/Parser/JsonRpcParser.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Result;
|
6 |
+
use Aws\CommandInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @internal Implements JSON-RPC parsing (e.g., DynamoDB)
|
11 |
+
*/
|
12 |
+
class JsonRpcParser extends AbstractParser
|
13 |
+
{
|
14 |
+
use PayloadParserTrait;
|
15 |
+
|
16 |
+
private $parser;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param Service $api Service description
|
20 |
+
* @param JsonParser $parser JSON body builder
|
21 |
+
*/
|
22 |
+
public function __construct(Service $api, JsonParser $parser = null)
|
23 |
+
{
|
24 |
+
parent::__construct($api);
|
25 |
+
$this->parser = $parser ?: new JsonParser();
|
26 |
+
}
|
27 |
+
|
28 |
+
public function __invoke(
|
29 |
+
CommandInterface $command,
|
30 |
+
ResponseInterface $response
|
31 |
+
) {
|
32 |
+
$operation = $this->api->getOperation($command->getName());
|
33 |
+
$result = $this->parser->parse(
|
34 |
+
$operation->getOutput(),
|
35 |
+
$this->parseJson($response->getBody())
|
36 |
+
);
|
37 |
+
|
38 |
+
return new Result($result ?: []);
|
39 |
+
}
|
40 |
+
}
|
includes/aws/Aws/Api/Parser/PayloadParserTrait.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\Exception\ParserException;
|
5 |
+
|
6 |
+
trait PayloadParserTrait
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* @param string $json
|
10 |
+
*
|
11 |
+
* @throws ParserException
|
12 |
+
*
|
13 |
+
* @return array
|
14 |
+
*/
|
15 |
+
private function parseJson($json)
|
16 |
+
{
|
17 |
+
$jsonPayload = json_decode($json, true);
|
18 |
+
|
19 |
+
if (JSON_ERROR_NONE !== json_last_error()) {
|
20 |
+
throw new ParserException('Error parsing JSON: '
|
21 |
+
. json_last_error_msg());
|
22 |
+
}
|
23 |
+
|
24 |
+
return $jsonPayload;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @param string $xml
|
29 |
+
*
|
30 |
+
* @throws ParserException
|
31 |
+
*
|
32 |
+
* @return \SimpleXMLElement
|
33 |
+
*/
|
34 |
+
private function parseXml($xml)
|
35 |
+
{
|
36 |
+
$priorSetting = libxml_use_internal_errors(true);
|
37 |
+
try {
|
38 |
+
libxml_clear_errors();
|
39 |
+
$xmlPayload = new \SimpleXMLElement($xml);
|
40 |
+
if ($error = libxml_get_last_error()) {
|
41 |
+
throw new \RuntimeException($error->message);
|
42 |
+
}
|
43 |
+
} catch (\Exception $e) {
|
44 |
+
throw new ParserException("Error parsing XML: {$e->getMessage()}", 0, $e);
|
45 |
+
} finally {
|
46 |
+
libxml_use_internal_errors($priorSetting);
|
47 |
+
}
|
48 |
+
|
49 |
+
return $xmlPayload;
|
50 |
+
}
|
51 |
+
}
|
includes/aws/Aws/Api/Parser/QueryParser.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Result;
|
6 |
+
use Aws\CommandInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @internal Parses query (XML) responses (e.g., EC2, SQS, and many others)
|
11 |
+
*/
|
12 |
+
class QueryParser extends AbstractParser
|
13 |
+
{
|
14 |
+
use PayloadParserTrait;
|
15 |
+
|
16 |
+
/** @var XmlParser */
|
17 |
+
private $xmlParser;
|
18 |
+
|
19 |
+
/** @var bool */
|
20 |
+
private $honorResultWrapper;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param Service $api Service description
|
24 |
+
* @param XmlParser $xmlParser Optional XML parser
|
25 |
+
* @param bool $honorResultWrapper Set to false to disable the peeling
|
26 |
+
* back of result wrappers from the
|
27 |
+
* output structure.
|
28 |
+
*/
|
29 |
+
public function __construct(
|
30 |
+
Service $api,
|
31 |
+
XmlParser $xmlParser = null,
|
32 |
+
$honorResultWrapper = true
|
33 |
+
) {
|
34 |
+
parent::__construct($api);
|
35 |
+
$this->xmlParser = $xmlParser ?: new XmlParser();
|
36 |
+
$this->honorResultWrapper = $honorResultWrapper;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function __invoke(
|
40 |
+
CommandInterface $command,
|
41 |
+
ResponseInterface $response
|
42 |
+
) {
|
43 |
+
$output = $this->api->getOperation($command->getName())->getOutput();
|
44 |
+
$xml = $this->parseXml($response->getBody());
|
45 |
+
|
46 |
+
if ($this->honorResultWrapper && $output['resultWrapper']) {
|
47 |
+
$xml = $xml->{$output['resultWrapper']};
|
48 |
+
}
|
49 |
+
|
50 |
+
return new Result($this->xmlParser->parse($output, $xml));
|
51 |
+
}
|
52 |
+
}
|
includes/aws/Aws/Api/Parser/RestJsonParser.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Api\StructureShape;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder)
|
10 |
+
*/
|
11 |
+
class RestJsonParser extends AbstractRestParser
|
12 |
+
{
|
13 |
+
use PayloadParserTrait;
|
14 |
+
|
15 |
+
/** @var JsonParser */
|
16 |
+
private $parser;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param Service $api Service description
|
20 |
+
* @param JsonParser $parser JSON body builder
|
21 |
+
*/
|
22 |
+
public function __construct(Service $api, JsonParser $parser = null)
|
23 |
+
{
|
24 |
+
parent::__construct($api);
|
25 |
+
$this->parser = $parser ?: new JsonParser();
|
26 |
+
}
|
27 |
+
|
28 |
+
protected function payload(
|
29 |
+
ResponseInterface $response,
|
30 |
+
StructureShape $member,
|
31 |
+
array &$result
|
32 |
+
) {
|
33 |
+
$jsonBody = $this->parseJson($response->getBody());
|
34 |
+
|
35 |
+
if ($jsonBody) {
|
36 |
+
$result += $this->parser->parse($member, $jsonBody);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
includes/aws/Aws/Api/Parser/RestXmlParser.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\StructureShape;
|
5 |
+
use Aws\Api\Service;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...)
|
10 |
+
*/
|
11 |
+
class RestXmlParser extends AbstractRestParser
|
12 |
+
{
|
13 |
+
use PayloadParserTrait;
|
14 |
+
|
15 |
+
/** @var XmlParser */
|
16 |
+
private $parser;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param Service $api Service description
|
20 |
+
* @param XmlParser $parser XML body parser
|
21 |
+
*/
|
22 |
+
public function __construct(Service $api, XmlParser $parser = null)
|
23 |
+
{
|
24 |
+
parent::__construct($api);
|
25 |
+
$this->parser = $parser ?: new XmlParser();
|
26 |
+
}
|
27 |
+
|
28 |
+
protected function payload(
|
29 |
+
ResponseInterface $response,
|
30 |
+
StructureShape $member,
|
31 |
+
array &$result
|
32 |
+
) {
|
33 |
+
$xml = $this->parseXml($response->getBody());
|
34 |
+
$result += $this->parser->parse($member, $xml);
|
35 |
+
}
|
36 |
+
}
|
includes/aws/Aws/Api/Parser/XmlParser.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Parser;
|
3 |
+
|
4 |
+
use Aws\Api\DateTimeResult;
|
5 |
+
use Aws\Api\ListShape;
|
6 |
+
use Aws\Api\MapShape;
|
7 |
+
use Aws\Api\Shape;
|
8 |
+
use Aws\Api\StructureShape;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @internal Implements standard XML parsing for REST-XML and Query protocols.
|
12 |
+
*/
|
13 |
+
class XmlParser
|
14 |
+
{
|
15 |
+
public function parse(StructureShape $shape, \SimpleXMLElement $value)
|
16 |
+
{
|
17 |
+
return $this->dispatch($shape, $value);
|
18 |
+
}
|
19 |
+
|
20 |
+
private function dispatch($shape, \SimpleXMLElement $value)
|
21 |
+
{
|
22 |
+
static $methods = [
|
23 |
+
'structure' => 'parse_structure',
|
24 |
+
'list' => 'parse_list',
|
25 |
+
'map' => 'parse_map',
|
26 |
+
'blob' => 'parse_blob',
|
27 |
+
'boolean' => 'parse_boolean',
|
28 |
+
'integer' => 'parse_integer',
|
29 |
+
'float' => 'parse_float',
|
30 |
+
'double' => 'parse_float',
|
31 |
+
'timestamp' => 'parse_timestamp',
|
32 |
+
];
|
33 |
+
|
34 |
+
$type = $shape['type'];
|
35 |
+
if (isset($methods[$type])) {
|
36 |
+
return $this->{$methods[$type]}($shape, $value);
|
37 |
+
}
|
38 |
+
|
39 |
+
return (string) $value;
|
40 |
+
}
|
41 |
+
|
42 |
+
private function parse_structure(
|
43 |
+
StructureShape $shape,
|
44 |
+
\SimpleXMLElement $value
|
45 |
+
) {
|
46 |
+
$target = [];
|
47 |
+
|
48 |
+
foreach ($shape->getMembers() as $name => $member) {
|
49 |
+
// Extract the name of the XML node
|
50 |
+
$node = $this->memberKey($member, $name);
|
51 |
+
if (isset($value->{$node})) {
|
52 |
+
$target[$name] = $this->dispatch($member, $value->{$node});
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
return $target;
|
57 |
+
}
|
58 |
+
|
59 |
+
private function memberKey(Shape $shape, $name)
|
60 |
+
{
|
61 |
+
if (null !== $shape['locationName']) {
|
62 |
+
return $shape['locationName'];
|
63 |
+
}
|
64 |
+
|
65 |
+
if ($shape instanceof ListShape && $shape['flattened']) {
|
66 |
+
return $shape->getMember()['locationName'] ?: $name;
|
67 |
+
}
|
68 |
+
|
69 |
+
return $name;
|
70 |
+
}
|
71 |
+
|
72 |
+
private function parse_list(ListShape $shape, \SimpleXMLElement $value)
|
73 |
+
{
|
74 |
+
$target = [];
|
75 |
+
$member = $shape->getMember();
|
76 |
+
|
77 |
+
if (!$shape['flattened']) {
|
78 |
+
$value = $value->{$member['locationName'] ?: 'member'};
|
79 |
+
}
|
80 |
+
|
81 |
+
foreach ($value as $v) {
|
82 |
+
$target[] = $this->dispatch($member, $v);
|
83 |
+
}
|
84 |
+
|
85 |
+
return $target;
|
86 |
+
}
|
87 |
+
|
88 |
+
private function parse_map(MapShape $shape, \SimpleXMLElement $value)
|
89 |
+
{
|
90 |
+
$target = [];
|
91 |
+
|
92 |
+
if (!$shape['flattened']) {
|
93 |
+
$value = $value->entry;
|
94 |
+
}
|
95 |
+
|
96 |
+
$mapKey = $shape->getKey();
|
97 |
+
$mapValue = $shape->getValue();
|
98 |
+
$keyName = $shape->getKey()['locationName'] ?: 'key';
|
99 |
+
$valueName = $shape->getValue()['locationName'] ?: 'value';
|
100 |
+
|
101 |
+
foreach ($value as $node) {
|
102 |
+
$key = $this->dispatch($mapKey, $node->{$keyName});
|
103 |
+
$value = $this->dispatch($mapValue, $node->{$valueName});
|
104 |
+
$target[$key] = $value;
|
105 |
+
}
|
106 |
+
|
107 |
+
return $target;
|
108 |
+
}
|
109 |
+
|
110 |
+
private function parse_blob(Shape $shape, $value)
|
111 |
+
{
|
112 |
+
return base64_decode((string) $value);
|
113 |
+
}
|
114 |
+
|
115 |
+
private function parse_float(Shape $shape, $value)
|
116 |
+
{
|
117 |
+
return (float) (string) $value;
|
118 |
+
}
|
119 |
+
|
120 |
+
private function parse_integer(Shape $shape, $value)
|
121 |
+
{
|
122 |
+
return (int) (string) $value;
|
123 |
+
}
|
124 |
+
|
125 |
+
private function parse_boolean(Shape $shape, $value)
|
126 |
+
{
|
127 |
+
return $value == 'true' ? true : false;
|
128 |
+
}
|
129 |
+
|
130 |
+
private function parse_timestamp(Shape $shape, $value)
|
131 |
+
{
|
132 |
+
return new DateTimeResult($value);
|
133 |
+
}
|
134 |
+
}
|
includes/aws/Aws/Api/Serializer/Ec2ParamBuilder.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\Shape;
|
5 |
+
use Aws\Api\ListShape;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class Ec2ParamBuilder extends QueryParamBuilder
|
11 |
+
{
|
12 |
+
protected function queryName(Shape $shape, $default = null)
|
13 |
+
{
|
14 |
+
return ($shape['queryName']
|
15 |
+
?: ucfirst($shape['locationName']))
|
16 |
+
?: $default;
|
17 |
+
}
|
18 |
+
|
19 |
+
protected function isFlat(Shape $shape)
|
20 |
+
{
|
21 |
+
return false;
|
22 |
+
}
|
23 |
+
|
24 |
+
protected function format_list(
|
25 |
+
ListShape $shape,
|
26 |
+
array $value,
|
27 |
+
$prefix,
|
28 |
+
&$query
|
29 |
+
) {
|
30 |
+
// Handle empty list serialization
|
31 |
+
if (!$value) {
|
32 |
+
$query[$prefix] = false;
|
33 |
+
} else {
|
34 |
+
$items = $shape->getMember();
|
35 |
+
foreach ($value as $k => $v) {
|
36 |
+
$this->format($items, $v, $prefix . '.' . ($k + 1), $query);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
includes/aws/Aws/Api/Serializer/JsonBody.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Api\Shape;
|
6 |
+
use Aws\Api\TimestampShape;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Formats the JSON body of a JSON-REST or JSON-RPC operation.
|
10 |
+
* @internal
|
11 |
+
*/
|
12 |
+
class JsonBody
|
13 |
+
{
|
14 |
+
private $api;
|
15 |
+
|
16 |
+
public function __construct(Service $api)
|
17 |
+
{
|
18 |
+
$this->api = $api;
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Gets the JSON Content-Type header for a service API
|
23 |
+
*
|
24 |
+
* @param Service $service
|
25 |
+
*
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
+
public static function getContentType(Service $service)
|
29 |
+
{
|
30 |
+
return 'application/x-amz-json-'
|
31 |
+
. number_format($service->getMetadata('jsonVersion'), 1);
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Builds the JSON body based on an array of arguments.
|
36 |
+
*
|
37 |
+
* @param Shape $shape Operation being constructed
|
38 |
+
* @param array $args Associative array of arguments
|
39 |
+
*
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
public function build(Shape $shape, array $args)
|
43 |
+
{
|
44 |
+
$result = json_encode($this->format($shape, $args));
|
45 |
+
|
46 |
+
return $result == '[]' ? '{}' : $result;
|
47 |
+
}
|
48 |
+
|
49 |
+
private function format(Shape $shape, $value)
|
50 |
+
{
|
51 |
+
switch ($shape['type']) {
|
52 |
+
case 'structure':
|
53 |
+
$data = [];
|
54 |
+
foreach ($value as $k => $v) {
|
55 |
+
if ($v !== null && $shape->hasMember($k)) {
|
56 |
+
$valueShape = $shape->getMember($k);
|
57 |
+
$data[$valueShape['locationName'] ?: $k]
|
58 |
+
= $this->format($valueShape, $v);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
return $data;
|
62 |
+
|
63 |
+
case 'list':
|
64 |
+
$items = $shape->getMember();
|
65 |
+
foreach ($value as &$v) {
|
66 |
+
$v = $this->format($items, $v);
|
67 |
+
}
|
68 |
+
return $value;
|
69 |
+
|
70 |
+
case 'map':
|
71 |
+
if (empty($value)) {
|
72 |
+
return new \stdClass;
|
73 |
+
}
|
74 |
+
$values = $shape->getValue();
|
75 |
+
foreach ($value as &$v) {
|
76 |
+
$v = $this->format($values, $v);
|
77 |
+
}
|
78 |
+
return $value;
|
79 |
+
|
80 |
+
case 'blob':
|
81 |
+
return base64_encode($value);
|
82 |
+
|
83 |
+
case 'timestamp':
|
84 |
+
return TimestampShape::format($value, 'unixTimestamp');
|
85 |
+
|
86 |
+
default:
|
87 |
+
return $value;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
}
|
includes/aws/Aws/Api/Serializer/JsonRpcSerializer.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use GuzzleHttp\Psr7\Request;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Prepares a JSON-RPC request for transfer.
|
11 |
+
* @internal
|
12 |
+
*/
|
13 |
+
class JsonRpcSerializer
|
14 |
+
{
|
15 |
+
/** @var JsonBody */
|
16 |
+
private $jsonFormatter;
|
17 |
+
|
18 |
+
/** @var string */
|
19 |
+
private $endpoint;
|
20 |
+
|
21 |
+
/** @var Service */
|
22 |
+
private $api;
|
23 |
+
|
24 |
+
/** @var string */
|
25 |
+
private $contentType;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @param Service $api Service description
|
29 |
+
* @param string $endpoint Endpoint to connect to
|
30 |
+
* @param JsonBody $jsonFormatter Optional JSON formatter to use
|
31 |
+
*/
|
32 |
+
public function __construct(
|
33 |
+
Service $api,
|
34 |
+
$endpoint,
|
35 |
+
JsonBody $jsonFormatter = null
|
36 |
+
) {
|
37 |
+
$this->endpoint = $endpoint;
|
38 |
+
$this->api = $api;
|
39 |
+
$this->jsonFormatter = $jsonFormatter ?: new JsonBody($this->api);
|
40 |
+
$this->contentType = JsonBody::getContentType($api);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* When invoked with an AWS command, returns a serialization array
|
45 |
+
* containing "method", "uri", "headers", and "body" key value pairs.
|
46 |
+
*
|
47 |
+
* @param CommandInterface $command
|
48 |
+
*
|
49 |
+
* @return RequestInterface
|
50 |
+
*/
|
51 |
+
public function __invoke(CommandInterface $command)
|
52 |
+
{
|
53 |
+
$name = $command->getName();
|
54 |
+
$operation = $this->api->getOperation($name);
|
55 |
+
|
56 |
+
return new Request(
|
57 |
+
$operation['http']['method'],
|
58 |
+
$this->endpoint,
|
59 |
+
[
|
60 |
+
'X-Amz-Target' => $this->api->getMetadata('targetPrefix') . '.' . $name,
|
61 |
+
'Content-Type' => $this->contentType
|
62 |
+
],
|
63 |
+
$this->jsonFormatter->build(
|
64 |
+
$operation->getInput(),
|
65 |
+
$command->toArray()
|
66 |
+
)
|
67 |
+
);
|
68 |
+
}
|
69 |
+
}
|
includes/aws/Aws/Api/Serializer/QueryParamBuilder.php
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\StructureShape;
|
5 |
+
use Aws\Api\ListShape;
|
6 |
+
use Aws\Api\MapShape;
|
7 |
+
use Aws\Api\Shape;
|
8 |
+
use Aws\Api\TimestampShape;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @internal
|
12 |
+
*/
|
13 |
+
class QueryParamBuilder
|
14 |
+
{
|
15 |
+
private $methods;
|
16 |
+
|
17 |
+
protected function queryName(Shape $shape, $default = null)
|
18 |
+
{
|
19 |
+
if (null !== $shape['queryName']) {
|
20 |
+
return $shape['queryName'];
|
21 |
+
}
|
22 |
+
|
23 |
+
if (null !== $shape['locationName']) {
|
24 |
+
return $shape['locationName'];
|
25 |
+
}
|
26 |
+
|
27 |
+
if ($this->isFlat($shape) && !empty($shape['member']['locationName'])) {
|
28 |
+
return $shape['member']['locationName'];
|
29 |
+
}
|
30 |
+
|
31 |
+
return $default;
|
32 |
+
}
|
33 |
+
|
34 |
+
protected function isFlat(Shape $shape)
|
35 |
+
{
|
36 |
+
return $shape['flattened'] === true;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function __invoke(StructureShape $shape, array $params)
|
40 |
+
{
|
41 |
+
if (!$this->methods) {
|
42 |
+
$this->methods = array_fill_keys(get_class_methods($this), true);
|
43 |
+
}
|
44 |
+
|
45 |
+
$query = [];
|
46 |
+
$this->format_structure($shape, $params, '', $query);
|
47 |
+
|
48 |
+
return $query;
|
49 |
+
}
|
50 |
+
|
51 |
+
protected function format(Shape $shape, $value, $prefix, array &$query)
|
52 |
+
{
|
53 |
+
$type = 'format_' . $shape['type'];
|
54 |
+
if (isset($this->methods[$type])) {
|
55 |
+
$this->{$type}($shape, $value, $prefix, $query);
|
56 |
+
} else {
|
57 |
+
$query[$prefix] = (string) $value;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
protected function format_structure(
|
62 |
+
StructureShape $shape,
|
63 |
+
array $value,
|
64 |
+
$prefix,
|
65 |
+
&$query
|
66 |
+
) {
|
67 |
+
if ($prefix) {
|
68 |
+
$prefix .= '.';
|
69 |
+
}
|
70 |
+
|
71 |
+
foreach ($value as $k => $v) {
|
72 |
+
if ($shape->hasMember($k)) {
|
73 |
+
$member = $shape->getMember($k);
|
74 |
+
$this->format(
|
75 |
+
$member,
|
76 |
+
$v,
|
77 |
+
$prefix . $this->queryName($member, $k),
|
78 |
+
$query
|
79 |
+
);
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
protected function format_list(
|
85 |
+
ListShape $shape,
|
86 |
+
array $value,
|
87 |
+
$prefix,
|
88 |
+
&$query
|
89 |
+
) {
|
90 |
+
// Handle empty list serialization
|
91 |
+
if (!$value) {
|
92 |
+
$query[$prefix] = '';
|
93 |
+
return;
|
94 |
+
}
|
95 |
+
|
96 |
+
$items = $shape->getMember();
|
97 |
+
|
98 |
+
if (!$this->isFlat($shape)) {
|
99 |
+
$locationName = $shape->getMember()['locationName'] ?: 'member';
|
100 |
+
$prefix .= ".$locationName";
|
101 |
+
} elseif ($name = $this->queryName($items)) {
|
102 |
+
$parts = explode('.', $prefix);
|
103 |
+
$parts[count($parts) - 1] = $name;
|
104 |
+
$prefix = implode('.', $parts);
|
105 |
+
}
|
106 |
+
|
107 |
+
foreach ($value as $k => $v) {
|
108 |
+
$this->format($items, $v, $prefix . '.' . ($k + 1), $query);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
protected function format_map(
|
113 |
+
MapShape $shape,
|
114 |
+
array $value,
|
115 |
+
$prefix,
|
116 |
+
array &$query
|
117 |
+
) {
|
118 |
+
$vals = $shape->getValue();
|
119 |
+
$keys = $shape->getKey();
|
120 |
+
|
121 |
+
if (!$this->isFlat($shape)) {
|
122 |
+
$prefix .= '.entry';
|
123 |
+
}
|
124 |
+
|
125 |
+
$i = 0;
|
126 |
+
$keyName = '%s.%d.' . $this->queryName($keys, 'key');
|
127 |
+
$valueName = '%s.%s.' . $this->queryName($vals, 'value');
|
128 |
+
|
129 |
+
foreach ($value as $k => $v) {
|
130 |
+
$i++;
|
131 |
+
$this->format($keys, $k, sprintf($keyName, $prefix, $i), $query);
|
132 |
+
$this->format($vals, $v, sprintf($valueName, $prefix, $i), $query);
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
protected function format_blob(Shape $shape, $value, $prefix, array &$query)
|
137 |
+
{
|
138 |
+
$query[$prefix] = base64_encode($value);
|
139 |
+
}
|
140 |
+
|
141 |
+
protected function format_timestamp(
|
142 |
+
TimestampShape $shape,
|
143 |
+
$value,
|
144 |
+
$prefix,
|
145 |
+
array &$query
|
146 |
+
) {
|
147 |
+
$query[$prefix] = TimestampShape::format($value, 'iso8601');
|
148 |
+
}
|
149 |
+
|
150 |
+
protected function format_boolean(Shape $shape, $value, $prefix, array &$query)
|
151 |
+
{
|
152 |
+
$query[$prefix] = ($value) ? 'true' : 'false';
|
153 |
+
}
|
154 |
+
}
|
includes/aws/Aws/Api/Serializer/QuerySerializer.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use GuzzleHttp\Psr7\Request;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Serializes a query protocol request.
|
11 |
+
* @internal
|
12 |
+
*/
|
13 |
+
class QuerySerializer
|
14 |
+
{
|
15 |
+
private $endpoint;
|
16 |
+
private $api;
|
17 |
+
private $paramBuilder;
|
18 |
+
|
19 |
+
public function __construct(
|
20 |
+
Service $api,
|
21 |
+
$endpoint,
|
22 |
+
callable $paramBuilder = null
|
23 |
+
) {
|
24 |
+
$this->api = $api;
|
25 |
+
$this->endpoint = $endpoint;
|
26 |
+
$this->paramBuilder = $paramBuilder ?: new QueryParamBuilder();
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* When invoked with an AWS command, returns a serialization array
|
31 |
+
* containing "method", "uri", "headers", and "body" key value pairs.
|
32 |
+
*
|
33 |
+
* @param CommandInterface $command
|
34 |
+
*
|
35 |
+
* @return RequestInterface
|
36 |
+
*/
|
37 |
+
public function __invoke(CommandInterface $command)
|
38 |
+
{
|
39 |
+
$operation = $this->api->getOperation($command->getName());
|
40 |
+
|
41 |
+
$body = [
|
42 |
+
'Action' => $command->getName(),
|
43 |
+
'Version' => $this->api->getMetadata('apiVersion')
|
44 |
+
];
|
45 |
+
|
46 |
+
$params = $command->toArray();
|
47 |
+
|
48 |
+
// Only build up the parameters when there are parameters to build
|
49 |
+
if ($params) {
|
50 |
+
$body += call_user_func(
|
51 |
+
$this->paramBuilder,
|
52 |
+
$operation->getInput(),
|
53 |
+
$params
|
54 |
+
);
|
55 |
+
}
|
56 |
+
|
57 |
+
$body = http_build_query($body, null, '&', PHP_QUERY_RFC3986);
|
58 |
+
|
59 |
+
return new Request(
|
60 |
+
'POST',
|
61 |
+
$this->endpoint,
|
62 |
+
[
|
63 |
+
'Content-Length' => strlen($body),
|
64 |
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
65 |
+
],
|
66 |
+
$body
|
67 |
+
);
|
68 |
+
}
|
69 |
+
}
|
includes/aws/Aws/Api/Serializer/RestJsonSerializer.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Api\StructureShape;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Serializes requests for the REST-JSON protocol.
|
9 |
+
* @internal
|
10 |
+
*/
|
11 |
+
class RestJsonSerializer extends RestSerializer
|
12 |
+
{
|
13 |
+
/** @var JsonBody */
|
14 |
+
private $jsonFormatter;
|
15 |
+
|
16 |
+
/** @var string */
|
17 |
+
private $contentType;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param Service $api Service API description
|
21 |
+
* @param string $endpoint Endpoint to connect to
|
22 |
+
* @param JsonBody $jsonFormatter Optional JSON formatter to use
|
23 |
+
*/
|
24 |
+
public function __construct(
|
25 |
+
Service $api,
|
26 |
+
$endpoint,
|
27 |
+
JsonBody $jsonFormatter = null
|
28 |
+
) {
|
29 |
+
parent::__construct($api, $endpoint);
|
30 |
+
$this->contentType = JsonBody::getContentType($api);
|
31 |
+
$this->jsonFormatter = $jsonFormatter ?: new JsonBody($api);
|
32 |
+
}
|
33 |
+
|
34 |
+
protected function payload(StructureShape $member, array $value, array &$opts)
|
35 |
+
{
|
36 |
+
$opts['headers']['Content-Type'] = $this->contentType;
|
37 |
+
$opts['body'] = (string) $this->jsonFormatter->build($member, $value);
|
38 |
+
}
|
39 |
+
}
|
includes/aws/Aws/Api/Serializer/RestSerializer.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\MapShape;
|
5 |
+
use Aws\Api\Service;
|
6 |
+
use Aws\Api\Operation;
|
7 |
+
use Aws\Api\Shape;
|
8 |
+
use Aws\Api\StructureShape;
|
9 |
+
use Aws\Api\TimestampShape;
|
10 |
+
use Aws\CommandInterface;
|
11 |
+
use GuzzleHttp\Psr7;
|
12 |
+
use Psr\Http\Message\RequestInterface;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Serializes HTTP locations like header, uri, payload, etc...
|
16 |
+
* @internal
|
17 |
+
*/
|
18 |
+
abstract class RestSerializer
|
19 |
+
{
|
20 |
+
/** @var Service */
|
21 |
+
private $api;
|
22 |
+
|
23 |
+
/** @var Psr7\Uri */
|
24 |
+
private $endpoint;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @param Service $api Service API description
|
28 |
+
* @param string $endpoint Endpoint to connect to
|
29 |
+
*/
|
30 |
+
public function __construct(Service $api, $endpoint)
|
31 |
+
{
|
32 |
+
$this->api = $api;
|
33 |
+
$this->endpoint = Psr7\uri_for($endpoint);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @param CommandInterface $command Command to serialized
|
38 |
+
*
|
39 |
+
* @return RequestInterface
|
40 |
+
*/
|
41 |
+
public function __invoke(CommandInterface $command)
|
42 |
+
{
|
43 |
+
$operation = $this->api->getOperation($command->getName());
|
44 |
+
$args = $command->toArray();
|
45 |
+
$opts = $this->serialize($operation, $args);
|
46 |
+
$uri = $this->buildEndpoint($operation, $args, $opts);
|
47 |
+
|
48 |
+
return new Psr7\Request(
|
49 |
+
$operation['http']['method'],
|
50 |
+
$uri,
|
51 |
+
isset($opts['headers']) ? $opts['headers'] : [],
|
52 |
+
isset($opts['body']) ? $opts['body'] : null
|
53 |
+
);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Modifies a hash of request options for a payload body.
|
58 |
+
*
|
59 |
+
* @param StructureShape $member Member to serialize
|
60 |
+
* @param array $value Value to serialize
|
61 |
+
* @param array $opts Request options to modify.
|
62 |
+
*/
|
63 |
+
abstract protected function payload(
|
64 |
+
StructureShape $member,
|
65 |
+
array $value,
|
66 |
+
array &$opts
|
67 |
+
);
|
68 |
+
|
69 |
+
private function serialize(Operation $operation, array $args)
|
70 |
+
{
|
71 |
+
$opts = [];
|
72 |
+
$input = $operation->getInput();
|
73 |
+
|
74 |
+
// Apply the payload trait if present
|
75 |
+
if ($payload = $input['payload']) {
|
76 |
+
$this->applyPayload($input, $payload, $args, $opts);
|
77 |
+
}
|
78 |
+
|
79 |
+
foreach ($args as $name => $value) {
|
80 |
+
if ($input->hasMember($name)) {
|
81 |
+
$member = $input->getMember($name);
|
82 |
+
$location = $member['location'];
|
83 |
+
if (!$payload && !$location) {
|
84 |
+
$bodyMembers[$name] = $value;
|
85 |
+
} elseif ($location == 'header') {
|
86 |
+
$this->applyHeader($name, $member, $value, $opts);
|
87 |
+
} elseif ($location == 'querystring') {
|
88 |
+
$this->applyQuery($name, $member, $value, $opts);
|
89 |
+
} elseif ($location == 'headers') {
|
90 |
+
$this->applyHeaderMap($name, $member, $value, $opts);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
if (isset($bodyMembers)) {
|
96 |
+
$this->payload($operation->getInput(), $bodyMembers, $opts);
|
97 |
+
}
|
98 |
+
|
99 |
+
return $opts;
|
100 |
+
}
|
101 |
+
|
102 |
+
private function applyPayload(StructureShape $input, $name, array $args, array &$opts)
|
103 |
+
{
|
104 |
+
if (!isset($args[$name])) {
|
105 |
+
return;
|
106 |
+
}
|
107 |
+
|
108 |
+
$m = $input->getMember($name);
|
109 |
+
|
110 |
+
if ($m['streaming'] ||
|
111 |
+
($m['type'] == 'string' || $m['type'] == 'blob')
|
112 |
+
) {
|
113 |
+
// Streaming bodies or payloads that are strings are
|
114 |
+
// always just a stream of data.
|
115 |
+
$opts['body'] = Psr7\stream_for($args[$name]);
|
116 |
+
return;
|
117 |
+
}
|
118 |
+
|
119 |
+
$this->payload($m, $args[$name], $opts);
|
120 |
+
}
|
121 |
+
|
122 |
+
private function applyHeader($name, Shape $member, $value, array &$opts)
|
123 |
+
{
|
124 |
+
if ($member->getType() == 'timestamp') {
|
125 |
+
$value = TimestampShape::format($value, 'rfc822');
|
126 |
+
}
|
127 |
+
|
128 |
+
$opts['headers'][$member['locationName'] ?: $name] = $value;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Note: This is currently only present in the Amazon S3 model.
|
133 |
+
*/
|
134 |
+
private function applyHeaderMap($name, Shape $member, array $value, array &$opts)
|
135 |
+
{
|
136 |
+
$prefix = $member['locationName'];
|
137 |
+
foreach ($value as $k => $v) {
|
138 |
+
$opts['headers'][$prefix . $k] = $v;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
private function applyQuery($name, Shape $member, $value, array &$opts)
|
143 |
+
{
|
144 |
+
if ($member instanceof MapShape) {
|
145 |
+
$opts['query'] = isset($opts['query']) && is_array($opts['query'])
|
146 |
+
? $opts['query'] + $value
|
147 |
+
: $value;
|
148 |
+
} elseif ($value !== null) {
|
149 |
+
$opts['query'][$member['locationName'] ?: $name] = $value;
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
private function buildEndpoint(Operation $operation, array $args, array $opts)
|
154 |
+
{
|
155 |
+
$varspecs = [];
|
156 |
+
|
157 |
+
// Create an associative array of varspecs used in expansions
|
158 |
+
foreach ($operation->getInput()->getMembers() as $name => $member) {
|
159 |
+
if ($member['location'] == 'uri') {
|
160 |
+
$varspecs[$member['locationName'] ?: $name] =
|
161 |
+
isset($args[$name])
|
162 |
+
? $args[$name]
|
163 |
+
: null;
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
$relative = preg_replace_callback(
|
168 |
+
'/\{([^\}]+)\}/',
|
169 |
+
function (array $matches) use ($varspecs) {
|
170 |
+
$isGreedy = substr($matches[1], -1, 1) == '+';
|
171 |
+
$k = $isGreedy ? substr($matches[1], 0, -1) : $matches[1];
|
172 |
+
if (!isset($varspecs[$k])) {
|
173 |
+
return '';
|
174 |
+
} elseif ($isGreedy) {
|
175 |
+
return str_replace('%2F', '/', rawurlencode($varspecs[$k]));
|
176 |
+
} else {
|
177 |
+
return rawurlencode($varspecs[$k]);
|
178 |
+
}
|
179 |
+
},
|
180 |
+
$operation['http']['requestUri']
|
181 |
+
);
|
182 |
+
|
183 |
+
// Add the query string variables or appending to one if needed.
|
184 |
+
if (!empty($opts['query'])) {
|
185 |
+
$append = Psr7\build_query($opts['query']);
|
186 |
+
$relative .= strpos($relative, '?') ? "&{$append}" : "?$append";
|
187 |
+
}
|
188 |
+
|
189 |
+
// Expand path place holders using Amazon's slightly different URI
|
190 |
+
// template syntax.
|
191 |
+
return Psr7\Uri::resolve($this->endpoint, $relative);
|
192 |
+
}
|
193 |
+
}
|
includes/aws/Aws/Api/Serializer/RestXmlSerializer.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\StructureShape;
|
5 |
+
use Aws\Api\Service;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class RestXmlSerializer extends RestSerializer
|
11 |
+
{
|
12 |
+
/** @var XmlBody */
|
13 |
+
private $xmlBody;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param Service $api Service API description
|
17 |
+
* @param string $endpoint Endpoint to connect to
|
18 |
+
* @param XmlBody $xmlBody Optional XML formatter to use
|
19 |
+
*/
|
20 |
+
public function __construct(
|
21 |
+
Service $api,
|
22 |
+
$endpoint,
|
23 |
+
XmlBody $xmlBody = null
|
24 |
+
) {
|
25 |
+
parent::__construct($api, $endpoint);
|
26 |
+
$this->xmlBody = $xmlBody ?: new XmlBody($api);
|
27 |
+
}
|
28 |
+
|
29 |
+
protected function payload(StructureShape $member, array $value, array &$opts)
|
30 |
+
{
|
31 |
+
$opts['headers']['Content-Type'] = 'application/xml';
|
32 |
+
$opts['body'] = (string) $this->xmlBody->build($member, $value);
|
33 |
+
}
|
34 |
+
}
|
includes/aws/Aws/Api/Serializer/XmlBody.php
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api\Serializer;
|
3 |
+
|
4 |
+
use Aws\Api\MapShape;
|
5 |
+
use Aws\Api\Service;
|
6 |
+
use Aws\Api\Shape;
|
7 |
+
use Aws\Api\StructureShape;
|
8 |
+
use Aws\Api\ListShape;
|
9 |
+
use Aws\Api\TimestampShape;
|
10 |
+
use XMLWriter;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @internal Formats the XML body of a REST-XML services.
|
14 |
+
*/
|
15 |
+
class XmlBody
|
16 |
+
{
|
17 |
+
/** @var \Aws\Api\Service */
|
18 |
+
private $api;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param Service $api API being used to create the XML body.
|
22 |
+
*/
|
23 |
+
public function __construct(Service $api)
|
24 |
+
{
|
25 |
+
$this->api = $api;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Builds the XML body based on an array of arguments.
|
30 |
+
*
|
31 |
+
* @param Shape $shape Operation being constructed
|
32 |
+
* @param array $args Associative array of arguments
|
33 |
+
*
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
+
public function build(Shape $shape, array $args)
|
37 |
+
{
|
38 |
+
$xml = new XMLWriter();
|
39 |
+
$xml->openMemory();
|
40 |
+
$xml->startDocument('1.0', 'UTF-8');
|
41 |
+
$this->format($shape, $shape['locationName'], $args, $xml);
|
42 |
+
$xml->endDocument();
|
43 |
+
|
44 |
+
return $xml->outputMemory();
|
45 |
+
}
|
46 |
+
|
47 |
+
private function startElement(Shape $shape, $name, XMLWriter $xml)
|
48 |
+
{
|
49 |
+
$xml->startElement($name);
|
50 |
+
|
51 |
+
if ($ns = $shape['xmlNamespace']) {
|
52 |
+
$xml->writeAttribute(
|
53 |
+
isset($ns['prefix']) ? "xmlns:{$ns['prefix']}" : 'xmlns',
|
54 |
+
$shape['xmlNamespace']['uri']
|
55 |
+
);
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
private function format(Shape $shape, $name, $value, XMLWriter $xml)
|
60 |
+
{
|
61 |
+
// Any method mentioned here has a custom serialization handler.
|
62 |
+
static $methods = [
|
63 |
+
'add_structure' => true,
|
64 |
+
'add_list' => true,
|
65 |
+
'add_blob' => true,
|
66 |
+
'add_timestamp' => true,
|
67 |
+
'add_boolean' => true,
|
68 |
+
'add_map' => true,
|
69 |
+
'add_string' => true
|
70 |
+
];
|
71 |
+
|
72 |
+
$type = 'add_' . $shape['type'];
|
73 |
+
if (isset($methods[$type])) {
|
74 |
+
$this->{$type}($shape, $name, $value, $xml);
|
75 |
+
} else {
|
76 |
+
$this->defaultShape($shape, $name, $value, $xml);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
private function defaultShape(Shape $shape, $name, $value, XMLWriter $xml)
|
81 |
+
{
|
82 |
+
$this->startElement($shape, $name, $xml);
|
83 |
+
$xml->writeRaw($value);
|
84 |
+
$xml->endElement();
|
85 |
+
}
|
86 |
+
|
87 |
+
private function add_structure(
|
88 |
+
StructureShape $shape,
|
89 |
+
$name,
|
90 |
+
array $value,
|
91 |
+
\XMLWriter $xml
|
92 |
+
) {
|
93 |
+
$this->startElement($shape, $name, $xml);
|
94 |
+
|
95 |
+
foreach ($this->getStructureMembers($shape, $value) as $k => $definition) {
|
96 |
+
$this->format(
|
97 |
+
$definition['member'],
|
98 |
+
$definition['member']['locationName'] ?: $k,
|
99 |
+
$definition['value'],
|
100 |
+
$xml
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
$xml->endElement();
|
105 |
+
}
|
106 |
+
|
107 |
+
private function getStructureMembers(StructureShape $shape, array $value)
|
108 |
+
{
|
109 |
+
$members = [];
|
110 |
+
|
111 |
+
foreach ($value as $k => $v) {
|
112 |
+
if ($v !== null && $shape->hasMember($k)) {
|
113 |
+
$definition = [
|
114 |
+
'member' => $shape->getMember($k),
|
115 |
+
'value' => $v,
|
116 |
+
];
|
117 |
+
|
118 |
+
if ($definition['member']['xmlAttribute']) {
|
119 |
+
// array_unshift_associative
|
120 |
+
$members = [$k => $definition] + $members;
|
121 |
+
} else {
|
122 |
+
$members[$k] = $definition;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
return $members;
|
128 |
+
}
|
129 |
+
|
130 |
+
private function add_list(
|
131 |
+
ListShape $shape,
|
132 |
+
$name,
|
133 |
+
array $value,
|
134 |
+
XMLWriter $xml
|
135 |
+
) {
|
136 |
+
$items = $shape->getMember();
|
137 |
+
|
138 |
+
if ($shape['flattened']) {
|
139 |
+
$elementName = $name;
|
140 |
+
} else {
|
141 |
+
$this->startElement($shape, $name, $xml);
|
142 |
+
$elementName = $items['locationName'] ?: 'member';
|
143 |
+
}
|
144 |
+
|
145 |
+
foreach ($value as &$v) {
|
146 |
+
$this->format($items, $elementName, $v, $xml);
|
147 |
+
}
|
148 |
+
|
149 |
+
if (!$shape['flattened']) {
|
150 |
+
$xml->endElement();
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
private function add_map(
|
155 |
+
MapShape $shape,
|
156 |
+
$name,
|
157 |
+
array $value,
|
158 |
+
XMLWriter $xml
|
159 |
+
) {
|
160 |
+
$xmlEntry = $shape['flattened'] ? $shape['locationName'] : 'entry';
|
161 |
+
$xmlKey = $shape->getKey()['locationName'] ?: 'key';
|
162 |
+
$xmlValue = $shape->getValue()['locationName'] ?: 'value';
|
163 |
+
|
164 |
+
$this->startElement($shape, $name, $xml);
|
165 |
+
|
166 |
+
foreach ($value as $key => $v) {
|
167 |
+
$this->startElement($shape, $xmlEntry, $xml);
|
168 |
+
$this->format($shape->getKey(), $xmlKey, $key, $xml);
|
169 |
+
$this->format($shape->getValue(), $xmlValue, $v, $xml);
|
170 |
+
$xml->endElement();
|
171 |
+
}
|
172 |
+
|
173 |
+
$xml->endElement();
|
174 |
+
}
|
175 |
+
|
176 |
+
private function add_blob(Shape $shape, $name, $value, XMLWriter $xml)
|
177 |
+
{
|
178 |
+
$this->startElement($shape, $name, $xml);
|
179 |
+
$xml->writeRaw(base64_encode($value));
|
180 |
+
$xml->endElement();
|
181 |
+
}
|
182 |
+
|
183 |
+
private function add_timestamp(
|
184 |
+
TimestampShape $shape,
|
185 |
+
$name,
|
186 |
+
$value,
|
187 |
+
XMLWriter $xml
|
188 |
+
) {
|
189 |
+
$this->startElement($shape, $name, $xml);
|
190 |
+
$xml->writeRaw(TimestampShape::format($value, 'iso8601'));
|
191 |
+
$xml->endElement();
|
192 |
+
}
|
193 |
+
|
194 |
+
private function add_boolean(
|
195 |
+
Shape $shape,
|
196 |
+
$name,
|
197 |
+
$value,
|
198 |
+
XMLWriter $xml
|
199 |
+
) {
|
200 |
+
$this->startElement($shape, $name, $xml);
|
201 |
+
$xml->writeRaw($value ? 'true' : 'false');
|
202 |
+
$xml->endElement();
|
203 |
+
}
|
204 |
+
|
205 |
+
private function add_string(
|
206 |
+
Shape $shape,
|
207 |
+
$name,
|
208 |
+
$value,
|
209 |
+
XMLWriter $xml
|
210 |
+
) {
|
211 |
+
if ($shape['xmlAttribute']) {
|
212 |
+
$xml->writeAttribute($shape['locationName'] ?: $name, $value);
|
213 |
+
} else {
|
214 |
+
$this->defaultShape($shape, $name, $value, $xml);
|
215 |
+
}
|
216 |
+
}
|
217 |
+
}
|
includes/aws/Aws/Api/Service.php
ADDED
@@ -0,0 +1,404 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
use Aws\Api\Serializer\QuerySerializer;
|
5 |
+
use Aws\Api\Serializer\Ec2ParamBuilder;
|
6 |
+
use Aws\Api\Parser\QueryParser;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Represents a web service API model.
|
10 |
+
*/
|
11 |
+
class Service extends AbstractModel
|
12 |
+
{
|
13 |
+
/** @var callable */
|
14 |
+
private $apiProvider;
|
15 |
+
|
16 |
+
/** @var string */
|
17 |
+
private $serviceName;
|
18 |
+
|
19 |
+
/** @var string */
|
20 |
+
private $apiVersion;
|
21 |
+
|
22 |
+
/** @var Operation[] */
|
23 |
+
private $operations = [];
|
24 |
+
|
25 |
+
/** @var array */
|
26 |
+
private $paginators = null;
|
27 |
+
|
28 |
+
/** @var array */
|
29 |
+
private $waiters = null;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param array $definition
|
33 |
+
* @param callable $provider
|
34 |
+
*
|
35 |
+
* @internal param array $definition Service description
|
36 |
+
*/
|
37 |
+
public function __construct(array $definition, callable $provider)
|
38 |
+
{
|
39 |
+
static $defaults = [
|
40 |
+
'operations' => [],
|
41 |
+
'shapes' => [],
|
42 |
+
'metadata' => []
|
43 |
+
], $defaultMeta = [
|
44 |
+
'apiVersion' => null,
|
45 |
+
'serviceFullName' => null,
|
46 |
+
'endpointPrefix' => null,
|
47 |
+
'signingName' => null,
|
48 |
+
'signatureVersion' => null,
|
49 |
+
'protocol' => null
|
50 |
+
];
|
51 |
+
|
52 |
+
$definition += $defaults;
|
53 |
+
$definition['metadata'] += $defaultMeta;
|
54 |
+
$this->definition = $definition;
|
55 |
+
$this->apiProvider = $provider;
|
56 |
+
parent::__construct($definition, new ShapeMap($definition['shapes']));
|
57 |
+
$this->serviceName = $this->getEndpointPrefix();
|
58 |
+
$this->apiVersion = $this->getApiVersion();
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Creates a request serializer for the provided API object.
|
63 |
+
*
|
64 |
+
* @param Service $api API that contains a protocol.
|
65 |
+
* @param string $endpoint Endpoint to send requests to.
|
66 |
+
*
|
67 |
+
* @return callable
|
68 |
+
* @throws \UnexpectedValueException
|
69 |
+
*/
|
70 |
+
public static function createSerializer(Service $api, $endpoint)
|
71 |
+
{
|
72 |
+
static $mapping = [
|
73 |
+
'json' => 'Aws\Api\Serializer\JsonRpcSerializer',
|
74 |
+
'query' => 'Aws\Api\Serializer\QuerySerializer',
|
75 |
+
'rest-json' => 'Aws\Api\Serializer\RestJsonSerializer',
|
76 |
+
'rest-xml' => 'Aws\Api\Serializer\RestXmlSerializer'
|
77 |
+
];
|
78 |
+
|
79 |
+
$proto = $api->getProtocol();
|
80 |
+
|
81 |
+
if (isset($mapping[$proto])) {
|
82 |
+
return new $mapping[$proto]($api, $endpoint);
|
83 |
+
} elseif ($proto == 'ec2') {
|
84 |
+
return new QuerySerializer($api, $endpoint, new Ec2ParamBuilder());
|
85 |
+
}
|
86 |
+
|
87 |
+
throw new \UnexpectedValueException(
|
88 |
+
'Unknown protocol: ' . $api->getProtocol()
|
89 |
+
);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Creates an error parser for the given protocol.
|
94 |
+
*
|
95 |
+
* @param string $protocol Protocol to parse (e.g., query, json, etc.)
|
96 |
+
*
|
97 |
+
* @return callable
|
98 |
+
* @throws \UnexpectedValueException
|
99 |
+
*/
|
100 |
+
public static function createErrorParser($protocol)
|
101 |
+
{
|
102 |
+
static $mapping = [
|
103 |
+
'json' => 'Aws\Api\ErrorParser\JsonRpcErrorParser',
|
104 |
+
'query' => 'Aws\Api\ErrorParser\XmlErrorParser',
|
105 |
+
'rest-json' => 'Aws\Api\ErrorParser\RestJsonErrorParser',
|
106 |
+
'rest-xml' => 'Aws\Api\ErrorParser\XmlErrorParser',
|
107 |
+
'ec2' => 'Aws\Api\ErrorParser\XmlErrorParser'
|
108 |
+
];
|
109 |
+
|
110 |
+
if (isset($mapping[$protocol])) {
|
111 |
+
return new $mapping[$protocol]();
|
112 |
+
}
|
113 |
+
|
114 |
+
throw new \UnexpectedValueException("Unknown protocol: $protocol");
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Applies the listeners needed to parse client models.
|
119 |
+
*
|
120 |
+
* @param Service $api API to create a parser for
|
121 |
+
* @return callable
|
122 |
+
* @throws \UnexpectedValueException
|
123 |
+
*/
|
124 |
+
public static function createParser(Service $api)
|
125 |
+
{
|
126 |
+
static $mapping = [
|
127 |
+
'json' => 'Aws\Api\Parser\JsonRpcParser',
|
128 |
+
'query' => 'Aws\Api\Parser\QueryParser',
|
129 |
+
'rest-json' => 'Aws\Api\Parser\RestJsonParser',
|
130 |
+
'rest-xml' => 'Aws\Api\Parser\RestXmlParser'
|
131 |
+
];
|
132 |
+
|
133 |
+
$proto = $api->getProtocol();
|
134 |
+
if (isset($mapping[$proto])) {
|
135 |
+
return new $mapping[$proto]($api);
|
136 |
+
} elseif ($proto == 'ec2') {
|
137 |
+
return new QueryParser($api, null, false);
|
138 |
+
}
|
139 |
+
|
140 |
+
throw new \UnexpectedValueException(
|
141 |
+
'Unknown protocol: ' . $api->getProtocol()
|
142 |
+
);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Get the full name of the service
|
147 |
+
*
|
148 |
+
* @return string
|
149 |
+
*/
|
150 |
+
public function getServiceFullName()
|
151 |
+
{
|
152 |
+
return $this->definition['metadata']['serviceFullName'];
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Get the API version of the service
|
157 |
+
*
|
158 |
+
* @return string
|
159 |
+
*/
|
160 |
+
public function getApiVersion()
|
161 |
+
{
|
162 |
+
return $this->definition['metadata']['apiVersion'];
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Get the API version of the service
|
167 |
+
*
|
168 |
+
* @return string
|
169 |
+
*/
|
170 |
+
public function getEndpointPrefix()
|
171 |
+
{
|
172 |
+
return $this->definition['metadata']['endpointPrefix'];
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Get the signing name used by the service.
|
177 |
+
*
|
178 |
+
* @return string
|
179 |
+
*/
|
180 |
+
public function getSigningName()
|
181 |
+
{
|
182 |
+
return $this->definition['metadata']['signingName']
|
183 |
+
?: $this->definition['metadata']['endpointPrefix'];
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Get the default signature version of the service.
|
188 |
+
*
|
189 |
+
* Note: this method assumes "v4" when not specified in the model.
|
190 |
+
*
|
191 |
+
* @return string
|
192 |
+
*/
|
193 |
+
public function getSignatureVersion()
|
194 |
+
{
|
195 |
+
return $this->definition['metadata']['signatureVersion'] ?: 'v4';
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Get the protocol used by the service.
|
200 |
+
*
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
+
public function getProtocol()
|
204 |
+
{
|
205 |
+
return $this->definition['metadata']['protocol'];
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Check if the description has a specific operation by name.
|
210 |
+
*
|
211 |
+
* @param string $name Operation to check by name
|
212 |
+
*
|
213 |
+
* @return bool
|
214 |
+
*/
|
215 |
+
public function hasOperation($name)
|
216 |
+
{
|
217 |
+
return isset($this['operations'][$name]);
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Get an operation by name.
|
222 |
+
*
|
223 |
+
* @param string $name Operation to retrieve by name
|
224 |
+
*
|
225 |
+
* @return Operation
|
226 |
+
* @throws \InvalidArgumentException If the operation is not found
|
227 |
+
*/
|
228 |
+
public function getOperation($name)
|
229 |
+
{
|
230 |
+
if (!isset($this->operations[$name])) {
|
231 |
+
if (!isset($this->definition['operations'][$name])) {
|
232 |
+
throw new \InvalidArgumentException("Unknown operation: $name");
|
233 |
+
}
|
234 |
+
$this->operations[$name] = new Operation(
|
235 |
+
$this->definition['operations'][$name],
|
236 |
+
$this->shapeMap
|
237 |
+
);
|
238 |
+
}
|
239 |
+
|
240 |
+
return $this->operations[$name];
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Get all of the operations of the description.
|
245 |
+
*
|
246 |
+
* @return Operation[]
|
247 |
+
*/
|
248 |
+
public function getOperations()
|
249 |
+
{
|
250 |
+
$result = [];
|
251 |
+
foreach ($this->definition['operations'] as $name => $definition) {
|
252 |
+
$result[$name] = $this->getOperation($name);
|
253 |
+
}
|
254 |
+
|
255 |
+
return $result;
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Get all of the service metadata or a specific metadata key value.
|
260 |
+
*
|
261 |
+
* @param string|null $key Key to retrieve or null to retrieve all metadata
|
262 |
+
*
|
263 |
+
* @return mixed Returns the result or null if the key is not found
|
264 |
+
*/
|
265 |
+
public function getMetadata($key = null)
|
266 |
+
{
|
267 |
+
if (!$key) {
|
268 |
+
return $this['metadata'];
|
269 |
+
} elseif (isset($this->definition['metadata'][$key])) {
|
270 |
+
return $this->definition['metadata'][$key];
|
271 |
+
}
|
272 |
+
|
273 |
+
return null;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Gets an associative array of available paginator configurations where
|
278 |
+
* the key is the name of the paginator, and the value is the paginator
|
279 |
+
* configuration.
|
280 |
+
*
|
281 |
+
* @return array
|
282 |
+
* @unstable The configuration format of paginators may change in the future
|
283 |
+
*/
|
284 |
+
public function getPaginators()
|
285 |
+
{
|
286 |
+
if (!isset($this->paginators)) {
|
287 |
+
$res = call_user_func(
|
288 |
+
$this->apiProvider,
|
289 |
+
'paginator',
|
290 |
+
$this->serviceName,
|
291 |
+
$this->apiVersion
|
292 |
+
);
|
293 |
+
$this->paginators = isset($res['pagination'])
|
294 |
+
? $res['pagination']
|
295 |
+
: [];
|
296 |
+
}
|
297 |
+
|
298 |
+
return $this->paginators;
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Determines if the service has a paginator by name.
|
303 |
+
*
|
304 |
+
* @param string $name Name of the paginator.
|
305 |
+
*
|
306 |
+
* @return bool
|
307 |
+
*/
|
308 |
+
public function hasPaginator($name)
|
309 |
+
{
|
310 |
+
return isset($this->getPaginators()[$name]);
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Retrieve a paginator by name.
|
315 |
+
*
|
316 |
+
* @param string $name Paginator to retrieve by name. This argument is
|
317 |
+
* typically the operation name.
|
318 |
+
* @return array
|
319 |
+
* @throws \UnexpectedValueException if the paginator does not exist.
|
320 |
+
* @unstable The configuration format of paginators may change in the future
|
321 |
+
*/
|
322 |
+
public function getPaginatorConfig($name)
|
323 |
+
{
|
324 |
+
static $defaults = [
|
325 |
+
'input_token' => null,
|
326 |
+
'output_token' => null,
|
327 |
+
'limit_key' => null,
|
328 |
+
'result_key' => null,
|
329 |
+
'more_results' => null,
|
330 |
+
];
|
331 |
+
|
332 |
+
if ($this->hasPaginator($name)) {
|
333 |
+
return $this->paginators[$name] + $defaults;
|
334 |
+
}
|
335 |
+
|
336 |
+
throw new \UnexpectedValueException("There is no {$name} "
|
337 |
+
. "paginator defined for the {$this->serviceName} service.");
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Gets an associative array of available waiter configurations where the
|
342 |
+
* key is the name of the waiter, and the value is the waiter
|
343 |
+
* configuration.
|
344 |
+
*
|
345 |
+
* @return array
|
346 |
+
*/
|
347 |
+
public function getWaiters()
|
348 |
+
{
|
349 |
+
if (!isset($this->waiters)) {
|
350 |
+
$res = call_user_func(
|
351 |
+
$this->apiProvider,
|
352 |
+
'waiter',
|
353 |
+
$this->serviceName,
|
354 |
+
$this->apiVersion
|
355 |
+
);
|
356 |
+
$this->waiters = isset($res['waiters'])
|
357 |
+
? $res['waiters']
|
358 |
+
: [];
|
359 |
+
}
|
360 |
+
|
361 |
+
return $this->waiters;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Determines if the service has a waiter by name.
|
366 |
+
*
|
367 |
+
* @param string $name Name of the waiter.
|
368 |
+
*
|
369 |
+
* @return bool
|
370 |
+
*/
|
371 |
+
public function hasWaiter($name)
|
372 |
+
{
|
373 |
+
return isset($this->getWaiters()[$name]);
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Get a waiter configuration by name.
|
378 |
+
*
|
379 |
+
* @param string $name Name of the waiter by name.
|
380 |
+
*
|
381 |
+
* @return array
|
382 |
+
* @throws \UnexpectedValueException if the waiter does not exist.
|
383 |
+
*/
|
384 |
+
public function getWaiterConfig($name)
|
385 |
+
{
|
386 |
+
// Error if the waiter is not defined
|
387 |
+
if ($this->hasWaiter($name)) {
|
388 |
+
return $this->waiters[$name];
|
389 |
+
}
|
390 |
+
|
391 |
+
throw new \UnexpectedValueException("There is no {$name} waiter "
|
392 |
+
. "defined for the {$this->serviceName} service.");
|
393 |
+
}
|
394 |
+
|
395 |
+
/**
|
396 |
+
* Get the shape map used by the API.
|
397 |
+
*
|
398 |
+
* @return ShapeMap
|
399 |
+
*/
|
400 |
+
public function getShapeMap()
|
401 |
+
{
|
402 |
+
return $this->shapeMap;
|
403 |
+
}
|
404 |
+
}
|
includes/aws/Aws/Api/Shape.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Base class representing a modeled shape.
|
6 |
+
*/
|
7 |
+
class Shape extends AbstractModel
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Get a concrete shape for the given definition.
|
11 |
+
*
|
12 |
+
* @param array $definition
|
13 |
+
* @param ShapeMap $shapeMap
|
14 |
+
*
|
15 |
+
* @return mixed
|
16 |
+
* @throws \RuntimeException if the type is invalid
|
17 |
+
*/
|
18 |
+
public static function create(array $definition, ShapeMap $shapeMap)
|
19 |
+
{
|
20 |
+
static $map = [
|
21 |
+
'structure' => 'Aws\Api\StructureShape',
|
22 |
+
'map' => 'Aws\Api\MapShape',
|
23 |
+
'list' => 'Aws\Api\ListShape',
|
24 |
+
'timestamp' => 'Aws\Api\TimestampShape',
|
25 |
+
'integer' => 'Aws\Api\Shape',
|
26 |
+
'double' => 'Aws\Api\Shape',
|
27 |
+
'float' => 'Aws\Api\Shape',
|
28 |
+
'long' => 'Aws\Api\Shape',
|
29 |
+
'string' => 'Aws\Api\Shape',
|
30 |
+
'byte' => 'Aws\Api\Shape',
|
31 |
+
'character' => 'Aws\Api\Shape',
|
32 |
+
'blob' => 'Aws\Api\Shape',
|
33 |
+
'boolean' => 'Aws\Api\Shape'
|
34 |
+
];
|
35 |
+
|
36 |
+
if (isset($definition['shape'])) {
|
37 |
+
return $shapeMap->resolve($definition);
|
38 |
+
}
|
39 |
+
|
40 |
+
if (!isset($map[$definition['type']])) {
|
41 |
+
throw new \RuntimeException('Invalid type: '
|
42 |
+
. print_r($definition, true));
|
43 |
+
}
|
44 |
+
|
45 |
+
$type = $map[$definition['type']];
|
46 |
+
|
47 |
+
return new $type($definition, $shapeMap);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Get the type of the shape
|
52 |
+
*
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
public function getType()
|
56 |
+
{
|
57 |
+
return $this->definition['type'];
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Get the name of the shape
|
62 |
+
*
|
63 |
+
* @return string
|
64 |
+
*/
|
65 |
+
public function getName()
|
66 |
+
{
|
67 |
+
return $this->definition['name'];
|
68 |
+
}
|
69 |
+
}
|
includes/aws/Aws/Api/ShapeMap.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Builds shape based on shape references.
|
6 |
+
*/
|
7 |
+
class ShapeMap
|
8 |
+
{
|
9 |
+
/** @var array */
|
10 |
+
private $definitions;
|
11 |
+
|
12 |
+
/** @var Shape[] */
|
13 |
+
private $simple;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param array $shapeModels Associative array of shape definitions.
|
17 |
+
*/
|
18 |
+
public function __construct(array $shapeModels)
|
19 |
+
{
|
20 |
+
$this->definitions = $shapeModels;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Get an array of shape names.
|
25 |
+
*
|
26 |
+
* @return array
|
27 |
+
*/
|
28 |
+
public function getShapeNames()
|
29 |
+
{
|
30 |
+
return array_keys($this->definitions);
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Resolve a shape reference
|
35 |
+
*
|
36 |
+
* @param array $shapeRef Shape reference shape
|
37 |
+
*
|
38 |
+
* @return Shape
|
39 |
+
* @throws \InvalidArgumentException
|
40 |
+
*/
|
41 |
+
public function resolve(array $shapeRef)
|
42 |
+
{
|
43 |
+
$shape = $shapeRef['shape'];
|
44 |
+
|
45 |
+
if (!isset($this->definitions[$shape])) {
|
46 |
+
throw new \InvalidArgumentException('Shape not found: ' . $shape);
|
47 |
+
}
|
48 |
+
|
49 |
+
$isSimple = count($shapeRef) == 1;
|
50 |
+
if ($isSimple && isset($this->simple[$shape])) {
|
51 |
+
return $this->simple[$shape];
|
52 |
+
}
|
53 |
+
|
54 |
+
$definition = $shapeRef + $this->definitions[$shape];
|
55 |
+
$definition['name'] = $definition['shape'];
|
56 |
+
unset($definition['shape']);
|
57 |
+
|
58 |
+
$result = Shape::create($definition, $this);
|
59 |
+
|
60 |
+
if ($isSimple) {
|
61 |
+
$this->simple[$shape] = $result;
|
62 |
+
}
|
63 |
+
|
64 |
+
return $result;
|
65 |
+
}
|
66 |
+
}
|
includes/aws/Aws/Api/StructureShape.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents a structure shape and resolve member shape references.
|
6 |
+
*/
|
7 |
+
class StructureShape extends Shape
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* @var Shape[]
|
11 |
+
*/
|
12 |
+
private $members;
|
13 |
+
|
14 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
15 |
+
{
|
16 |
+
$definition['type'] = 'structure';
|
17 |
+
|
18 |
+
if (!isset($definition['members'])) {
|
19 |
+
$definition['members'] = [];
|
20 |
+
}
|
21 |
+
|
22 |
+
parent::__construct($definition, $shapeMap);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets a list of all members
|
27 |
+
*
|
28 |
+
* @return Shape[]
|
29 |
+
*/
|
30 |
+
public function getMembers()
|
31 |
+
{
|
32 |
+
if (empty($this->members)) {
|
33 |
+
$this->generateMembersHash();
|
34 |
+
}
|
35 |
+
|
36 |
+
return $this->members;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Check if a specific member exists by name.
|
41 |
+
*
|
42 |
+
* @param string $name Name of the member to check
|
43 |
+
*
|
44 |
+
* @return bool
|
45 |
+
*/
|
46 |
+
public function hasMember($name)
|
47 |
+
{
|
48 |
+
return isset($this->definition['members'][$name]);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Retrieve a member by name.
|
53 |
+
*
|
54 |
+
* @param string $name Name of the member to retrieve
|
55 |
+
*
|
56 |
+
* @return Shape
|
57 |
+
* @throws \InvalidArgumentException if the member is not found.
|
58 |
+
*/
|
59 |
+
public function getMember($name)
|
60 |
+
{
|
61 |
+
$members = $this->getMembers();
|
62 |
+
|
63 |
+
if (!isset($members[$name])) {
|
64 |
+
throw new \InvalidArgumentException('Unknown member ' . $name);
|
65 |
+
}
|
66 |
+
|
67 |
+
return $members[$name];
|
68 |
+
}
|
69 |
+
|
70 |
+
|
71 |
+
private function generateMembersHash()
|
72 |
+
{
|
73 |
+
$this->members = [];
|
74 |
+
|
75 |
+
foreach ($this->definition['members'] as $name => $definition) {
|
76 |
+
$this->members[$name] = $this->shapeFor($definition);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
}
|
includes/aws/Aws/Api/TimestampShape.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents a timestamp shape.
|
6 |
+
*/
|
7 |
+
class TimestampShape extends Shape
|
8 |
+
{
|
9 |
+
public function __construct(array $definition, ShapeMap $shapeMap)
|
10 |
+
{
|
11 |
+
$definition['type'] = 'timestamp';
|
12 |
+
parent::__construct($definition, $shapeMap);
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Formats a timestamp value for a service.
|
17 |
+
*
|
18 |
+
* @param mixed $value Value to format
|
19 |
+
* @param string $format Format used to serialize the value
|
20 |
+
*
|
21 |
+
* @return int|string
|
22 |
+
* @throws \UnexpectedValueException if the format is unknown.
|
23 |
+
* @throws \InvalidArgumentException if the value is an unsupported type.
|
24 |
+
*/
|
25 |
+
public static function format($value, $format)
|
26 |
+
{
|
27 |
+
if ($value instanceof \DateTime) {
|
28 |
+
$value = $value->getTimestamp();
|
29 |
+
} elseif (is_string($value)) {
|
30 |
+
$value = strtotime($value);
|
31 |
+
} elseif (!is_int($value)) {
|
32 |
+
throw new \InvalidArgumentException('Unable to handle the provided'
|
33 |
+
. ' timestamp type: ' . gettype($value));
|
34 |
+
}
|
35 |
+
|
36 |
+
switch ($format) {
|
37 |
+
case 'iso8601':
|
38 |
+
return gmdate('Y-m-d\TH:i:s\Z', $value);
|
39 |
+
case 'rfc822':
|
40 |
+
return gmdate('D, d M Y H:i:s \G\M\T', $value);
|
41 |
+
case 'unixTimestamp':
|
42 |
+
return $value;
|
43 |
+
default:
|
44 |
+
throw new \UnexpectedValueException('Unknown timestamp format: '
|
45 |
+
. $format);
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
includes/aws/Aws/Api/Validator.php
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Api;
|
3 |
+
|
4 |
+
use Aws;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Validates a schema against a hash of input.
|
8 |
+
*/
|
9 |
+
class Validator
|
10 |
+
{
|
11 |
+
private $path = [];
|
12 |
+
private $errors = [];
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Validates the given input against the schema.
|
16 |
+
*
|
17 |
+
* @param string $name Operation name
|
18 |
+
* @param Shape $shape Shape to validate
|
19 |
+
* @param array $input Input to validate
|
20 |
+
*
|
21 |
+
* @throws \InvalidArgumentException if the input is invalid.
|
22 |
+
*/
|
23 |
+
public function validate($name, Shape $shape, array $input)
|
24 |
+
{
|
25 |
+
$this->dispatch($shape, $input);
|
26 |
+
|
27 |
+
if ($this->errors) {
|
28 |
+
$message = sprintf(
|
29 |
+
"Found %d error%s while validating the input provided for the "
|
30 |
+
. "%s operation:\n%s",
|
31 |
+
count($this->errors),
|
32 |
+
count($this->errors) > 1 ? 's' : '',
|
33 |
+
$name,
|
34 |
+
implode("\n", $this->errors)
|
35 |
+
);
|
36 |
+
$this->errors = [];
|
37 |
+
|
38 |
+
throw new \InvalidArgumentException($message);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
private function dispatch(Shape $shape, $value)
|
43 |
+
{
|
44 |
+
static $methods = [
|
45 |
+
'structure' => 'check_structure',
|
46 |
+
'list' => 'check_list',
|
47 |
+
'map' => 'check_map',
|
48 |
+
'blob' => 'check_blob',
|
49 |
+
'boolean' => 'check_boolean',
|
50 |
+
'integer' => 'check_numeric',
|
51 |
+
'float' => 'check_numeric',
|
52 |
+
'long' => 'check_numeric',
|
53 |
+
'string' => 'check_string',
|
54 |
+
'byte' => 'check_string',
|
55 |
+
'char' => 'check_string'
|
56 |
+
];
|
57 |
+
|
58 |
+
$type = $shape->getType();
|
59 |
+
if (isset($methods[$type])) {
|
60 |
+
$this->{$methods[$type]}($shape, $value);
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
private function check_structure(StructureShape $shape, $value)
|
65 |
+
{
|
66 |
+
if (!$this->checkAssociativeArray($value)) {
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
if ($shape['required']) {
|
71 |
+
foreach ($shape['required'] as $req) {
|
72 |
+
if (!isset($value[$req])) {
|
73 |
+
$this->path[] = $req;
|
74 |
+
$this->addError('is missing and is a required parameter');
|
75 |
+
array_pop($this->path);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
foreach ($value as $name => $v) {
|
81 |
+
if ($shape->hasMember($name)) {
|
82 |
+
$this->path[] = $name;
|
83 |
+
$this->dispatch(
|
84 |
+
$shape->getMember($name),
|
85 |
+
isset($value[$name]) ? $value[$name] : null
|
86 |
+
);
|
87 |
+
array_pop($this->path);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
private function check_list(ListShape $shape, $value)
|
93 |
+
{
|
94 |
+
if (!is_array($value)) {
|
95 |
+
$this->addError('must be an array. Found '
|
96 |
+
. Aws\describe_type($value));
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
list($min, $max, $count) = [$shape['min'], $shape['max'], count($value)];
|
101 |
+
|
102 |
+
if ($min && $count < $min) {
|
103 |
+
$this->addError("must have at least $min members."
|
104 |
+
. " Value provided has $count.");
|
105 |
+
}
|
106 |
+
|
107 |
+
if ($max && $count > $max) {
|
108 |
+
$this->addError("must have no more than $max members."
|
109 |
+
. " Value provided has $count.");
|
110 |
+
}
|
111 |
+
|
112 |
+
$items = $shape->getMember();
|
113 |
+
foreach ($value as $index => $v) {
|
114 |
+
$this->path[] = $index;
|
115 |
+
$this->dispatch($items, $v);
|
116 |
+
array_pop($this->path);
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
private function check_map(MapShape $shape, $value)
|
121 |
+
{
|
122 |
+
if (!$this->checkAssociativeArray($value)) {
|
123 |
+
return;
|
124 |
+
}
|
125 |
+
|
126 |
+
$values = $shape->getValue();
|
127 |
+
foreach ($value as $key => $v) {
|
128 |
+
$this->path[] = $key;
|
129 |
+
$this->dispatch($values, $v);
|
130 |
+
array_pop($this->path);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
private function check_blob(Shape $shape, $value)
|
135 |
+
{
|
136 |
+
static $valid = [
|
137 |
+
'string' => true,
|
138 |
+
'integer' => true,
|
139 |
+
'double' => true,
|
140 |
+
'resource' => true
|
141 |
+
];
|
142 |
+
|
143 |
+
$type = gettype($value);
|
144 |
+
if (!isset($valid[$type])) {
|
145 |
+
if ($type != 'object' || !method_exists($value, '__toString')) {
|
146 |
+
$this->addError('must be an fopen resource, a '
|
147 |
+
. 'GuzzleHttp\Stream\StreamInterface object, or something '
|
148 |
+
. 'that can be cast to a string. Found '
|
149 |
+
. Aws\describe_type($value));
|
150 |
+
}
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
private function check_numeric(Shape $shape, $value)
|
155 |
+
{
|
156 |
+
if (!is_numeric($value)) {
|
157 |
+
$this->addError('must be numeric. Found '
|
158 |
+
. Aws\describe_type($value));
|
159 |
+
return;
|
160 |
+
}
|
161 |
+
|
162 |
+
list($min, $max) = [$shape['min'], $shape['max']];
|
163 |
+
|
164 |
+
if ($min && $value < $min) {
|
165 |
+
$this->addError("must be at least $min. Value provided is $value.");
|
166 |
+
}
|
167 |
+
|
168 |
+
if ($max && $value > $max) {
|
169 |
+
$this->addError("must be no more than $max."
|
170 |
+
. " Value provided is $value.");
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
private function check_boolean(Shape $shape, $value)
|
175 |
+
{
|
176 |
+
if (!is_bool($value)) {
|
177 |
+
$this->addError('must be a boolean. Found '
|
178 |
+
. Aws\describe_type($value));
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
private function check_string(Shape $shape, $value)
|
183 |
+
{
|
184 |
+
if (!$this->checkCanString($value)) {
|
185 |
+
$this->addError('must be a string or an object that implements '
|
186 |
+
. '__toString(). Found ' . Aws\describe_type($value));
|
187 |
+
return;
|
188 |
+
}
|
189 |
+
|
190 |
+
list($min, $max, $len) = [$shape['min'], $shape['max'], strlen($value)];
|
191 |
+
|
192 |
+
if ($min && $len < $min) {
|
193 |
+
$this->addError("must be at least $min characters long."
|
194 |
+
. " Value provided is $len characters long.");
|
195 |
+
}
|
196 |
+
|
197 |
+
if ($max && $len > $max) {
|
198 |
+
$this->addError("must be no more than $max characters long."
|
199 |
+
. " Value provided is $len characters long.");
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
private function checkCanString($value)
|
204 |
+
{
|
205 |
+
static $valid = [
|
206 |
+
'string' => true,
|
207 |
+
'integer' => true,
|
208 |
+
'double' => true,
|
209 |
+
'NULL' => true,
|
210 |
+
];
|
211 |
+
|
212 |
+
$type = gettype($value);
|
213 |
+
|
214 |
+
return isset($valid[$type]) ||
|
215 |
+
($type == 'object' && method_exists($value, '__toString'));
|
216 |
+
}
|
217 |
+
|
218 |
+
private function checkAssociativeArray($value)
|
219 |
+
{
|
220 |
+
if (!is_array($value) || isset($value[0])) {
|
221 |
+
$this->addError('must be an associative array. Found '
|
222 |
+
. Aws\describe_type($value));
|
223 |
+
return false;
|
224 |
+
}
|
225 |
+
|
226 |
+
return true;
|
227 |
+
}
|
228 |
+
|
229 |
+
private function addError($message)
|
230 |
+
{
|
231 |
+
$this->errors[] =
|
232 |
+
implode('', array_map(function ($s) { return "[{$s}]"; }, $this->path))
|
233 |
+
. ' '
|
234 |
+
. $message;
|
235 |
+
}
|
236 |
+
}
|
includes/aws/Aws/ApiGateway/ApiGatewayClient.php
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\ApiGateway;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This client is used to interact with the **AWS API Gateway** service.
|
10 |
+
*
|
11 |
+
* @method \Aws\Result createApiKey(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise createApiKeyAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createBasePathMapping(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createBasePathMappingAsync(array $args = [])
|
15 |
+
* @method \Aws\Result createDeployment(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise createDeploymentAsync(array $args = [])
|
17 |
+
* @method \Aws\Result createDomainName(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise createDomainNameAsync(array $args = [])
|
19 |
+
* @method \Aws\Result createModel(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise createModelAsync(array $args = [])
|
21 |
+
* @method \Aws\Result createResource(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise createResourceAsync(array $args = [])
|
23 |
+
* @method \Aws\Result createRestApi(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise createRestApiAsync(array $args = [])
|
25 |
+
* @method \Aws\Result createStage(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise createStageAsync(array $args = [])
|
27 |
+
* @method \Aws\Result deleteApiKey(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise deleteApiKeyAsync(array $args = [])
|
29 |
+
* @method \Aws\Result deleteBasePathMapping(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise deleteBasePathMappingAsync(array $args = [])
|
31 |
+
* @method \Aws\Result deleteClientCertificate(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise deleteClientCertificateAsync(array $args = [])
|
33 |
+
* @method \Aws\Result deleteDeployment(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise deleteDeploymentAsync(array $args = [])
|
35 |
+
* @method \Aws\Result deleteDomainName(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise deleteDomainNameAsync(array $args = [])
|
37 |
+
* @method \Aws\Result deleteIntegration(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise deleteIntegrationAsync(array $args = [])
|
39 |
+
* @method \Aws\Result deleteIntegrationResponse(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise deleteIntegrationResponseAsync(array $args = [])
|
41 |
+
* @method \Aws\Result deleteMethod(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise deleteMethodAsync(array $args = [])
|
43 |
+
* @method \Aws\Result deleteMethodResponse(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise deleteMethodResponseAsync(array $args = [])
|
45 |
+
* @method \Aws\Result deleteModel(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise deleteModelAsync(array $args = [])
|
47 |
+
* @method \Aws\Result deleteResource(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise deleteResourceAsync(array $args = [])
|
49 |
+
* @method \Aws\Result deleteRestApi(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise deleteRestApiAsync(array $args = [])
|
51 |
+
* @method \Aws\Result deleteStage(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise deleteStageAsync(array $args = [])
|
53 |
+
* @method \Aws\Result flushStageCache(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise flushStageCacheAsync(array $args = [])
|
55 |
+
* @method \Aws\Result generateClientCertificate(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise generateClientCertificateAsync(array $args = [])
|
57 |
+
* @method \Aws\Result getAccount(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise getAccountAsync(array $args = [])
|
59 |
+
* @method \Aws\Result getApiKey(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise getApiKeyAsync(array $args = [])
|
61 |
+
* @method \Aws\Result getApiKeys(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise getApiKeysAsync(array $args = [])
|
63 |
+
* @method \Aws\Result getBasePathMapping(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise getBasePathMappingAsync(array $args = [])
|
65 |
+
* @method \Aws\Result getBasePathMappings(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise getBasePathMappingsAsync(array $args = [])
|
67 |
+
* @method \Aws\Result getClientCertificate(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise getClientCertificateAsync(array $args = [])
|
69 |
+
* @method \Aws\Result getClientCertificates(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise getClientCertificatesAsync(array $args = [])
|
71 |
+
* @method \Aws\Result getDeployment(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise getDeploymentAsync(array $args = [])
|
73 |
+
* @method \Aws\Result getDeployments(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise getDeploymentsAsync(array $args = [])
|
75 |
+
* @method \Aws\Result getDomainName(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise getDomainNameAsync(array $args = [])
|
77 |
+
* @method \Aws\Result getDomainNames(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise getDomainNamesAsync(array $args = [])
|
79 |
+
* @method \Aws\Result getIntegration(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise getIntegrationAsync(array $args = [])
|
81 |
+
* @method \Aws\Result getIntegrationResponse(array $args = [])
|
82 |
+
* @method \GuzzleHttp\Promise\Promise getIntegrationResponseAsync(array $args = [])
|
83 |
+
* @method \Aws\Result getMethod(array $args = [])
|
84 |
+
* @method \GuzzleHttp\Promise\Promise getMethodAsync(array $args = [])
|
85 |
+
* @method \Aws\Result getMethodResponse(array $args = [])
|
86 |
+
* @method \GuzzleHttp\Promise\Promise getMethodResponseAsync(array $args = [])
|
87 |
+
* @method \Aws\Result getModel(array $args = [])
|
88 |
+
* @method \GuzzleHttp\Promise\Promise getModelAsync(array $args = [])
|
89 |
+
* @method \Aws\Result getModelTemplate(array $args = [])
|
90 |
+
* @method \GuzzleHttp\Promise\Promise getModelTemplateAsync(array $args = [])
|
91 |
+
* @method \Aws\Result getModels(array $args = [])
|
92 |
+
* @method \GuzzleHttp\Promise\Promise getModelsAsync(array $args = [])
|
93 |
+
* @method \Aws\Result getResource(array $args = [])
|
94 |
+
* @method \GuzzleHttp\Promise\Promise getResourceAsync(array $args = [])
|
95 |
+
* @method \Aws\Result getResources(array $args = [])
|
96 |
+
* @method \GuzzleHttp\Promise\Promise getResourcesAsync(array $args = [])
|
97 |
+
* @method \Aws\Result getRestApi(array $args = [])
|
98 |
+
* @method \GuzzleHttp\Promise\Promise getRestApiAsync(array $args = [])
|
99 |
+
* @method \Aws\Result getRestApis(array $args = [])
|
100 |
+
* @method \GuzzleHttp\Promise\Promise getRestApisAsync(array $args = [])
|
101 |
+
* @method \Aws\Result getSdk(array $args = [])
|
102 |
+
* @method \GuzzleHttp\Promise\Promise getSdkAsync(array $args = [])
|
103 |
+
* @method \Aws\Result getStage(array $args = [])
|
104 |
+
* @method \GuzzleHttp\Promise\Promise getStageAsync(array $args = [])
|
105 |
+
* @method \Aws\Result getStages(array $args = [])
|
106 |
+
* @method \GuzzleHttp\Promise\Promise getStagesAsync(array $args = [])
|
107 |
+
* @method \Aws\Result putIntegration(array $args = [])
|
108 |
+
* @method \GuzzleHttp\Promise\Promise putIntegrationAsync(array $args = [])
|
109 |
+
* @method \Aws\Result putIntegrationResponse(array $args = [])
|
110 |
+
* @method \GuzzleHttp\Promise\Promise putIntegrationResponseAsync(array $args = [])
|
111 |
+
* @method \Aws\Result putMethod(array $args = [])
|
112 |
+
* @method \GuzzleHttp\Promise\Promise putMethodAsync(array $args = [])
|
113 |
+
* @method \Aws\Result putMethodResponse(array $args = [])
|
114 |
+
* @method \GuzzleHttp\Promise\Promise putMethodResponseAsync(array $args = [])
|
115 |
+
* @method \Aws\Result testInvokeMethod(array $args = [])
|
116 |
+
* @method \GuzzleHttp\Promise\Promise testInvokeMethodAsync(array $args = [])
|
117 |
+
* @method \Aws\Result updateAccount(array $args = [])
|
118 |
+
* @method \GuzzleHttp\Promise\Promise updateAccountAsync(array $args = [])
|
119 |
+
* @method \Aws\Result updateApiKey(array $args = [])
|
120 |
+
* @method \GuzzleHttp\Promise\Promise updateApiKeyAsync(array $args = [])
|
121 |
+
* @method \Aws\Result updateBasePathMapping(array $args = [])
|
122 |
+
* @method \GuzzleHttp\Promise\Promise updateBasePathMappingAsync(array $args = [])
|
123 |
+
* @method \Aws\Result updateClientCertificate(array $args = [])
|
124 |
+
* @method \GuzzleHttp\Promise\Promise updateClientCertificateAsync(array $args = [])
|
125 |
+
* @method \Aws\Result updateDeployment(array $args = [])
|
126 |
+
* @method \GuzzleHttp\Promise\Promise updateDeploymentAsync(array $args = [])
|
127 |
+
* @method \Aws\Result updateDomainName(array $args = [])
|
128 |
+
* @method \GuzzleHttp\Promise\Promise updateDomainNameAsync(array $args = [])
|
129 |
+
* @method \Aws\Result updateIntegration(array $args = [])
|
130 |
+
* @method \GuzzleHttp\Promise\Promise updateIntegrationAsync(array $args = [])
|
131 |
+
* @method \Aws\Result updateIntegrationResponse(array $args = [])
|
132 |
+
* @method \GuzzleHttp\Promise\Promise updateIntegrationResponseAsync(array $args = [])
|
133 |
+
* @method \Aws\Result updateMethod(array $args = [])
|
134 |
+
* @method \GuzzleHttp\Promise\Promise updateMethodAsync(array $args = [])
|
135 |
+
* @method \Aws\Result updateMethodResponse(array $args = [])
|
136 |
+
* @method \GuzzleHttp\Promise\Promise updateMethodResponseAsync(array $args = [])
|
137 |
+
* @method \Aws\Result updateModel(array $args = [])
|
138 |
+
* @method \GuzzleHttp\Promise\Promise updateModelAsync(array $args = [])
|
139 |
+
* @method \Aws\Result updateResource(array $args = [])
|
140 |
+
* @method \GuzzleHttp\Promise\Promise updateResourceAsync(array $args = [])
|
141 |
+
* @method \Aws\Result updateRestApi(array $args = [])
|
142 |
+
* @method \GuzzleHttp\Promise\Promise updateRestApiAsync(array $args = [])
|
143 |
+
* @method \Aws\Result updateStage(array $args = [])
|
144 |
+
* @method \GuzzleHttp\Promise\Promise updateStageAsync(array $args = [])
|
145 |
+
*/
|
146 |
+
class ApiGatewayClient extends AwsClient
|
147 |
+
{
|
148 |
+
public function __construct(array $args)
|
149 |
+
{
|
150 |
+
parent::__construct($args);
|
151 |
+
$stack = $this->getHandlerList();
|
152 |
+
$stack->appendBuild([__CLASS__, '_add_accept_header']);
|
153 |
+
}
|
154 |
+
|
155 |
+
public static function _add_accept_header(callable $handler)
|
156 |
+
{
|
157 |
+
return function (
|
158 |
+
CommandInterface $command,
|
159 |
+
RequestInterface $request
|
160 |
+
) use ($handler) {
|
161 |
+
$request = $request->withHeader('Accept', 'application/json');
|
162 |
+
|
163 |
+
return $handler($command, $request);
|
164 |
+
};
|
165 |
+
}
|
166 |
+
}
|
includes/aws/Aws/ApiGateway/Exception/ApiGatewayException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\ApiGateway\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the **AWS API Gateway** service.
|
8 |
+
*/
|
9 |
+
class ApiGatewayException extends AwsException {}
|
includes/aws/Aws/AwsClient.php
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Api\ApiProvider;
|
5 |
+
use Aws\Api\DocModel;
|
6 |
+
use Aws\Api\Service;
|
7 |
+
use Aws\Signature\SignatureProvider;
|
8 |
+
use GuzzleHttp\Psr7\Uri;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Default AWS client implementation
|
12 |
+
*/
|
13 |
+
class AwsClient implements AwsClientInterface
|
14 |
+
{
|
15 |
+
/** @var string */
|
16 |
+
private $region;
|
17 |
+
|
18 |
+
/** @var string */
|
19 |
+
private $endpoint;
|
20 |
+
|
21 |
+
/** @var Service */
|
22 |
+
private $api;
|
23 |
+
|
24 |
+
/** @var callable */
|
25 |
+
private $signatureProvider;
|
26 |
+
|
27 |
+
/** @var callable */
|
28 |
+
private $credentialProvider;
|
29 |
+
|
30 |
+
/** @var HandlerList */
|
31 |
+
private $handlerList;
|
32 |
+
|
33 |
+
/** @var array*/
|
34 |
+
private $defaultRequestOptions;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Get an array of client constructor arguments used by the client.
|
38 |
+
*
|
39 |
+
* @return array
|
40 |
+
*/
|
41 |
+
public static function getArguments()
|
42 |
+
{
|
43 |
+
return ClientResolver::getDefaultArguments();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The client constructor accepts the following options:
|
48 |
+
*
|
49 |
+
* - api_provider: (callable) An optional PHP callable that accepts a
|
50 |
+
* type, service, and version argument, and returns an array of
|
51 |
+
* corresponding configuration data. The type value can be one of api,
|
52 |
+
* waiter, or paginator.
|
53 |
+
* - credentials:
|
54 |
+
* (Aws\Credentials\CredentialsInterface|array|bool|callable) Specifies
|
55 |
+
* the credentials used to sign requests. Provide an
|
56 |
+
* Aws\Credentials\CredentialsInterface object, an associative array of
|
57 |
+
* "key", "secret", and an optional "token" key, `false` to use null
|
58 |
+
* credentials, or a callable credentials provider used to create
|
59 |
+
* credentials or return null. See Aws\Credentials\CredentialProvider for
|
60 |
+
* a list of built-in credentials providers. If no credentials are
|
61 |
+
* provided, the SDK will attempt to load them from the environment.
|
62 |
+
* - debug: (bool|array) Set to true to display debug information when
|
63 |
+
* sending requests. Alternatively, you can provide an associative array
|
64 |
+
* with the following keys: logfn: (callable) Function that is invoked
|
65 |
+
* with log messages; stream_size: (int) When the size of a stream is
|
66 |
+
* greater than this number, the stream data will not be logged (set to
|
67 |
+
* "0" to not log any stream data); scrub_auth: (bool) Set to false to
|
68 |
+
* disable the scrubbing of auth data from the logged messages; http:
|
69 |
+
* (bool) Set to false to disable the "debug" feature of lower level HTTP
|
70 |
+
* adapters (e.g., verbose curl output).
|
71 |
+
* - endpoint: (string) The full URI of the webservice. This is only
|
72 |
+
* required when connecting to a custom endpoint (e.g., a local version
|
73 |
+
* of S3).
|
74 |
+
* - endpoint_provider: (callable) An optional PHP callable that
|
75 |
+
* accepts a hash of options including a "service" and "region" key and
|
76 |
+
* returns NULL or a hash of endpoint data, of which the "endpoint" key
|
77 |
+
* is required. See Aws\Endpoint\EndpointProvider for a list of built-in
|
78 |
+
* providers.
|
79 |
+
* - handler: (callable) A handler that accepts a command object,
|
80 |
+
* request object and returns a promise that is fulfilled with an
|
81 |
+
* Aws\ResultInterface object or rejected with an
|
82 |
+
* Aws\Exception\AwsException. A handler does not accept a next handler
|
83 |
+
* as it is terminal and expected to fulfill a command. If no handler is
|
84 |
+
* provided, a default Guzzle handler will be utilized.
|
85 |
+
* - http: (array, default=array(0)) Set to an array of SDK request
|
86 |
+
* options to apply to each request (e.g., proxy, verify, etc.).
|
87 |
+
* - http_handler: (callable) An HTTP handler is a function that
|
88 |
+
* accepts a PSR-7 request object and returns a promise that is fulfilled
|
89 |
+
* with a PSR-7 response object or rejected with an array of exception
|
90 |
+
* data. NOTE: This option supersedes any provided "handler" option.
|
91 |
+
* - profile: (string) Allows you to specify which profile to use when
|
92 |
+
* credentials are created from the AWS credentials file in your HOME
|
93 |
+
* directory. This setting overrides the AWS_PROFILE environment
|
94 |
+
* variable. Note: Specifying "profile" will cause the "credentials" key
|
95 |
+
* to be ignored.
|
96 |
+
* - region: (string, required) Region to connect to. See
|
97 |
+
* http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of
|
98 |
+
* available regions.
|
99 |
+
* - retries: (int, default=int(3)) Configures the maximum number of
|
100 |
+
* allowed retries for a client (pass 0 to disable retries).
|
101 |
+
* - scheme: (string, default=string(5) "https") URI scheme to use when
|
102 |
+
* connecting connect. The SDK will utilize "https" endpoints (i.e.,
|
103 |
+
* utilize SSL/TLS connections) by default. You can attempt to connect to
|
104 |
+
* a service over an unencrypted "http" endpoint by setting ``scheme`` to
|
105 |
+
* "http".
|
106 |
+
* - signature_provider: (callable) A callable that accepts a signature
|
107 |
+
* version name (e.g., "v4"), a service name, and region, and
|
108 |
+
* returns a SignatureInterface object or null. This provider is used to
|
109 |
+
* create signers utilized by the client. See
|
110 |
+
* Aws\Signature\SignatureProvider for a list of built-in providers
|
111 |
+
* - signature_version: (string) A string representing a custom
|
112 |
+
* signature version to use with a service (e.g., v4). Note that
|
113 |
+
* per/operation signature version MAY override this requested signature
|
114 |
+
* version.
|
115 |
+
* - validate: (bool, default=bool(true)) Set to false to disable
|
116 |
+
* client-side parameter validation.
|
117 |
+
* - version: (string, required) The version of the webservice to
|
118 |
+
* utilize (e.g., 2006-03-01).
|
119 |
+
*
|
120 |
+
* @param array $args Client configuration arguments.
|
121 |
+
*
|
122 |
+
* @throws \InvalidArgumentException if any required options are missing or
|
123 |
+
* the service is not supported.
|
124 |
+
*/
|
125 |
+
public function __construct(array $args)
|
126 |
+
{
|
127 |
+
list($service, $exceptionClass) = $this->parseClass();
|
128 |
+
if (!isset($args['service'])) {
|
129 |
+
$args['service'] = manifest($service)['endpoint'];
|
130 |
+
}
|
131 |
+
if (!isset($args['exception_class'])) {
|
132 |
+
$args['exception_class'] = $exceptionClass;
|
133 |
+
}
|
134 |
+
|
135 |
+
$this->handlerList = new HandlerList();
|
136 |
+
$resolver = new ClientResolver(static::getArguments());
|
137 |
+
$config = $resolver->resolve($args, $this->handlerList);
|
138 |
+
$this->api = $config['api'];
|
139 |
+
$this->signatureProvider = $config['signature_provider'];
|
140 |
+
$this->endpoint = new Uri($config['endpoint']);
|
141 |
+
$this->credentialProvider = $config['credentials'];
|
142 |
+
$this->region = isset($config['region']) ? $config['region'] : null;
|
143 |
+
$this->config = $config['config'];
|
144 |
+
$this->defaultRequestOptions = $config['http'];
|
145 |
+
$this->addSignatureMiddleware();
|
146 |
+
|
147 |
+
if (isset($args['with_resolved'])) {
|
148 |
+
$args['with_resolved']($config);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
public function getHandlerList()
|
153 |
+
{
|
154 |
+
return $this->handlerList;
|
155 |
+
}
|
156 |
+
|
157 |
+
public function __call($name, array $args)
|
158 |
+
{
|
159 |
+
$params = isset($args[0]) ? $args[0] : [];
|
160 |
+
|
161 |
+
if (substr($name, -5) === 'Async') {
|
162 |
+
return $this->executeAsync(
|
163 |
+
$this->getCommand(substr($name, 0, -5), $params)
|
164 |
+
);
|
165 |
+
}
|
166 |
+
|
167 |
+
return $this->execute($this->getCommand($name, $params));
|
168 |
+
}
|
169 |
+
|
170 |
+
public function getConfig($option = null)
|
171 |
+
{
|
172 |
+
return $option === null
|
173 |
+
? $this->config
|
174 |
+
: (isset($this->config[$option])
|
175 |
+
? $this->config[$option]
|
176 |
+
: null);
|
177 |
+
}
|
178 |
+
|
179 |
+
public function getCredentials()
|
180 |
+
{
|
181 |
+
$fn = $this->credentialProvider;
|
182 |
+
return $fn();
|
183 |
+
}
|
184 |
+
|
185 |
+
public function getEndpoint()
|
186 |
+
{
|
187 |
+
return $this->endpoint;
|
188 |
+
}
|
189 |
+
|
190 |
+
public function getRegion()
|
191 |
+
{
|
192 |
+
return $this->region;
|
193 |
+
}
|
194 |
+
|
195 |
+
public function getApi()
|
196 |
+
{
|
197 |
+
return $this->api;
|
198 |
+
}
|
199 |
+
|
200 |
+
public function execute(CommandInterface $command)
|
201 |
+
{
|
202 |
+
return $this->executeAsync($command)->wait();
|
203 |
+
}
|
204 |
+
|
205 |
+
public function executeAsync(CommandInterface $command)
|
206 |
+
{
|
207 |
+
$handler = $command->getHandlerList()->resolve();
|
208 |
+
return $handler($command);
|
209 |
+
}
|
210 |
+
|
211 |
+
public function getCommand($name, array $args = [])
|
212 |
+
{
|
213 |
+
// Fail fast if the command cannot be found in the description.
|
214 |
+
if (!isset($this->api['operations'][$name])) {
|
215 |
+
$name = ucfirst($name);
|
216 |
+
if (!isset($this->api['operations'][$name])) {
|
217 |
+
throw new \InvalidArgumentException("Operation not found: $name");
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
if (!isset($args['@http'])) {
|
222 |
+
$args['@http'] = $this->defaultRequestOptions;
|
223 |
+
} else {
|
224 |
+
$args['@http'] += $this->defaultRequestOptions;
|
225 |
+
}
|
226 |
+
|
227 |
+
return new Command($name, $args, clone $this->getHandlerList());
|
228 |
+
}
|
229 |
+
|
230 |
+
public function getIterator($name, array $args = [])
|
231 |
+
{
|
232 |
+
$config = $this->api->getPaginatorConfig($name);
|
233 |
+
if (!$config['result_key']) {
|
234 |
+
throw new \UnexpectedValueException(sprintf(
|
235 |
+
'There are no resources to iterate for the %s operation of %s',
|
236 |
+
$name, $this->api['serviceFullName']
|
237 |
+
));
|
238 |
+
}
|
239 |
+
|
240 |
+
$key = is_array($config['result_key'])
|
241 |
+
? $config['result_key'][0]
|
242 |
+
: $config['result_key'];
|
243 |
+
|
244 |
+
if ($config['output_token'] && $config['input_token']) {
|
245 |
+
return $this->getPaginator($name, $args)->search($key);
|
246 |
+
}
|
247 |
+
|
248 |
+
$result = $this->execute($this->getCommand($name, $args))->search($key);
|
249 |
+
|
250 |
+
return new \ArrayIterator((array) $result);
|
251 |
+
}
|
252 |
+
|
253 |
+
public function getPaginator($name, array $args = [])
|
254 |
+
{
|
255 |
+
$config = $this->api->getPaginatorConfig($name);
|
256 |
+
|
257 |
+
return new ResultPaginator($this, $name, $args, $config);
|
258 |
+
}
|
259 |
+
|
260 |
+
public function waitUntil($name, array $args = [])
|
261 |
+
{
|
262 |
+
return $this->getWaiter($name, $args)->promise()->wait();
|
263 |
+
}
|
264 |
+
|
265 |
+
public function getWaiter($name, array $args = [])
|
266 |
+
{
|
267 |
+
$config = isset($args['@waiter']) ? $args['@waiter'] : [];
|
268 |
+
$config += $this->api->getWaiterConfig($name);
|
269 |
+
|
270 |
+
return new Waiter($this, $name, $args, $config);
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Get the signature_provider function of the client.
|
275 |
+
*
|
276 |
+
* @return callable
|
277 |
+
*/
|
278 |
+
final protected function getSignatureProvider()
|
279 |
+
{
|
280 |
+
return $this->signatureProvider;
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Parse the class name and setup the custom exception class of the client
|
285 |
+
* and return the "service" name of the client and "exception_class".
|
286 |
+
*
|
287 |
+
* @return array
|
288 |
+
*/
|
289 |
+
private function parseClass()
|
290 |
+
{
|
291 |
+
$klass = get_class($this);
|
292 |
+
|
293 |
+
if ($klass === __CLASS__) {
|
294 |
+
return ['', 'Aws\Exception\AwsException'];
|
295 |
+
}
|
296 |
+
|
297 |
+
$service = substr($klass, strrpos($klass, '\\') + 1, -6);
|
298 |
+
|
299 |
+
return [
|
300 |
+
strtolower($service),
|
301 |
+
"Aws\\{$service}\\Exception\\{$service}Exception"
|
302 |
+
];
|
303 |
+
}
|
304 |
+
|
305 |
+
private function addSignatureMiddleware()
|
306 |
+
{
|
307 |
+
// Sign requests. This may need to be modified later to support
|
308 |
+
// variable signatures per/operation.
|
309 |
+
$this->handlerList->appendSign(
|
310 |
+
Middleware::signer(
|
311 |
+
$this->credentialProvider,
|
312 |
+
constantly(SignatureProvider::resolve(
|
313 |
+
$this->signatureProvider,
|
314 |
+
$this->config['signature_version'],
|
315 |
+
$this->api->getSigningName(),
|
316 |
+
$this->region
|
317 |
+
))
|
318 |
+
),
|
319 |
+
'signer'
|
320 |
+
);
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Returns a service model and doc model with any necessary changes
|
325 |
+
* applied.
|
326 |
+
*
|
327 |
+
* @param array $api Array of service data being documented.
|
328 |
+
* @param array $docs Array of doc model data.
|
329 |
+
*
|
330 |
+
* @return array Tuple containing a [Service, DocModel]
|
331 |
+
*
|
332 |
+
* @internal This should only used to document the service API.
|
333 |
+
* @codeCoverageIgnore
|
334 |
+
*/
|
335 |
+
public static function applyDocFilters(array $api, array $docs)
|
336 |
+
{
|
337 |
+
return [
|
338 |
+
new Service($api, ApiProvider::defaultProvider()),
|
339 |
+
new DocModel($docs)
|
340 |
+
];
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* @deprecated
|
345 |
+
* @return static
|
346 |
+
*/
|
347 |
+
public static function factory(array $config = [])
|
348 |
+
{
|
349 |
+
return new static($config);
|
350 |
+
}
|
351 |
+
}
|
includes/aws/Aws/AwsClientInterface.php
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Psr\Http\Message\UriInterface;
|
5 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Represents an AWS client.
|
9 |
+
*/
|
10 |
+
interface AwsClientInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Creates and executes a command for an operation by name.
|
14 |
+
*
|
15 |
+
* Suffixing an operation name with "Async" will return a
|
16 |
+
* promise that can be used to execute commands asynchronously.
|
17 |
+
*
|
18 |
+
* @param string $name Name of the command to execute.
|
19 |
+
* @param array $arguments Arguments to pass to the getCommand method.
|
20 |
+
*
|
21 |
+
* @return ResultInterface
|
22 |
+
* @throws \Exception
|
23 |
+
*/
|
24 |
+
public function __call($name, array $arguments);
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Create a command for an operation name.
|
28 |
+
*
|
29 |
+
* Special keys may be set on the command to control how it behaves,
|
30 |
+
* including:
|
31 |
+
*
|
32 |
+
* - @http: Associative array of transfer specific options to apply to the
|
33 |
+
* request that is serialized for this command. Available keys include
|
34 |
+
* "proxy", "verify", "timeout", "connect_timeout", "debug", "delay", and
|
35 |
+
* "headers".
|
36 |
+
*
|
37 |
+
* @param string $name Name of the operation to use in the command
|
38 |
+
* @param array $args Arguments to pass to the command
|
39 |
+
*
|
40 |
+
* @return CommandInterface
|
41 |
+
* @throws \InvalidArgumentException if no command can be found by name
|
42 |
+
*/
|
43 |
+
public function getCommand($name, array $args = []);
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Execute a single command.
|
47 |
+
*
|
48 |
+
* @param CommandInterface $command Command to execute
|
49 |
+
*
|
50 |
+
* @return ResultInterface
|
51 |
+
* @throws \Exception
|
52 |
+
*/
|
53 |
+
public function execute(CommandInterface $command);
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Execute a command asynchronously.
|
57 |
+
*
|
58 |
+
* @param CommandInterface $command Command to execute
|
59 |
+
*
|
60 |
+
* @return \GuzzleHttp\Promise\PromiseInterface
|
61 |
+
*/
|
62 |
+
public function executeAsync(CommandInterface $command);
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Returns a promise that is fulfilled with an
|
66 |
+
* {@see \Aws\Credentials\CredentialsInterface} object.
|
67 |
+
*
|
68 |
+
* If you need the credentials synchronously, then call the wait() method
|
69 |
+
* on the returned promise.
|
70 |
+
*
|
71 |
+
* @return PromiseInterface
|
72 |
+
*/
|
73 |
+
public function getCredentials();
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Get the region to which the client is configured to send requests.
|
77 |
+
*
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function getRegion();
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Gets the default endpoint, or base URL, used by the client.
|
84 |
+
*
|
85 |
+
* @return UriInterface
|
86 |
+
*/
|
87 |
+
public function getEndpoint();
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get the service description associated with the client.
|
91 |
+
*
|
92 |
+
* @return \Aws\Api\Service
|
93 |
+
*/
|
94 |
+
public function getApi();
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Get a client configuration value.
|
98 |
+
*
|
99 |
+
* @param string|null $option The option to retrieve. Pass null to retrieve
|
100 |
+
* all options.
|
101 |
+
* @return mixed|null
|
102 |
+
*/
|
103 |
+
public function getConfig($option = null);
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Get the handler list used to transfer commands.
|
107 |
+
*
|
108 |
+
* This list can be modified to add middleware or to change the underlying
|
109 |
+
* handler used to send HTTP requests.
|
110 |
+
*
|
111 |
+
* @return HandlerList
|
112 |
+
*/
|
113 |
+
public function getHandlerList();
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Get a resource iterator for the specified operation.
|
117 |
+
*
|
118 |
+
* @param string $name Name of the iterator to retrieve.
|
119 |
+
* @param array $args Command arguments to use with each command.
|
120 |
+
*
|
121 |
+
* @return \Iterator
|
122 |
+
* @throws \UnexpectedValueException if the iterator config is invalid.
|
123 |
+
*/
|
124 |
+
public function getIterator($name, array $args = []);
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get a result paginator for the specified operation.
|
128 |
+
*
|
129 |
+
* @param string $name Name of the operation used for iterator
|
130 |
+
* @param array $args Command args to be used with each command
|
131 |
+
*
|
132 |
+
* @return \Aws\ResultPaginator
|
133 |
+
* @throws \UnexpectedValueException if the iterator config is invalid.
|
134 |
+
*/
|
135 |
+
public function getPaginator($name, array $args = []);
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Wait until a resource is in a particular state.
|
139 |
+
*
|
140 |
+
* @param string|callable $name Name of the waiter that defines the wait
|
141 |
+
* configuration and conditions.
|
142 |
+
* @param array $args Args to be used with each command executed
|
143 |
+
* by the waiter. Waiter configuration options
|
144 |
+
* can be provided in an associative array in
|
145 |
+
* the @waiter key.
|
146 |
+
* @return void
|
147 |
+
* @throws \UnexpectedValueException if the waiter is invalid.
|
148 |
+
*/
|
149 |
+
public function waitUntil($name, array $args = []);
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Get a waiter that waits until a resource is in a particular state.
|
153 |
+
*
|
154 |
+
* Retrieving a waiter can be useful when you wish to wait asynchronously:
|
155 |
+
*
|
156 |
+
* $waiter = $client->getWaiter('foo', ['bar' => 'baz']);
|
157 |
+
* $waiter->promise()->then(function () { echo 'Done!'; });
|
158 |
+
*
|
159 |
+
* @param string|callable $name Name of the waiter that defines the wait
|
160 |
+
* configuration and conditions.
|
161 |
+
* @param array $args Args to be used with each command executed
|
162 |
+
* by the waiter. Waiter configuration options
|
163 |
+
* can be provided in an associative array in
|
164 |
+
* the @waiter key.
|
165 |
+
* @return \Aws\Waiter
|
166 |
+
* @throws \UnexpectedValueException if the waiter is invalid.
|
167 |
+
*/
|
168 |
+
public function getWaiter($name, array $args = []);
|
169 |
+
}
|
includes/aws/Aws/CacheInterface.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents a simple cache interface.
|
6 |
+
*/
|
7 |
+
interface CacheInterface
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Get a cache item by key.
|
11 |
+
*
|
12 |
+
* @param string $key Key to retrieve.
|
13 |
+
*
|
14 |
+
* @return mixed|null Returns the value or null if not found.
|
15 |
+
*/
|
16 |
+
public function get($key);
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Set a cache key value.
|
20 |
+
*
|
21 |
+
* @param string $key Key to set
|
22 |
+
* @param mixed $value Value to set.
|
23 |
+
* @param int $ttl Number of seconds the item is allowed to live. Set
|
24 |
+
* to 0 to allow an unlimited lifetime.
|
25 |
+
*/
|
26 |
+
public function set($key, $value, $ttl = 0);
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Remove a cache key.
|
30 |
+
*
|
31 |
+
* @param string $key Key to remove.
|
32 |
+
*/
|
33 |
+
public function remove($key);
|
34 |
+
}
|
includes/aws/Aws/ClientResolver.php
ADDED
@@ -0,0 +1,548 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Api\Validator;
|
5 |
+
use Aws\Api\ApiProvider;
|
6 |
+
use Aws\Api\Service;
|
7 |
+
use Aws\Credentials\Credentials;
|
8 |
+
use Aws\Credentials\CredentialsInterface;
|
9 |
+
use Aws\Signature\SignatureProvider;
|
10 |
+
use Aws\Endpoint\EndpointProvider;
|
11 |
+
use Aws\Credentials\CredentialProvider;
|
12 |
+
use GuzzleHttp\Promise;
|
13 |
+
use InvalidArgumentException as IAE;
|
14 |
+
use Psr\Http\Message\RequestInterface;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @internal Resolves a hash of client arguments to construct a client.
|
18 |
+
*/
|
19 |
+
class ClientResolver
|
20 |
+
{
|
21 |
+
/** @var array */
|
22 |
+
private $argDefinitions;
|
23 |
+
|
24 |
+
/** @var array Map of types to a corresponding function */
|
25 |
+
private static $typeMap = [
|
26 |
+
'resource' => 'is_resource',
|
27 |
+
'callable' => 'is_callable',
|
28 |
+
'int' => 'is_int',
|
29 |
+
'bool' => 'is_bool',
|
30 |
+
'string' => 'is_string',
|
31 |
+
'object' => 'is_object',
|
32 |
+
'array' => 'is_array',
|
33 |
+
];
|
34 |
+
|
35 |
+
private static $defaultArgs = [
|
36 |
+
'service' => [
|
37 |
+
'type' => 'value',
|
38 |
+
'valid' => ['string'],
|
39 |
+
'doc' => 'Name of the service to utilize. This value will be supplied by default when using one of the SDK clients (e.g., Aws\\S3\\S3Client).',
|
40 |
+
'required' => true,
|
41 |
+
'internal' => true
|
42 |
+
],
|
43 |
+
'exception_class' => [
|
44 |
+
'type' => 'value',
|
45 |
+
'valid' => ['string'],
|
46 |
+
'doc' => 'Exception class to create when an error occurs.',
|
47 |
+
'default' => 'Aws\Exception\AwsException',
|
48 |
+
'internal' => true
|
49 |
+
],
|
50 |
+
'scheme' => [
|
51 |
+
'type' => 'value',
|
52 |
+
'valid' => ['string'],
|
53 |
+
'default' => 'https',
|
54 |
+
'doc' => 'URI scheme to use when connecting connect. The SDK will utilize "https" endpoints (i.e., utilize SSL/TLS connections) by default. You can attempt to connect to a service over an unencrypted "http" endpoint by setting ``scheme`` to "http".',
|
55 |
+
],
|
56 |
+
'endpoint' => [
|
57 |
+
'type' => 'value',
|
58 |
+
'valid' => ['string'],
|
59 |
+
'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).',
|
60 |
+
'fn' => [__CLASS__, '_apply_endpoint'],
|
61 |
+
],
|
62 |
+
'region' => [
|
63 |
+
'type' => 'value',
|
64 |
+
'valid' => ['string'],
|
65 |
+
'required' => [__CLASS__, '_missing_region'],
|
66 |
+
'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.',
|
67 |
+
],
|
68 |
+
'version' => [
|
69 |
+
'type' => 'value',
|
70 |
+
'valid' => ['string'],
|
71 |
+
'required' => [__CLASS__, '_missing_version'],
|
72 |
+
'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).',
|
73 |
+
],
|
74 |
+
'signature_provider' => [
|
75 |
+
'type' => 'value',
|
76 |
+
'valid' => ['callable'],
|
77 |
+
'doc' => 'A callable that accepts a signature version name (e.g., "v4"), a service name, and region, and returns a SignatureInterface object or null. This provider is used to create signers utilized by the client. See Aws\\Signature\\SignatureProvider for a list of built-in providers',
|
78 |
+
'default' => [__CLASS__, '_default_signature_provider'],
|
79 |
+
],
|
80 |
+
'endpoint_provider' => [
|
81 |
+
'type' => 'value',
|
82 |
+
'valid' => ['callable'],
|
83 |
+
'fn' => [__CLASS__, '_apply_endpoint_provider'],
|
84 |
+
'doc' => 'An optional PHP callable that accepts a hash of options including a "service" and "region" key and returns NULL or a hash of endpoint data, of which the "endpoint" key is required. See Aws\\Endpoint\\EndpointProvider for a list of built-in providers.',
|
85 |
+
'default' => [__CLASS__, '_default_endpoint_provider'],
|
86 |
+
],
|
87 |
+
'api_provider' => [
|
88 |
+
'type' => 'value',
|
89 |
+
'valid' => ['callable'],
|
90 |
+
'doc' => 'An optional PHP callable that accepts a type, service, and version argument, and returns an array of corresponding configuration data. The type value can be one of api, waiter, or paginator.',
|
91 |
+
'fn' => [__CLASS__, '_apply_api_provider'],
|
92 |
+
'default' => [ApiProvider::class, 'defaultProvider'],
|
93 |
+
],
|
94 |
+
'signature_version' => [
|
95 |
+
'type' => 'config',
|
96 |
+
'valid' => ['string'],
|
97 |
+
'doc' => 'A string representing a custom signature version to use with a service (e.g., v4). Note that per/operation signature version MAY override this requested signature version.',
|
98 |
+
'default' => [__CLASS__, '_default_signature_version'],
|
99 |
+
],
|
100 |
+
'profile' => [
|
101 |
+
'type' => 'config',
|
102 |
+
'valid' => ['string'],
|
103 |
+
'doc' => 'Allows you to specify which profile to use when credentials are created from the AWS credentials file in your HOME directory. This setting overrides the AWS_PROFILE environment variable. Note: Specifying "profile" will cause the "credentials" key to be ignored.',
|
104 |
+
'fn' => [__CLASS__, '_apply_profile'],
|
105 |
+
],
|
106 |
+
'credentials' => [
|
107 |
+
'type' => 'value',
|
108 |
+
'valid' => [CredentialsInterface::class, CacheInterface::class, 'array', 'bool', 'callable'],
|
109 |
+
'doc' => 'Specifies the credentials used to sign requests. Provide an Aws\Credentials\CredentialsInterface object, an associative array of "key", "secret", and an optional "token" key, `false` to use null credentials, or a callable credentials provider used to create credentials or return null. See Aws\\Credentials\\CredentialProvider for a list of built-in credentials providers. If no credentials are provided, the SDK will attempt to load them from the environment.',
|
110 |
+
'fn' => [__CLASS__, '_apply_credentials'],
|
111 |
+
'default' => [CredentialProvider::class, 'defaultProvider'],
|
112 |
+
],
|
113 |
+
'retries' => [
|
114 |
+
'type' => 'value',
|
115 |
+
'valid' => ['int'],
|
116 |
+
'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ',
|
117 |
+
'fn' => [__CLASS__, '_apply_retries'],
|
118 |
+
'default' => 3,
|
119 |
+
],
|
120 |
+
'validate' => [
|
121 |
+
'type' => 'value',
|
122 |
+
'valid' => ['bool'],
|
123 |
+
'default' => true,
|
124 |
+
'doc' => 'Set to false to disable client-side parameter validation.',
|
125 |
+
'fn' => [__CLASS__, '_apply_validate'],
|
126 |
+
],
|
127 |
+
'debug' => [
|
128 |
+
'type' => 'value',
|
129 |
+
'valid' => ['bool', 'array'],
|
130 |
+
'doc' => 'Set to true to display debug information when sending requests. Alternatively, you can provide an associative array with the following keys: logfn: (callable) Function that is invoked with log messages; stream_size: (int) When the size of a stream is greater than this number, the stream data will not be logged (set to "0" to not log any stream data); scrub_auth: (bool) Set to false to disable the scrubbing of auth data from the logged messages; http: (bool) Set to false to disable the "debug" feature of lower level HTTP adapters (e.g., verbose curl output).',
|
131 |
+
'fn' => [__CLASS__, '_apply_debug'],
|
132 |
+
],
|
133 |
+
'http' => [
|
134 |
+
'type' => 'value',
|
135 |
+
'valid' => ['array'],
|
136 |
+
'default' => [],
|
137 |
+
'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).',
|
138 |
+
],
|
139 |
+
'http_handler' => [
|
140 |
+
'type' => 'value',
|
141 |
+
'valid' => ['callable'],
|
142 |
+
'doc' => 'An HTTP handler is a function that accepts a PSR-7 request object and returns a promise that is fulfilled with a PSR-7 response object or rejected with an array of exception data. NOTE: This option supersedes any provided "handler" option.',
|
143 |
+
'fn' => [__CLASS__, '_apply_http_handler']
|
144 |
+
],
|
145 |
+
'handler' => [
|
146 |
+
'type' => 'value',
|
147 |
+
'valid' => ['callable'],
|
148 |
+
'doc' => 'A handler that accepts a command object, request object and returns a promise that is fulfilled with an Aws\ResultInterface object or rejected with an Aws\Exception\AwsException. A handler does not accept a next handler as it is terminal and expected to fulfill a command. If no handler is provided, a default Guzzle handler will be utilized.',
|
149 |
+
'fn' => [__CLASS__, '_apply_handler'],
|
150 |
+
'default' => [__CLASS__, '_default_handler']
|
151 |
+
],
|
152 |
+
'ua_append' => [
|
153 |
+
'type' => 'value',
|
154 |
+
'valid' => ['string', 'array'],
|
155 |
+
'doc' => 'Provide a string or array of strings to send in the User-Agent header.',
|
156 |
+
'fn' => [__CLASS__, '_apply_user_agent'],
|
157 |
+
'default' => [],
|
158 |
+
],
|
159 |
+
];
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Gets an array of default client arguments, each argument containing a
|
163 |
+
* hash of the following:
|
164 |
+
*
|
165 |
+
* - type: (string, required) option type described as follows:
|
166 |
+
* - value: The default option type.
|
167 |
+
* - config: The provided value is made available in the client's
|
168 |
+
* getConfig() method.
|
169 |
+
* - valid: (array, required) Valid PHP types or class names. Note: null
|
170 |
+
* is not an allowed type.
|
171 |
+
* - required: (bool, callable) Whether or not the argument is required.
|
172 |
+
* Provide a function that accepts an array of arguments and returns a
|
173 |
+
* string to provide a custom error message.
|
174 |
+
* - default: (mixed) The default value of the argument if not provided. If
|
175 |
+
* a function is provided, then it will be invoked to provide a default
|
176 |
+
* value. The function is provided the array of options and is expected
|
177 |
+
* to return the default value of the option.
|
178 |
+
* - doc: (string) The argument documentation string.
|
179 |
+
* - fn: (callable) Function used to apply the argument. The function
|
180 |
+
* accepts the provided value, array of arguments by reference, and an
|
181 |
+
* event emitter.
|
182 |
+
*
|
183 |
+
* Note: Order is honored and important when applying arguments.
|
184 |
+
*
|
185 |
+
* @return array
|
186 |
+
*/
|
187 |
+
public static function getDefaultArguments()
|
188 |
+
{
|
189 |
+
return self::$defaultArgs;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* @param array $argDefinitions Client arguments.
|
194 |
+
*/
|
195 |
+
public function __construct(array $argDefinitions)
|
196 |
+
{
|
197 |
+
$this->argDefinitions = $argDefinitions;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Resolves client configuration options and attached event listeners.
|
202 |
+
*
|
203 |
+
* @param array $args Provided constructor arguments.
|
204 |
+
* @param HandlerList $list Handler list to augment.
|
205 |
+
*
|
206 |
+
* @return array Returns the array of provided options.
|
207 |
+
* @throws \InvalidArgumentException
|
208 |
+
* @see Aws\AwsClient::__construct for a list of available options.
|
209 |
+
*/
|
210 |
+
public function resolve(array $args, HandlerList $list)
|
211 |
+
{
|
212 |
+
$args['config'] = [];
|
213 |
+
foreach ($this->argDefinitions as $key => $a) {
|
214 |
+
// Add defaults, validate required values, and skip if not set.
|
215 |
+
if (!isset($args[$key])) {
|
216 |
+
if (isset($a['default'])) {
|
217 |
+
// Merge defaults in when not present.
|
218 |
+
$args[$key] = is_callable($a['default'])
|
219 |
+
? $a['default']($args)
|
220 |
+
: $a['default'];
|
221 |
+
} elseif (empty($a['required'])) {
|
222 |
+
continue;
|
223 |
+
} else {
|
224 |
+
$this->throwRequired($args);
|
225 |
+
}
|
226 |
+
}
|
227 |
+
|
228 |
+
// Validate the types against the provided value.
|
229 |
+
foreach ($a['valid'] as $check) {
|
230 |
+
if (isset(self::$typeMap[$check])) {
|
231 |
+
$fn = self::$typeMap[$check];
|
232 |
+
if ($fn($args[$key])) {
|
233 |
+
goto is_valid;
|
234 |
+
}
|
235 |
+
} elseif ($args[$key] instanceof $check) {
|
236 |
+
goto is_valid;
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
$this->invalidType($key, $args[$key]);
|
241 |
+
|
242 |
+
// Apply the value
|
243 |
+
is_valid:
|
244 |
+
if (isset($a['fn'])) {
|
245 |
+
$a['fn']($args[$key], $args, $list);
|
246 |
+
}
|
247 |
+
|
248 |
+
if ($a['type'] === 'config') {
|
249 |
+
$args['config'][$key] = $args[$key];
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
return $args;
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Creates a verbose error message for an invalid argument.
|
258 |
+
*
|
259 |
+
* @param string $name Name of the argument that is missing.
|
260 |
+
* @param array $args Provided arguments
|
261 |
+
* @param bool $useRequired Set to true to show the required fn text if
|
262 |
+
* available instead of the documentation.
|
263 |
+
* @return string
|
264 |
+
*/
|
265 |
+
private function getArgMessage($name, $args = [], $useRequired = false)
|
266 |
+
{
|
267 |
+
$arg = $this->argDefinitions[$name];
|
268 |
+
$msg = '';
|
269 |
+
$modifiers = [];
|
270 |
+
if (isset($arg['valid'])) {
|
271 |
+
$modifiers[] = implode('|', $arg['valid']);
|
272 |
+
}
|
273 |
+
if (isset($arg['choice'])) {
|
274 |
+
$modifiers[] = 'One of ' . implode(', ', $arg['choice']);
|
275 |
+
}
|
276 |
+
if ($modifiers) {
|
277 |
+
$msg .= '(' . implode('; ', $modifiers) . ')';
|
278 |
+
}
|
279 |
+
$msg = wordwrap("{$name}: {$msg}", 75, "\n ");
|
280 |
+
|
281 |
+
if ($useRequired && is_callable($arg['required'])) {
|
282 |
+
$msg .= "\n\n ";
|
283 |
+
$msg .= str_replace("\n", "\n ", call_user_func($arg['required'], $args));
|
284 |
+
} elseif (isset($arg['doc'])) {
|
285 |
+
$msg .= wordwrap("\n\n {$arg['doc']}", 75, "\n ");
|
286 |
+
}
|
287 |
+
|
288 |
+
return $msg;
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Throw when an invalid type is encountered.
|
293 |
+
*
|
294 |
+
* @param string $name Name of the value being validated.
|
295 |
+
* @param mixed $provided The provided value.
|
296 |
+
* @throws \InvalidArgumentException
|
297 |
+
*/
|
298 |
+
private function invalidType($name, $provided)
|
299 |
+
{
|
300 |
+
$expected = implode('|', $this->argDefinitions[$name]['valid']);
|
301 |
+
$msg = "Invalid configuration value "
|
302 |
+
. "provided for \"{$name}\". Expected {$expected}, but got "
|
303 |
+
. describe_type($provided) . "\n\n"
|
304 |
+
. $this->getArgMessage($name);
|
305 |
+
throw new IAE($msg);
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Throws an exception for missing required arguments.
|
310 |
+
*
|
311 |
+
* @param array $args Passed in arguments.
|
312 |
+
* @throws \InvalidArgumentException
|
313 |
+
*/
|
314 |
+
private function throwRequired(array $args)
|
315 |
+
{
|
316 |
+
$missing = [];
|
317 |
+
foreach ($this->argDefinitions as $k => $a) {
|
318 |
+
if (empty($a['required'])
|
319 |
+
|| isset($a['default'])
|
320 |
+
|| array_key_exists($k, $args)
|
321 |
+
) {
|
322 |
+
continue;
|
323 |
+
}
|
324 |
+
$missing[] = $this->getArgMessage($k, $args, true);
|
325 |
+
}
|
326 |
+
$msg = "Missing required client configuration options: \n\n";
|
327 |
+
$msg .= implode("\n\n", $missing);
|
328 |
+
throw new IAE($msg);
|
329 |
+
}
|
330 |
+
|
331 |
+
public static function _apply_retries($value, array &$args, HandlerList $list)
|
332 |
+
{
|
333 |
+
if ($value) {
|
334 |
+
$decider = RetryMiddleware::createDefaultDecider($value);
|
335 |
+
$list->appendSign(Middleware::retry($decider), 'retry');
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
public static function _apply_credentials($value, array &$args)
|
340 |
+
{
|
341 |
+
if (is_callable($value)) {
|
342 |
+
return;
|
343 |
+
} elseif ($value instanceof CredentialsInterface) {
|
344 |
+
$args['credentials'] = CredentialProvider::fromCredentials($value);
|
345 |
+
} elseif (is_array($value)
|
346 |
+
&& isset($value['key'])
|
347 |
+
&& isset($value['secret'])
|
348 |
+
) {
|
349 |
+
$args['credentials'] = CredentialProvider::fromCredentials(
|
350 |
+
new Credentials(
|
351 |
+
$value['key'],
|
352 |
+
$value['secret'],
|
353 |
+
isset($value['token']) ? $value['token'] : null,
|
354 |
+
isset($value['expires']) ? $value['expires'] : null
|
355 |
+
)
|
356 |
+
);
|
357 |
+
} elseif ($value === false) {
|
358 |
+
$args['credentials'] = CredentialProvider::fromCredentials(
|
359 |
+
new Credentials('', '')
|
360 |
+
);
|
361 |
+
$args['config']['signature_version'] = 'anonymous';
|
362 |
+
} elseif ($value instanceof CacheInterface) {
|
363 |
+
$args['credentials'] = CredentialProvider::defaultProvider($args);
|
364 |
+
} else {
|
365 |
+
throw new IAE('Credentials must be an instance of '
|
366 |
+
. 'Aws\Credentials\CredentialsInterface, an associative '
|
367 |
+
. 'array that contains "key", "secret", and an optional "token" '
|
368 |
+
. 'key-value pairs, a credentials provider function, or false.');
|
369 |
+
}
|
370 |
+
}
|
371 |
+
|
372 |
+
public static function _apply_api_provider(callable $value, array &$args, HandlerList $list)
|
373 |
+
{
|
374 |
+
$api = new Service(
|
375 |
+
ApiProvider::resolve(
|
376 |
+
$value,
|
377 |
+
'api',
|
378 |
+
$args['service'],
|
379 |
+
$args['version']
|
380 |
+
),
|
381 |
+
$value
|
382 |
+
);
|
383 |
+
$args['api'] = $api;
|
384 |
+
$args['serializer'] = Service::createSerializer($api, $args['endpoint']);
|
385 |
+
$args['parser'] = Service::createParser($api);
|
386 |
+
$args['error_parser'] = Service::createErrorParser($api->getProtocol());
|
387 |
+
$list->prependBuild(Middleware::requestBuilder($args['serializer']), 'builder');
|
388 |
+
}
|
389 |
+
|
390 |
+
public static function _apply_endpoint_provider(callable $value, array &$args)
|
391 |
+
{
|
392 |
+
if (!isset($args['endpoint'])) {
|
393 |
+
// Invoke the endpoint provider and throw if it does not resolve.
|
394 |
+
$result = EndpointProvider::resolve($value, [
|
395 |
+
'service' => $args['service'],
|
396 |
+
'region' => $args['region'],
|
397 |
+
'scheme' => $args['scheme']
|
398 |
+
]);
|
399 |
+
|
400 |
+
$args['endpoint'] = $result['endpoint'];
|
401 |
+
|
402 |
+
if (isset($result['signatureVersion'])) {
|
403 |
+
$args['config']['signature_version'] = $result['signatureVersion'];
|
404 |
+
}
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
public static function _apply_debug($value, array &$args, HandlerList $list)
|
409 |
+
{
|
410 |
+
if ($value !== false) {
|
411 |
+
$list->interpose(new TraceMiddleware($value === true ? [] : $value));
|
412 |
+
}
|
413 |
+
}
|
414 |
+
|
415 |
+
public static function _apply_profile($_, array &$args)
|
416 |
+
{
|
417 |
+
$args['credentials'] = CredentialProvider::ini($args['profile']);
|
418 |
+
}
|
419 |
+
|
420 |
+
public static function _apply_validate($value, array &$args, HandlerList $list)
|
421 |
+
{
|
422 |
+
if ($value === true) {
|
423 |
+
$list->appendValidate(
|
424 |
+
Middleware::validation($args['api'], new Validator()),
|
425 |
+
'validation'
|
426 |
+
);
|
427 |
+
}
|
428 |
+
}
|
429 |
+
|
430 |
+
public static function _apply_handler($value, array &$args, HandlerList $list)
|
431 |
+
{
|
432 |
+
$list->setHandler($value);
|
433 |
+
}
|
434 |
+
|
435 |
+
public static function _default_handler(array &$args)
|
436 |
+
{
|
437 |
+
return new WrappedHttpHandler(
|
438 |
+
default_http_handler(),
|
439 |
+
$args['parser'],
|
440 |
+
$args['error_parser'],
|
441 |
+
$args['exception_class']
|
442 |
+
);
|
443 |
+
}
|
444 |
+
|
445 |
+
public static function _apply_http_handler($value, array &$args, HandlerList $list)
|
446 |
+
{
|
447 |
+
$args['handler'] = new WrappedHttpHandler(
|
448 |
+
$value,
|
449 |
+
$args['parser'],
|
450 |
+
$args['error_parser'],
|
451 |
+
$args['exception_class']
|
452 |
+
);
|
453 |
+
}
|
454 |
+
|
455 |
+
public static function _apply_user_agent($value, array &$args, HandlerList $list)
|
456 |
+
{
|
457 |
+
if (!is_array($value)) {
|
458 |
+
$value = [$value];
|
459 |
+
}
|
460 |
+
|
461 |
+
$value = array_map('strval', $value);
|
462 |
+
|
463 |
+
array_unshift($value, 'aws-sdk-php/' . Sdk::VERSION);
|
464 |
+
$args['ua_append'] = $value;
|
465 |
+
|
466 |
+
$list->appendBuild(static function (callable $handler) use ($value) {
|
467 |
+
return function (
|
468 |
+
CommandInterface $command,
|
469 |
+
RequestInterface $request
|
470 |
+
) use ($handler, $value) {
|
471 |
+
return $handler($command, $request->withHeader(
|
472 |
+
'User-Agent',
|
473 |
+
implode(' ', array_merge(
|
474 |
+
$value,
|
475 |
+
$request->getHeader('User-Agent')
|
476 |
+
))
|
477 |
+
));
|
478 |
+
};
|
479 |
+
});
|
480 |
+
}
|
481 |
+
|
482 |
+
public static function _apply_endpoint($value, array &$args, HandlerList $list)
|
483 |
+
{
|
484 |
+
$parts = parse_url($value);
|
485 |
+
if (empty($parts['scheme']) || empty($parts['host'])) {
|
486 |
+
throw new IAE(
|
487 |
+
'Endpoints must be full URIs and include a scheme and host'
|
488 |
+
);
|
489 |
+
}
|
490 |
+
|
491 |
+
$args['endpoint'] = $value;
|
492 |
+
}
|
493 |
+
|
494 |
+
public static function _default_endpoint_provider()
|
495 |
+
{
|
496 |
+
return EndpointProvider::defaultProvider();
|
497 |
+
}
|
498 |
+
|
499 |
+
public static function _default_signature_provider()
|
500 |
+
{
|
501 |
+
return SignatureProvider::defaultProvider();
|
502 |
+
}
|
503 |
+
|
504 |
+
public static function _default_signature_version(array &$args)
|
505 |
+
{
|
506 |
+
return isset($args['config']['signature_version'])
|
507 |
+
? $args['config']['signature_version']
|
508 |
+
: $args['api']->getSignatureVersion();
|
509 |
+
}
|
510 |
+
|
511 |
+
public static function _missing_version(array $args)
|
512 |
+
{
|
513 |
+
$service = isset($args['service']) ? $args['service'] : '';
|
514 |
+
$versions = ApiProvider::defaultProvider()->getVersions($service);
|
515 |
+
$versions = implode("\n", array_map(function ($v) {
|
516 |
+
return "* \"$v\"";
|
517 |
+
}, $versions)) ?: '* (none found)';
|
518 |
+
|
519 |
+
return <<<EOT
|
520 |
+
A "version" configuration value is required. Specifying a version constraint
|
521 |
+
ensures that your code will not be affected by a breaking change made to the
|
522 |
+
service. For example, when using Amazon S3, you can lock your API version to
|
523 |
+
"2006-03-01".
|
524 |
+
|
525 |
+
Your build of the SDK has the following version(s) of "{$service}": {$versions}
|
526 |
+
|
527 |
+
You may provide "latest" to the "version" configuration value to utilize the
|
528 |
+
most recent available API version that your client's API provider can find.
|
529 |
+
Note: Using 'latest' in a production application is not recommended.
|
530 |
+
|
531 |
+
A list of available API versions can be found on each client's API documentation
|
532 |
+
page: http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html. If you are
|
533 |
+
unable to load a specific API version, then you may need to update your copy of
|
534 |
+
the SDK.
|
535 |
+
EOT;
|
536 |
+
}
|
537 |
+
|
538 |
+
public static function _missing_region(array $args)
|
539 |
+
{
|
540 |
+
$service = isset($args['service']) ? $args['service'] : '';
|
541 |
+
|
542 |
+
return <<<EOT
|
543 |
+
A "region" configuration value is required for the "{$service}" service
|
544 |
+
(e.g., "us-west-2"). A list of available public regions and endpoints can be
|
545 |
+
found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
|
546 |
+
EOT;
|
547 |
+
}
|
548 |
+
}
|
includes/aws/Aws/CloudFront/CloudFrontClient.php
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\CloudFront;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **Amazon CloudFront** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result createCloudFrontOriginAccessIdentity(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise createCloudFrontOriginAccessIdentityAsync(array $args = [])
|
11 |
+
* @method \Aws\Result createDistribution(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise createDistributionAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createInvalidation(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createInvalidationAsync(array $args = [])
|
15 |
+
* @method \Aws\Result createStreamingDistribution(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise createStreamingDistributionAsync(array $args = [])
|
17 |
+
* @method \Aws\Result deleteCloudFrontOriginAccessIdentity(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise deleteCloudFrontOriginAccessIdentityAsync(array $args = [])
|
19 |
+
* @method \Aws\Result deleteDistribution(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise deleteDistributionAsync(array $args = [])
|
21 |
+
* @method \Aws\Result deleteStreamingDistribution(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise deleteStreamingDistributionAsync(array $args = [])
|
23 |
+
* @method \Aws\Result getCloudFrontOriginAccessIdentity(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityAsync(array $args = [])
|
25 |
+
* @method \Aws\Result getCloudFrontOriginAccessIdentityConfig(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityConfigAsync(array $args = [])
|
27 |
+
* @method \Aws\Result getDistribution(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise getDistributionAsync(array $args = [])
|
29 |
+
* @method \Aws\Result getDistributionConfig(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise getDistributionConfigAsync(array $args = [])
|
31 |
+
* @method \Aws\Result getInvalidation(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise getInvalidationAsync(array $args = [])
|
33 |
+
* @method \Aws\Result getStreamingDistribution(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise getStreamingDistributionAsync(array $args = [])
|
35 |
+
* @method \Aws\Result getStreamingDistributionConfig(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise getStreamingDistributionConfigAsync(array $args = [])
|
37 |
+
* @method \Aws\Result listCloudFrontOriginAccessIdentities(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise listCloudFrontOriginAccessIdentitiesAsync(array $args = [])
|
39 |
+
* @method \Aws\Result listDistributions(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise listDistributionsAsync(array $args = [])
|
41 |
+
* @method \Aws\Result listDistributionsByWebACLId(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise listDistributionsByWebACLIdAsync(array $args = [])
|
43 |
+
* @method \Aws\Result listInvalidations(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise listInvalidationsAsync(array $args = [])
|
45 |
+
* @method \Aws\Result listStreamingDistributions(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise listStreamingDistributionsAsync(array $args = [])
|
47 |
+
* @method \Aws\Result updateCloudFrontOriginAccessIdentity(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise updateCloudFrontOriginAccessIdentityAsync(array $args = [])
|
49 |
+
* @method \Aws\Result updateDistribution(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise updateDistributionAsync(array $args = [])
|
51 |
+
* @method \Aws\Result updateStreamingDistribution(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise updateStreamingDistributionAsync(array $args = [])
|
53 |
+
*/
|
54 |
+
class CloudFrontClient extends AwsClient
|
55 |
+
{
|
56 |
+
/**
|
57 |
+
* Create a signed Amazon CloudFront URL.
|
58 |
+
*
|
59 |
+
* This method accepts an array of configuration options:
|
60 |
+
*
|
61 |
+
* - url: (string) URL of the resource being signed (can include query
|
62 |
+
* string and wildcards). For example: rtmp://s5c39gqb8ow64r.cloudfront.net/videos/mp3_name.mp3
|
63 |
+
* http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
|
64 |
+
* - policy: (string) JSON policy. Use this option when creating a signed
|
65 |
+
* URL for a custom policy.
|
66 |
+
* - expires: (int) UTC Unix timestamp used when signing with a canned
|
67 |
+
* policy. Not required when passing a custom 'policy' option.
|
68 |
+
* - key_pair_id: (string) The ID of the key pair used to sign CloudFront
|
69 |
+
* URLs for private distributions.
|
70 |
+
* - private_key: (string) The filepath ot the private key used to sign
|
71 |
+
* CloudFront URLs for private distributions.
|
72 |
+
*
|
73 |
+
* @param array $options Array of configuration options used when signing
|
74 |
+
*
|
75 |
+
* @return string Signed URL with authentication parameters
|
76 |
+
* @throws \InvalidArgumentException if url, key_pair_id, or private_key
|
77 |
+
* were not specified.
|
78 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
79 |
+
*/
|
80 |
+
public function getSignedUrl(array $options)
|
81 |
+
{
|
82 |
+
foreach (['url', 'key_pair_id', 'private_key'] as $required) {
|
83 |
+
if (!isset($options[$required])) {
|
84 |
+
throw new \InvalidArgumentException("$required is required");
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
$urlSigner = new UrlSigner(
|
89 |
+
$options['key_pair_id'],
|
90 |
+
$options['private_key']
|
91 |
+
);
|
92 |
+
|
93 |
+
return $urlSigner->getSignedUrl(
|
94 |
+
$options['url'],
|
95 |
+
isset($options['expires']) ? $options['expires'] : null,
|
96 |
+
isset($options['policy']) ? $options['policy'] : null
|
97 |
+
);
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Create a signed Amazon CloudFront cookie.
|
102 |
+
*
|
103 |
+
* This method accepts an array of configuration options:
|
104 |
+
*
|
105 |
+
* - url: (string) URL of the resource being signed (can include query
|
106 |
+
* string and wildcards). For example: http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
|
107 |
+
* - policy: (string) JSON policy. Use this option when creating a signed
|
108 |
+
* URL for a custom policy.
|
109 |
+
* - expires: (int) UTC Unix timestamp used when signing with a canned
|
110 |
+
* policy. Not required when passing a custom 'policy' option.
|
111 |
+
* - key_pair_id: (string) The ID of the key pair used to sign CloudFront
|
112 |
+
* URLs for private distributions.
|
113 |
+
* - private_key: (string) The filepath ot the private key used to sign
|
114 |
+
* CloudFront URLs for private distributions.
|
115 |
+
*
|
116 |
+
* @param array $options Array of configuration options used when signing
|
117 |
+
*
|
118 |
+
* @return array Key => value pairs of signed cookies to set
|
119 |
+
* @throws \InvalidArgumentException if url, key_pair_id, or private_key
|
120 |
+
* were not specified.
|
121 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
122 |
+
*/
|
123 |
+
public function getSignedCookie(array $options)
|
124 |
+
{
|
125 |
+
foreach (['key_pair_id', 'private_key'] as $required) {
|
126 |
+
if (!isset($options[$required])) {
|
127 |
+
throw new \InvalidArgumentException("$required is required");
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
$cookieSigner = new CookieSigner(
|
132 |
+
$options['key_pair_id'],
|
133 |
+
$options['private_key']
|
134 |
+
);
|
135 |
+
|
136 |
+
return $cookieSigner->getSignedCookie(
|
137 |
+
isset($options['url']) ? $options['url'] : null,
|
138 |
+
isset($options['expires']) ? $options['expires'] : null,
|
139 |
+
isset($options['policy']) ? $options['policy'] : null
|
140 |
+
);
|
141 |
+
}
|
142 |
+
}
|
includes/aws/Aws/CloudFront/CookieSigner.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\CloudFront;
|
3 |
+
|
4 |
+
class CookieSigner
|
5 |
+
{
|
6 |
+
/** @var Signer */
|
7 |
+
private $signer;
|
8 |
+
|
9 |
+
private static $schemes = [
|
10 |
+
'http' => true,
|
11 |
+
'https' => true,
|
12 |
+
];
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param $keyPairId string ID of the key pair
|
16 |
+
* @param $privateKey string Path to the private key used for signing
|
17 |
+
*
|
18 |
+
* @throws \RuntimeException if the openssl extension is missing
|
19 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
20 |
+
*/
|
21 |
+
public function __construct($keyPairId, $privateKey)
|
22 |
+
{
|
23 |
+
$this->signer = new Signer($keyPairId, $privateKey);
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Create a signed Amazon CloudFront Cookie.
|
28 |
+
*
|
29 |
+
* @param string $url URL to sign (can include query string
|
30 |
+
* and wildcards). Not required
|
31 |
+
* when passing a custom $policy.
|
32 |
+
* @param string|integer|null $expires UTC Unix timestamp used when signing
|
33 |
+
* with a canned policy. Not required
|
34 |
+
* when passing a custom $policy.
|
35 |
+
* @param string $policy JSON policy. Use this option when
|
36 |
+
* creating a signed cookie for a custom
|
37 |
+
* policy.
|
38 |
+
*
|
39 |
+
* @return array The authenticated cookie parameters
|
40 |
+
* @throws \InvalidArgumentException if the URL provided is invalid
|
41 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
|
42 |
+
*/
|
43 |
+
public function getSignedCookie($url = null, $expires = null, $policy = null)
|
44 |
+
{
|
45 |
+
if ($url) {
|
46 |
+
$this->validateUrl($url);
|
47 |
+
}
|
48 |
+
|
49 |
+
$cookieParameters = [];
|
50 |
+
$signature = $this->signer->getSignature($url, $expires, $policy);
|
51 |
+
foreach ($signature as $key => $value) {
|
52 |
+
$cookieParameters["CloudFront-$key"] = $value;
|
53 |
+
}
|
54 |
+
|
55 |
+
return $cookieParameters;
|
56 |
+
}
|
57 |
+
|
58 |
+
private function validateUrl($url)
|
59 |
+
{
|
60 |
+
$scheme = str_replace('*', '', explode('://', $url)[0]);
|
61 |
+
if (empty(self::$schemes[strtolower($scheme)])) {
|
62 |
+
throw new \InvalidArgumentException('Invalid or missing URI scheme');
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
includes/aws/Aws/CloudFront/Exception/CloudFrontException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\CloudFront\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the Amazon CloudFront service.
|
8 |
+
*/
|
9 |
+
class CloudFrontException extends AwsException {}
|
includes/aws/Aws/CloudFront/Signer.php
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\CloudFront;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* @internal
|
6 |
+
*/
|
7 |
+
class Signer
|
8 |
+
{
|
9 |
+
private $keyPairId;
|
10 |
+
private $pk;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A signer for creating the signature values used in CloudFront signed URLs
|
14 |
+
* and signed cookies.
|
15 |
+
*
|
16 |
+
* @param $keyPairId string ID of the key pair
|
17 |
+
* @param $privateKey string Path to the private key used for signing
|
18 |
+
*
|
19 |
+
* @throws \RuntimeException if the openssl extension is missing
|
20 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
21 |
+
*/
|
22 |
+
public function __construct($keyPairId, $privateKey)
|
23 |
+
{
|
24 |
+
if (!extension_loaded('openssl')) {
|
25 |
+
//@codeCoverageIgnoreStart
|
26 |
+
throw new \RuntimeException('The openssl extension is required to '
|
27 |
+
. 'sign CloudFront urls.');
|
28 |
+
//@codeCoverageIgnoreEnd
|
29 |
+
}
|
30 |
+
|
31 |
+
$this->keyPairId = $keyPairId;
|
32 |
+
|
33 |
+
if (!file_exists($privateKey)) {
|
34 |
+
throw new \InvalidArgumentException("PK file not found: $privateKey");
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->pk = file_get_contents($privateKey);
|
38 |
+
}
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Create the values used to construct signed URLs and cookies.
|
43 |
+
*
|
44 |
+
* @param string $resource The CloudFront resource to which
|
45 |
+
* this signature will grant access.
|
46 |
+
* Not used when a custom policy is
|
47 |
+
* provided.
|
48 |
+
* @param string|integer|null $expires UTC Unix timestamp used when
|
49 |
+
* signing with a canned policy.
|
50 |
+
* Not required when passing a
|
51 |
+
* custom $policy.
|
52 |
+
* @param string $policy JSON policy. Use this option when
|
53 |
+
* creating a signature for a custom
|
54 |
+
* policy.
|
55 |
+
*
|
56 |
+
* @return array The values needed to construct a signed URL or cookie
|
57 |
+
* @throws \InvalidArgumentException when not provided either a policy or a
|
58 |
+
* resource and a expires
|
59 |
+
*
|
60 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
|
61 |
+
*/
|
62 |
+
public function getSignature($resource = null, $expires = null, $policy = null)
|
63 |
+
{
|
64 |
+
$signatureHash = [];
|
65 |
+
if ($policy) {
|
66 |
+
$policy = preg_replace('/\s/s', '', $policy);
|
67 |
+
$signatureHash['Policy'] = $this->encode($policy);
|
68 |
+
} elseif ($resource && $expires) {
|
69 |
+
$policy = $this->createCannedPolicy($resource, $expires);
|
70 |
+
$signatureHash['Expires'] = $expires;
|
71 |
+
} else {
|
72 |
+
throw new \InvalidArgumentException('Either a policy or a resource'
|
73 |
+
. ' and an expiration time must be provided.');
|
74 |
+
}
|
75 |
+
|
76 |
+
$signatureHash['Signature'] = $this->encode($this->sign($policy));
|
77 |
+
$signatureHash['Key-Pair-Id'] = $this->keyPairId;
|
78 |
+
|
79 |
+
return $signatureHash;
|
80 |
+
}
|
81 |
+
|
82 |
+
private function createCannedPolicy($resource, $expiration)
|
83 |
+
{
|
84 |
+
return json_encode([
|
85 |
+
'Statement' => [
|
86 |
+
[
|
87 |
+
'Resource' => $resource,
|
88 |
+
'Condition' => [
|
89 |
+
'DateLessThan' => ['AWS:EpochTime' => $expiration],
|
90 |
+
],
|
91 |
+
],
|
92 |
+
],
|
93 |
+
], JSON_UNESCAPED_SLASHES);
|
94 |
+
}
|
95 |
+
|
96 |
+
private function sign($policy)
|
97 |
+
{
|
98 |
+
$signature = '';
|
99 |
+
openssl_sign($policy, $signature, $this->pk);
|
100 |
+
|
101 |
+
return $signature;
|
102 |
+
}
|
103 |
+
|
104 |
+
private function encode($policy)
|
105 |
+
{
|
106 |
+
return strtr(base64_encode($policy), '+=/', '-_~');
|
107 |
+
}
|
108 |
+
}
|
includes/aws/Aws/CloudFront/UrlSigner.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\CloudFront;
|
3 |
+
|
4 |
+
use GuzzleHttp\Psr7;
|
5 |
+
use GuzzleHttp\Psr7\Uri;
|
6 |
+
use Psr\Http\Message\UriInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Creates signed URLs for Amazon CloudFront resources.
|
10 |
+
*/
|
11 |
+
class UrlSigner
|
12 |
+
{
|
13 |
+
private $signer;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param $keyPairId string ID of the key pair
|
17 |
+
* @param $privateKey string Path to the private key used for signing
|
18 |
+
*
|
19 |
+
* @throws \RuntimeException if the openssl extension is missing
|
20 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
21 |
+
*/
|
22 |
+
public function __construct($keyPairId, $privateKey)
|
23 |
+
{
|
24 |
+
$this->signer = new Signer($keyPairId, $privateKey);
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Create a signed Amazon CloudFront URL.
|
29 |
+
*
|
30 |
+
* Keep in mind that URLs meant for use in media/flash players may have
|
31 |
+
* different requirements for URL formats (e.g. some require that the
|
32 |
+
* extension be removed, some require the file name to be prefixed
|
33 |
+
* - mp4:<path>, some require you to add "/cfx/st" into your URL).
|
34 |
+
*
|
35 |
+
* @param string $url URL to sign (can include query
|
36 |
+
* string string and wildcards)
|
37 |
+
* @param string|integer|null $expires UTC Unix timestamp used when signing
|
38 |
+
* with a canned policy. Not required
|
39 |
+
* when passing a custom $policy.
|
40 |
+
* @param string $policy JSON policy. Use this option when
|
41 |
+
* creating a signed URL for a custom
|
42 |
+
* policy.
|
43 |
+
*
|
44 |
+
* @return string The file URL with authentication parameters
|
45 |
+
* @throws \InvalidArgumentException if the URL provided is invalid
|
46 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
47 |
+
*/
|
48 |
+
public function getSignedUrl($url, $expires = null, $policy = null)
|
49 |
+
{
|
50 |
+
// Determine the scheme of the url
|
51 |
+
$urlSections = explode('://', $url);
|
52 |
+
|
53 |
+
if (count($urlSections) < 2) {
|
54 |
+
throw new \InvalidArgumentException("Invalid URL: {$url}");
|
55 |
+
}
|
56 |
+
|
57 |
+
// Get the real scheme by removing wildcards from the scheme
|
58 |
+
$scheme = str_replace('*', '', $urlSections[0]);
|
59 |
+
$uri = new Uri($scheme . '://' . $urlSections[1]);
|
60 |
+
$query = Psr7\parse_query($uri->getQuery(), PHP_QUERY_RFC3986);
|
61 |
+
$signature = $this->signer->getSignature(
|
62 |
+
$this->createResource($scheme, (string) $uri),
|
63 |
+
$expires,
|
64 |
+
$policy
|
65 |
+
);
|
66 |
+
$uri = $uri->withQuery(
|
67 |
+
http_build_query($query + $signature, null, '&', PHP_QUERY_RFC3986)
|
68 |
+
);
|
69 |
+
|
70 |
+
return $scheme === 'rtmp'
|
71 |
+
? $this->createRtmpUrl($uri)
|
72 |
+
: (string) $uri;
|
73 |
+
}
|
74 |
+
|
75 |
+
private function createRtmpUrl(UriInterface $uri)
|
76 |
+
{
|
77 |
+
// Use a relative URL when creating Flash player URLs
|
78 |
+
$result = ltrim($uri->getPath(), '/');
|
79 |
+
|
80 |
+
if ($query = $uri->getQuery()) {
|
81 |
+
$result .= '?' . $query;
|
82 |
+
}
|
83 |
+
|
84 |
+
return $result;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @param $scheme
|
89 |
+
* @param $url
|
90 |
+
*
|
91 |
+
* @return string
|
92 |
+
*/
|
93 |
+
private function createResource($scheme, $url)
|
94 |
+
{
|
95 |
+
switch ($scheme) {
|
96 |
+
case 'http':
|
97 |
+
case 'http*':
|
98 |
+
case 'https':
|
99 |
+
return $url;
|
100 |
+
case 'rtmp':
|
101 |
+
$parts = parse_url($url);
|
102 |
+
$pathParts = pathinfo($parts['path']);
|
103 |
+
$resource = ltrim(
|
104 |
+
$pathParts['dirname'] . '/' . $pathParts['basename'],
|
105 |
+
'/'
|
106 |
+
);
|
107 |
+
|
108 |
+
// Add a query string if present.
|
109 |
+
if (isset($parts['query'])) {
|
110 |
+
$resource .= "?{$parts['query']}";
|
111 |
+
}
|
112 |
+
|
113 |
+
return $resource;
|
114 |
+
}
|
115 |
+
|
116 |
+
throw new \InvalidArgumentException("Invalid URI scheme: {$scheme}. "
|
117 |
+
. "Scheme must be one of: http, https, or rtmp");
|
118 |
+
}
|
119 |
+
}
|
includes/aws/Aws/Command.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* AWS command object.
|
6 |
+
*/
|
7 |
+
class Command implements CommandInterface
|
8 |
+
{
|
9 |
+
use HasDataTrait;
|
10 |
+
|
11 |
+
/** @var string */
|
12 |
+
private $name;
|
13 |
+
|
14 |
+
/** @var HandlerList */
|
15 |
+
private $handlerList;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Accepts an associative array of command options, including:
|
19 |
+
*
|
20 |
+
* - @http: (array) Associative array of transfer options.
|
21 |
+
*
|
22 |
+
* @param string $name Name of the command
|
23 |
+
* @param array $args Arguments to pass to the command
|
24 |
+
* @param HandlerList $list Handler list
|
25 |
+
*/
|
26 |
+
public function __construct($name, array $args = [], HandlerList $list = null)
|
27 |
+
{
|
28 |
+
$this->name = $name;
|
29 |
+
$this->data = $args;
|
30 |
+
$this->handlerList = $list ?: new HandlerList();
|
31 |
+
|
32 |
+
if (!isset($this->data['@http'])) {
|
33 |
+
$this->data['@http'] = [];
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getName()
|
38 |
+
{
|
39 |
+
return $this->name;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function hasParam($name)
|
43 |
+
{
|
44 |
+
return array_key_exists($name, $this->data);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getHandlerList()
|
48 |
+
{
|
49 |
+
return $this->handlerList;
|
50 |
+
}
|
51 |
+
|
52 |
+
/** @deprecated */
|
53 |
+
public function get($name)
|
54 |
+
{
|
55 |
+
return $this[$name];
|
56 |
+
}
|
57 |
+
}
|
includes/aws/Aws/CommandInterface.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* A command object encapsulates the input parameters used to control the
|
6 |
+
* creation of a HTTP request and processing of a HTTP response.
|
7 |
+
*
|
8 |
+
* Using the toArray() method will return the input parameters of the command
|
9 |
+
* as an associative array.
|
10 |
+
*/
|
11 |
+
interface CommandInterface extends \ArrayAccess, \Countable, \IteratorAggregate
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Converts the command parameters to an array
|
15 |
+
*
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
public function toArray();
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Get the name of the command
|
22 |
+
*
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
+
public function getName();
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Check if the command has a parameter by name.
|
29 |
+
*
|
30 |
+
* @param string $name Name of the parameter to check
|
31 |
+
*
|
32 |
+
* @return bool
|
33 |
+
*/
|
34 |
+
public function hasParam($name);
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Get the handler list used to transfer the command.
|
38 |
+
*
|
39 |
+
* @return HandlerList
|
40 |
+
*/
|
41 |
+
public function getHandlerList();
|
42 |
+
}
|
includes/aws/Aws/CommandPool.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
5 |
+
use GuzzleHttp\Promise\EachPromise;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Sends and iterator of commands concurrently using a capped pool size.
|
9 |
+
*
|
10 |
+
* The pool will read command objects from an iterator until it is cancelled or
|
11 |
+
* until the iterator is consumed.
|
12 |
+
*/
|
13 |
+
class CommandPool implements PromisorInterface
|
14 |
+
{
|
15 |
+
/** @var EachPromise */
|
16 |
+
private $each;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* The CommandPool constructor accepts a hash of configuration options:
|
20 |
+
*
|
21 |
+
* - concurrency: (callable|int) Maximum number of commands to execute
|
22 |
+
* concurrently. Provide a function to resize the pool dynamically. The
|
23 |
+
* function will be provided the current number of pending requests and
|
24 |
+
* is expected to return an integer representing the new pool size limit.
|
25 |
+
* - before: (callable) function to invoke before sending each command. The
|
26 |
+
* before function accepts the command and the key of the iterator of the
|
27 |
+
* command. You can mutate the command as needed in the before function
|
28 |
+
* before sending the command.
|
29 |
+
* - fulfilled: (callable) Function to invoke when a promise is fulfilled.
|
30 |
+
* The function is provided the result object, id of the iterator that the
|
31 |
+
* result came from, and the aggregate promise that can be resolved/rejected
|
32 |
+
* if you need to short-circuit the pool.
|
33 |
+
* - rejected: (callable) Function to invoke when a promise is rejected.
|
34 |
+
* The function is provided an AwsException object, id of the iterator that
|
35 |
+
* the exception came from, and the aggregate promise that can be
|
36 |
+
* resolved/rejected if you need to short-circuit the pool.
|
37 |
+
*
|
38 |
+
* @param AwsClientInterface $client Client used to execute commands.
|
39 |
+
* @param array|\Iterator $commands Iterable that yields commands.
|
40 |
+
* @param array $config Associative array of options.
|
41 |
+
*/
|
42 |
+
public function __construct(
|
43 |
+
AwsClientInterface $client,
|
44 |
+
$commands,
|
45 |
+
array $config = []
|
46 |
+
) {
|
47 |
+
if (!isset($config['concurrency'])) {
|
48 |
+
$config['concurrency'] = 25;
|
49 |
+
}
|
50 |
+
|
51 |
+
$before = $this->getBefore($config);
|
52 |
+
$mapFn = function ($commands) use ($client, $before) {
|
53 |
+
foreach ($commands as $key => $command) {
|
54 |
+
if (!($command instanceof CommandInterface)) {
|
55 |
+
throw new \InvalidArgumentException('Each value yielded by '
|
56 |
+
. 'the iterator must be an Aws\CommandInterface.');
|
57 |
+
}
|
58 |
+
if ($before) {
|
59 |
+
$before($command, $key);
|
60 |
+
}
|
61 |
+
yield $client->executeAsync($command);
|
62 |
+
}
|
63 |
+
};
|
64 |
+
|
65 |
+
$this->each = new EachPromise($mapFn($commands), $config);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @return \GuzzleHttp\Promise\PromiseInterface
|
70 |
+
*/
|
71 |
+
public function promise()
|
72 |
+
{
|
73 |
+
return $this->each->promise();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Executes a pool synchronously and aggregates the results of the pool
|
78 |
+
* into an indexed array in the same order as the passed in array.
|
79 |
+
*
|
80 |
+
* @param AwsClientInterface $client Client used to execute commands.
|
81 |
+
* @param mixed $commands Iterable that yields commands.
|
82 |
+
* @param array $config Configuration options.
|
83 |
+
*
|
84 |
+
* @return array
|
85 |
+
* @see \Aws\CommandPool::__construct for available configuration options.
|
86 |
+
*/
|
87 |
+
public static function batch(
|
88 |
+
AwsClientInterface $client,
|
89 |
+
$commands,
|
90 |
+
array $config = []
|
91 |
+
) {
|
92 |
+
$results = [];
|
93 |
+
self::cmpCallback($config, 'fulfilled', $results);
|
94 |
+
self::cmpCallback($config, 'rejected', $results);
|
95 |
+
|
96 |
+
return (new self($client, $commands, $config))
|
97 |
+
->promise()
|
98 |
+
->then(static function () use (&$results) {
|
99 |
+
ksort($results);
|
100 |
+
return $results;
|
101 |
+
})
|
102 |
+
->wait();
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @return callable
|
107 |
+
*/
|
108 |
+
private function getBefore(array $config)
|
109 |
+
{
|
110 |
+
if (!isset($config['before'])) {
|
111 |
+
return null;
|
112 |
+
}
|
113 |
+
|
114 |
+
if (is_callable($config['before'])) {
|
115 |
+
return $config['before'];
|
116 |
+
}
|
117 |
+
|
118 |
+
throw new \InvalidArgumentException('before must be callable');
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Adds an onFulfilled or onRejected callback that aggregates results into
|
123 |
+
* an array. If a callback is already present, it is replaced with the
|
124 |
+
* composed function.
|
125 |
+
*
|
126 |
+
* @param array $config
|
127 |
+
* @param $name
|
128 |
+
* @param array $results
|
129 |
+
*/
|
130 |
+
private static function cmpCallback(array &$config, $name, array &$results)
|
131 |
+
{
|
132 |
+
if (!isset($config[$name])) {
|
133 |
+
$config[$name] = function ($v, $k) use (&$results) {
|
134 |
+
$results[$k] = $v;
|
135 |
+
};
|
136 |
+
} else {
|
137 |
+
$currentFn = $config[$name];
|
138 |
+
$config[$name] = function ($v, $k) use (&$results, $currentFn) {
|
139 |
+
$currentFn($v, $k);
|
140 |
+
$results[$k] = $v;
|
141 |
+
};
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
includes/aws/Aws/ConfigService/ConfigServiceClient.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\ConfigService;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with AWS Config.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result deleteConfigRule(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise deleteConfigRuleAsync(array $args = [])
|
11 |
+
* @method \Aws\Result deleteDeliveryChannel(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise deleteDeliveryChannelAsync(array $args = [])
|
13 |
+
* @method \Aws\Result deliverConfigSnapshot(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise deliverConfigSnapshotAsync(array $args = [])
|
15 |
+
* @method \Aws\Result describeComplianceByConfigRule(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise describeComplianceByConfigRuleAsync(array $args = [])
|
17 |
+
* @method \Aws\Result describeComplianceByResource(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise describeComplianceByResourceAsync(array $args = [])
|
19 |
+
* @method \Aws\Result describeConfigRuleEvaluationStatus(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise describeConfigRuleEvaluationStatusAsync(array $args = [])
|
21 |
+
* @method \Aws\Result describeConfigRules(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise describeConfigRulesAsync(array $args = [])
|
23 |
+
* @method \Aws\Result describeConfigurationRecorderStatus(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise describeConfigurationRecorderStatusAsync(array $args = [])
|
25 |
+
* @method \Aws\Result describeConfigurationRecorders(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise describeConfigurationRecordersAsync(array $args = [])
|
27 |
+
* @method \Aws\Result describeDeliveryChannelStatus(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise describeDeliveryChannelStatusAsync(array $args = [])
|
29 |
+
* @method \Aws\Result describeDeliveryChannels(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise describeDeliveryChannelsAsync(array $args = [])
|
31 |
+
* @method \Aws\Result getComplianceDetailsByConfigRule(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise getComplianceDetailsByConfigRuleAsync(array $args = [])
|
33 |
+
* @method \Aws\Result getComplianceDetailsByResource(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise getComplianceDetailsByResourceAsync(array $args = [])
|
35 |
+
* @method \Aws\Result getComplianceSummaryByConfigRule(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise getComplianceSummaryByConfigRuleAsync(array $args = [])
|
37 |
+
* @method \Aws\Result getComplianceSummaryByResourceType(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise getComplianceSummaryByResourceTypeAsync(array $args = [])
|
39 |
+
* @method \Aws\Result getResourceConfigHistory(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise getResourceConfigHistoryAsync(array $args = [])
|
41 |
+
* @method \Aws\Result listDiscoveredResources(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise listDiscoveredResourcesAsync(array $args = [])
|
43 |
+
* @method \Aws\Result putConfigRule(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise putConfigRuleAsync(array $args = [])
|
45 |
+
* @method \Aws\Result putConfigurationRecorder(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise putConfigurationRecorderAsync(array $args = [])
|
47 |
+
* @method \Aws\Result putDeliveryChannel(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise putDeliveryChannelAsync(array $args = [])
|
49 |
+
* @method \Aws\Result putEvaluations(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise putEvaluationsAsync(array $args = [])
|
51 |
+
* @method \Aws\Result startConfigurationRecorder(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise startConfigurationRecorderAsync(array $args = [])
|
53 |
+
* @method \Aws\Result stopConfigurationRecorder(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise stopConfigurationRecorderAsync(array $args = [])
|
55 |
+
*/
|
56 |
+
class ConfigServiceClient extends AwsClient {}
|
includes/aws/Aws/ConfigService/Exception/ConfigServiceException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\ConfigService\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the AWS Config service.
|
8 |
+
*/
|
9 |
+
class ConfigServiceException extends AwsException {}
|
includes/aws/Aws/Credentials/CredentialProvider.php
ADDED
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Credentials;
|
3 |
+
|
4 |
+
use Aws;
|
5 |
+
use Aws\CacheInterface;
|
6 |
+
use Aws\Exception\CredentialsException;
|
7 |
+
use GuzzleHttp\Promise;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Credential providers are functions that accept no arguments and return a
|
11 |
+
* promise that is fulfilled with an {@see \Aws\Credentials\CredentialsInterface}
|
12 |
+
* or rejected with an {@see \Aws\Exception\CredentialsException}.
|
13 |
+
*
|
14 |
+
* <code>
|
15 |
+
* use Aws\Credentials\CredentialProvider;
|
16 |
+
* $provider = CredentialProvider::defaultProvider();
|
17 |
+
* // Returns a CredentialsInterface or throws.
|
18 |
+
* $creds = $provider()->wait();
|
19 |
+
* </code>
|
20 |
+
*
|
21 |
+
* Credential providers can be composed to create credentials using conditional
|
22 |
+
* logic that can create different credentials in different environments. You
|
23 |
+
* can compose multiple providers into a single provider using
|
24 |
+
* {@see Aws\Credentials\CredentialProvider::chain}. This function accepts
|
25 |
+
* providers as variadic arguments and returns a new function that will invoke
|
26 |
+
* each provider until a successful set of credentials is returned.
|
27 |
+
*
|
28 |
+
* <code>
|
29 |
+
* // First try an INI file at this location.
|
30 |
+
* $a = CredentialProvider::ini(null, '/path/to/file.ini');
|
31 |
+
* // Then try an INI file at this location.
|
32 |
+
* $b = CredentialProvider::ini(null, '/path/to/other-file.ini');
|
33 |
+
* // Then try loading from envrionment variables.
|
34 |
+
* $c = CredentialProvider::env();
|
35 |
+
* // Combine the three providers together.
|
36 |
+
* $composed = CredentialProvider::chain($a, $b, $c);
|
37 |
+
* // Returns a promise that is fulfilled with credentials or throws.
|
38 |
+
* $promise = $composed();
|
39 |
+
* // Wait on the credentials to resolve.
|
40 |
+
* $creds = $promise->wait();
|
41 |
+
* </code>
|
42 |
+
*/
|
43 |
+
class CredentialProvider
|
44 |
+
{
|
45 |
+
const ENV_KEY = 'AWS_ACCESS_KEY_ID';
|
46 |
+
const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
|
47 |
+
const ENV_SESSION = 'AWS_SESSION_TOKEN';
|
48 |
+
const ENV_PROFILE = 'AWS_PROFILE';
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Create a default credential provider that first checks for environment
|
52 |
+
* variables, then checks for the "default" profile in ~/.aws/credentials,
|
53 |
+
* and finally checks for credentials using EC2 instance profile
|
54 |
+
* credentials.
|
55 |
+
*
|
56 |
+
* This provider is automatically wrapped in a memoize function that caches
|
57 |
+
* previously provided credentials.
|
58 |
+
*
|
59 |
+
* @param array $config Optional array of instance profile credentials
|
60 |
+
* provider options.
|
61 |
+
* @return callable
|
62 |
+
*/
|
63 |
+
public static function defaultProvider(array $config = [])
|
64 |
+
{
|
65 |
+
$instanceProfileProvider = self::instanceProfile($config);
|
66 |
+
if (isset($config['credentials'])
|
67 |
+
&& $config['credentials'] instanceof CacheInterface
|
68 |
+
) {
|
69 |
+
$instanceProfileProvider = self::cache(
|
70 |
+
$instanceProfileProvider,
|
71 |
+
$config['credentials']
|
72 |
+
);
|
73 |
+
}
|
74 |
+
|
75 |
+
return self::memoize(
|
76 |
+
self::chain(
|
77 |
+
self::env(),
|
78 |
+
self::ini(),
|
79 |
+
$instanceProfileProvider
|
80 |
+
)
|
81 |
+
);
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Create a credential provider function from a set of static credentials.
|
86 |
+
*
|
87 |
+
* @param CredentialsInterface $creds
|
88 |
+
*
|
89 |
+
* @return callable
|
90 |
+
*/
|
91 |
+
public static function fromCredentials(CredentialsInterface $creds)
|
92 |
+
{
|
93 |
+
$promise = Promise\promise_for($creds);
|
94 |
+
|
95 |
+
return function () use ($promise) {
|
96 |
+
return $promise;
|
97 |
+
};
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Creates an aggregate credentials provider that invokes the provided
|
102 |
+
* variadic providers one after the other until a provider returns
|
103 |
+
* credentials.
|
104 |
+
*
|
105 |
+
* @return callable
|
106 |
+
*/
|
107 |
+
public static function chain()
|
108 |
+
{
|
109 |
+
$links = func_get_args();
|
110 |
+
if (empty($links)) {
|
111 |
+
throw new \InvalidArgumentException('No providers in chain');
|
112 |
+
}
|
113 |
+
|
114 |
+
return function () use ($links) {
|
115 |
+
/** @var callable $parent */
|
116 |
+
$parent = array_shift($links);
|
117 |
+
$promise = $parent();
|
118 |
+
while ($next = array_shift($links)) {
|
119 |
+
$promise = $promise->otherwise($next);
|
120 |
+
}
|
121 |
+
return $promise;
|
122 |
+
};
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Wraps a credential provider and caches previously provided credentials.
|
127 |
+
*
|
128 |
+
* Ensures that cached credentials are refreshed when they expire.
|
129 |
+
*
|
130 |
+
* @param callable $provider Credentials provider function to wrap.
|
131 |
+
*
|
132 |
+
* @return callable
|
133 |
+
*/
|
134 |
+
public static function memoize(callable $provider)
|
135 |
+
{
|
136 |
+
return function () use ($provider) {
|
137 |
+
static $result;
|
138 |
+
static $isConstant;
|
139 |
+
|
140 |
+
// Constant credentials will be returned constantly.
|
141 |
+
if ($isConstant) {
|
142 |
+
return $result;
|
143 |
+
}
|
144 |
+
|
145 |
+
// Create the initial promise that will be used as the cached value
|
146 |
+
// until it expires.
|
147 |
+
if (null === $result) {
|
148 |
+
$result = $provider();
|
149 |
+
}
|
150 |
+
|
151 |
+
// Return credentials that could expire and refresh when needed.
|
152 |
+
return $result
|
153 |
+
->then(function (CredentialsInterface $creds) use ($provider, &$isConstant, &$result) {
|
154 |
+
// Determine if these are constant credentials.
|
155 |
+
if (!$creds->getExpiration()) {
|
156 |
+
$isConstant = true;
|
157 |
+
return $creds;
|
158 |
+
}
|
159 |
+
|
160 |
+
// Refresh expired credentials.
|
161 |
+
if (!$creds->isExpired()) {
|
162 |
+
return $creds;
|
163 |
+
}
|
164 |
+
// Refresh the result and forward the promise.
|
165 |
+
return $result = $provider();
|
166 |
+
});
|
167 |
+
};
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Wraps a credential provider and saves provided credentials in an
|
172 |
+
* instance of Aws\CacheInterface. Forwards calls when no credentials found
|
173 |
+
* in cache and updates cache with the results.
|
174 |
+
*
|
175 |
+
* Defaults to using a simple file-based cache when none provided.
|
176 |
+
*
|
177 |
+
* @param callable $provider Credentials provider function to wrap
|
178 |
+
* @param CacheInterface $cache (optional) Cache to store credentials
|
179 |
+
* @param string|null $cacheKey (optional) Cache key to use
|
180 |
+
*
|
181 |
+
* @return callable
|
182 |
+
*/
|
183 |
+
public static function cache(
|
184 |
+
callable $provider,
|
185 |
+
CacheInterface $cache,
|
186 |
+
$cacheKey = null
|
187 |
+
) {
|
188 |
+
$cacheKey = $cacheKey ?: 'aws_cached_credentials';
|
189 |
+
|
190 |
+
return function () use ($provider, $cache, $cacheKey) {
|
191 |
+
$found = $cache->get($cacheKey);
|
192 |
+
if ($found instanceof CredentialsInterface && !$found->isExpired()) {
|
193 |
+
return Promise\promise_for($found);
|
194 |
+
}
|
195 |
+
|
196 |
+
return $provider()
|
197 |
+
->then(function (CredentialsInterface $creds) use (
|
198 |
+
$cache,
|
199 |
+
$cacheKey
|
200 |
+
) {
|
201 |
+
$cache->set(
|
202 |
+
$cacheKey,
|
203 |
+
$creds,
|
204 |
+
null === $creds->getExpiration() ?
|
205 |
+
0 : $creds->getExpiration() - time()
|
206 |
+
);
|
207 |
+
|
208 |
+
return $creds;
|
209 |
+
});
|
210 |
+
};
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Provider that creates credentials from environment variables
|
215 |
+
* AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
|
216 |
+
*
|
217 |
+
* @return callable
|
218 |
+
*/
|
219 |
+
public static function env()
|
220 |
+
{
|
221 |
+
return function () {
|
222 |
+
// Use credentials from environment variables, if available
|
223 |
+
$key = getenv(self::ENV_KEY);
|
224 |
+
$secret = getenv(self::ENV_SECRET);
|
225 |
+
if ($key && $secret) {
|
226 |
+
return Promise\promise_for(
|
227 |
+
new Credentials($key, $secret, getenv(self::ENV_SESSION))
|
228 |
+
);
|
229 |
+
}
|
230 |
+
|
231 |
+
return self::reject('Could not find environment variable '
|
232 |
+
. 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET);
|
233 |
+
};
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Credential provider that creates credentials using instance profile
|
238 |
+
* credentials.
|
239 |
+
*
|
240 |
+
* @param array $config Array of configuration data.
|
241 |
+
*
|
242 |
+
* @return InstanceProfileProvider
|
243 |
+
* @see Aws\Credentials\InstanceProfileProvider for $config details.
|
244 |
+
*/
|
245 |
+
public static function instanceProfile(array $config = [])
|
246 |
+
{
|
247 |
+
return new InstanceProfileProvider($config);
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Credentials provider that creates credentials using an ini file stored
|
252 |
+
* in the current user's home directory.
|
253 |
+
*
|
254 |
+
* @param string|null $profile Profile to use. If not specified will use
|
255 |
+
* the "default" profile.
|
256 |
+
* @param string|null $filename If provided, uses a custom filename rather
|
257 |
+
* than looking in the home directory for the
|
258 |
+
*
|
259 |
+
* @return callable
|
260 |
+
*/
|
261 |
+
public static function ini($profile = null, $filename = null)
|
262 |
+
{
|
263 |
+
$filename = $filename ?: (self::getHomeDir() . '/.aws/credentials');
|
264 |
+
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
265 |
+
|
266 |
+
return function () use ($profile, $filename) {
|
267 |
+
if (!is_readable($filename)) {
|
268 |
+
return self::reject("Cannot read credentials from $filename");
|
269 |
+
}
|
270 |
+
$data = parse_ini_file($filename, true);
|
271 |
+
if ($data === false) {
|
272 |
+
return self::reject("Invalid credentials file: $filename");
|
273 |
+
}
|
274 |
+
if (!isset($data[$profile])) {
|
275 |
+
return self::reject("'$profile' not found in credentials file");
|
276 |
+
}
|
277 |
+
if (!isset($data[$profile]['aws_access_key_id'])
|
278 |
+
|| !isset($data[$profile]['aws_secret_access_key'])
|
279 |
+
) {
|
280 |
+
return self::reject("No credentials present in INI profile "
|
281 |
+
. "'$profile' ($filename)");
|
282 |
+
}
|
283 |
+
|
284 |
+
if (empty($data[$profile]['aws_session_token'])) {
|
285 |
+
$data[$profile]['aws_session_token']
|
286 |
+
= isset($data[$profile]['aws_security_token'])
|
287 |
+
? $data[$profile]['aws_security_token']
|
288 |
+
: null;
|
289 |
+
}
|
290 |
+
|
291 |
+
return Promise\promise_for(
|
292 |
+
new Credentials(
|
293 |
+
$data[$profile]['aws_access_key_id'],
|
294 |
+
$data[$profile]['aws_secret_access_key'],
|
295 |
+
$data[$profile]['aws_session_token']
|
296 |
+
)
|
297 |
+
);
|
298 |
+
};
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Gets the environment's HOME directory if available.
|
303 |
+
*
|
304 |
+
* @return null|string
|
305 |
+
*/
|
306 |
+
private static function getHomeDir()
|
307 |
+
{
|
308 |
+
// On Linux/Unix-like systems, use the HOME environment variable
|
309 |
+
if ($homeDir = getenv('HOME')) {
|
310 |
+
return $homeDir;
|
311 |
+
}
|
312 |
+
|
313 |
+
// Get the HOMEDRIVE and HOMEPATH values for Windows hosts
|
314 |
+
$homeDrive = getenv('HOMEDRIVE');
|
315 |
+
$homePath = getenv('HOMEPATH');
|
316 |
+
|
317 |
+
return ($homeDrive && $homePath) ? $homeDrive . $homePath : null;
|
318 |
+
}
|
319 |
+
|
320 |
+
private static function reject($msg)
|
321 |
+
{
|
322 |
+
return new Promise\RejectedPromise(new CredentialsException($msg));
|
323 |
+
}
|
324 |
+
}
|
includes/aws/Aws/Credentials/Credentials.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Credentials;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Basic implementation of the AWS Credentials interface that allows callers to
|
6 |
+
* pass in the AWS Access Key and AWS Secret Access Key in the constructor.
|
7 |
+
*/
|
8 |
+
class Credentials implements CredentialsInterface, \Serializable
|
9 |
+
{
|
10 |
+
private $key;
|
11 |
+
private $secret;
|
12 |
+
private $token;
|
13 |
+
private $expires;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Constructs a new BasicAWSCredentials object, with the specified AWS
|
17 |
+
* access key and AWS secret key
|
18 |
+
*
|
19 |
+
* @param string $key AWS access key ID
|
20 |
+
* @param string $secret AWS secret access key
|
21 |
+
* @param string $token Security token to use
|
22 |
+
* @param int $expires UNIX timestamp for when credentials expire
|
23 |
+
*/
|
24 |
+
public function __construct($key, $secret, $token = null, $expires = null)
|
25 |
+
{
|
26 |
+
$this->key = trim($key);
|
27 |
+
$this->secret = trim($secret);
|
28 |
+
$this->token = $token;
|
29 |
+
$this->expires = $expires;
|
30 |
+
}
|
31 |
+
|
32 |
+
public static function __set_state(array $state)
|
33 |
+
{
|
34 |
+
return new self(
|
35 |
+
$state['key'],
|
36 |
+
$state['secret'],
|
37 |
+
$state['token'],
|
38 |
+
$state['expires']
|
39 |
+
);
|
40 |
+
}
|
41 |
+
|
42 |
+
public function getAccessKeyId()
|
43 |
+
{
|
44 |
+
return $this->key;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getSecretKey()
|
48 |
+
{
|
49 |
+
return $this->secret;
|
50 |
+
}
|
51 |
+
|
52 |
+
public function getSecurityToken()
|
53 |
+
{
|
54 |
+
return $this->token;
|
55 |
+
}
|
56 |
+
|
57 |
+
public function getExpiration()
|
58 |
+
{
|
59 |
+
return $this->expires;
|
60 |
+
}
|
61 |
+
|
62 |
+
public function isExpired()
|
63 |
+
{
|
64 |
+
return $this->expires !== null && time() >= $this->expires;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function toArray()
|
68 |
+
{
|
69 |
+
return [
|
70 |
+
'key' => $this->key,
|
71 |
+
'secret' => $this->secret,
|
72 |
+
'token' => $this->token,
|
73 |
+
'expires' => $this->expires
|
74 |
+
];
|
75 |
+
}
|
76 |
+
|
77 |
+
public function serialize()
|
78 |
+
{
|
79 |
+
return json_encode($this->toArray());
|
80 |
+
}
|
81 |
+
|
82 |
+
public function unserialize($serialized)
|
83 |
+
{
|
84 |
+
$data = json_decode($serialized, true);
|
85 |
+
|
86 |
+
$this->key = $data['key'];
|
87 |
+
$this->secret = $data['secret'];
|
88 |
+
$this->token = $data['token'];
|
89 |
+
$this->expires = $data['expires'];
|
90 |
+
}
|
91 |
+
}
|
includes/aws/Aws/Credentials/CredentialsInterface.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Credentials;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Provides access to the AWS credentials used for accessing AWS services: AWS
|
6 |
+
* access key ID, secret access key, and security token. These credentials are
|
7 |
+
* used to securely sign requests to AWS services.
|
8 |
+
*/
|
9 |
+
interface CredentialsInterface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Returns the AWS access key ID for this credentials object.
|
13 |
+
*
|
14 |
+
* @return string
|
15 |
+
*/
|
16 |
+
public function getAccessKeyId();
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Returns the AWS secret access key for this credentials object.
|
20 |
+
*
|
21 |
+
* @return string
|
22 |
+
*/
|
23 |
+
public function getSecretKey();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Get the associated security token if available
|
27 |
+
*
|
28 |
+
* @return string|null
|
29 |
+
*/
|
30 |
+
public function getSecurityToken();
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Get the UNIX timestamp in which the credentials will expire
|
34 |
+
*
|
35 |
+
* @return int|null
|
36 |
+
*/
|
37 |
+
public function getExpiration();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Check if the credentials are expired
|
41 |
+
*
|
42 |
+
* @return bool
|
43 |
+
*/
|
44 |
+
public function isExpired();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Converts the credentials to an associative array.
|
48 |
+
*
|
49 |
+
* @return array
|
50 |
+
*/
|
51 |
+
public function toArray();
|
52 |
+
}
|
includes/aws/Aws/Credentials/InstanceProfileProvider.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Credentials;
|
3 |
+
|
4 |
+
use Aws\Exception\CredentialsException;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use GuzzleHttp\Psr7\Request;
|
7 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Credential provider that provides credentials from the EC2 metadata server.
|
12 |
+
*/
|
13 |
+
class InstanceProfileProvider
|
14 |
+
{
|
15 |
+
const SERVER_URI = 'http://169.254.169.254/latest/';
|
16 |
+
const CRED_PATH = 'meta-data/iam/security-credentials/';
|
17 |
+
|
18 |
+
/** @var string */
|
19 |
+
private $profile;
|
20 |
+
|
21 |
+
/** @var callable */
|
22 |
+
private $client;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The constructor accepts the following options:
|
26 |
+
*
|
27 |
+
* - timeout: Connection timeout, in seconds.
|
28 |
+
* - profile: Optional EC2 profile name, if known.
|
29 |
+
*
|
30 |
+
* @param array $config Configuration options.
|
31 |
+
*/
|
32 |
+
public function __construct(array $config = [])
|
33 |
+
{
|
34 |
+
$this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
|
35 |
+
$this->profile = isset($config['profile']) ? $config['profile'] : null;
|
36 |
+
$this->client = isset($config['client'])
|
37 |
+
? $config['client'] // internal use only
|
38 |
+
: \Aws\default_http_handler();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Loads instance profile credentials.
|
43 |
+
*
|
44 |
+
* @return PromiseInterface
|
45 |
+
*/
|
46 |
+
public function __invoke()
|
47 |
+
{
|
48 |
+
return Promise\coroutine(function () {
|
49 |
+
if (!$this->profile) {
|
50 |
+
$this->profile = (yield $this->request(self::CRED_PATH));
|
51 |
+
}
|
52 |
+
$json = (yield $this->request(self::CRED_PATH . $this->profile));
|
53 |
+
$result = $this->decodeResult($json);
|
54 |
+
yield new Credentials(
|
55 |
+
$result['AccessKeyId'],
|
56 |
+
$result['SecretAccessKey'],
|
57 |
+
$result['Token'],
|
58 |
+
strtotime($result['Expiration'])
|
59 |
+
);
|
60 |
+
});
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @param string $url
|
65 |
+
* @return PromiseInterface Returns a promise that is fulfilled with the
|
66 |
+
* body of the response as a string.
|
67 |
+
*/
|
68 |
+
private function request($url)
|
69 |
+
{
|
70 |
+
$fn = $this->client;
|
71 |
+
$request = new Request('GET', self::SERVER_URI . $url);
|
72 |
+
|
73 |
+
return $fn($request, ['timeout' => $this->timeout])
|
74 |
+
->then(function (ResponseInterface $response) {
|
75 |
+
return (string) $response->getBody();
|
76 |
+
})->otherwise(function (array $reason) {
|
77 |
+
$reason = $reason['exception'];
|
78 |
+
$msg = $reason->getMessage();
|
79 |
+
throw new CredentialsException(
|
80 |
+
$this->createErrorMessage($msg, 0, $reason)
|
81 |
+
);
|
82 |
+
});
|
83 |
+
}
|
84 |
+
|
85 |
+
private function createErrorMessage($previous)
|
86 |
+
{
|
87 |
+
return "Error retrieving credentials from the instance profile "
|
88 |
+
. "metadata server. ({$previous})";
|
89 |
+
}
|
90 |
+
|
91 |
+
private function decodeResult($response)
|
92 |
+
{
|
93 |
+
$result = json_decode($response, true);
|
94 |
+
|
95 |
+
if ($result['Code'] !== 'Success') {
|
96 |
+
throw new CredentialsException('Unexpected instance profile '
|
97 |
+
. 'response code: ' . $result['Code']);
|
98 |
+
}
|
99 |
+
|
100 |
+
return $result;
|
101 |
+
}
|
102 |
+
}
|
includes/aws/Aws/DataPipeline/DataPipelineClient.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DataPipeline;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **AWS Data Pipeline** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result activatePipeline(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise activatePipelineAsync(array $args = [])
|
11 |
+
* @method \Aws\Result addTags(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise addTagsAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createPipeline(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createPipelineAsync(array $args = [])
|
15 |
+
* @method \Aws\Result deactivatePipeline(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise deactivatePipelineAsync(array $args = [])
|
17 |
+
* @method \Aws\Result deletePipeline(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise deletePipelineAsync(array $args = [])
|
19 |
+
* @method \Aws\Result describeObjects(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise describeObjectsAsync(array $args = [])
|
21 |
+
* @method \Aws\Result describePipelines(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise describePipelinesAsync(array $args = [])
|
23 |
+
* @method \Aws\Result evaluateExpression(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise evaluateExpressionAsync(array $args = [])
|
25 |
+
* @method \Aws\Result getPipelineDefinition(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise getPipelineDefinitionAsync(array $args = [])
|
27 |
+
* @method \Aws\Result listPipelines(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise listPipelinesAsync(array $args = [])
|
29 |
+
* @method \Aws\Result pollForTask(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise pollForTaskAsync(array $args = [])
|
31 |
+
* @method \Aws\Result putPipelineDefinition(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise putPipelineDefinitionAsync(array $args = [])
|
33 |
+
* @method \Aws\Result queryObjects(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise queryObjectsAsync(array $args = [])
|
35 |
+
* @method \Aws\Result removeTags(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise removeTagsAsync(array $args = [])
|
37 |
+
* @method \Aws\Result reportTaskProgress(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise reportTaskProgressAsync(array $args = [])
|
39 |
+
* @method \Aws\Result reportTaskRunnerHeartbeat(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise reportTaskRunnerHeartbeatAsync(array $args = [])
|
41 |
+
* @method \Aws\Result setStatus(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise setStatusAsync(array $args = [])
|
43 |
+
* @method \Aws\Result setTaskStatus(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise setTaskStatusAsync(array $args = [])
|
45 |
+
* @method \Aws\Result validatePipelineDefinition(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise validatePipelineDefinitionAsync(array $args = [])
|
47 |
+
*/
|
48 |
+
class DataPipelineClient extends AwsClient {}
|
includes/aws/Aws/DataPipeline/Exception/DataPipelineException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DataPipeline\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the AWS Data Pipeline service.
|
8 |
+
*/
|
9 |
+
class DataPipelineException extends AwsException {}
|
includes/aws/Aws/DirectConnect/DirectConnectClient.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DirectConnect;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **AWS Direct Connect** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result allocateConnectionOnInterconnect(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise allocateConnectionOnInterconnectAsync(array $args = [])
|
11 |
+
* @method \Aws\Result allocatePrivateVirtualInterface(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise allocatePrivateVirtualInterfaceAsync(array $args = [])
|
13 |
+
* @method \Aws\Result allocatePublicVirtualInterface(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise allocatePublicVirtualInterfaceAsync(array $args = [])
|
15 |
+
* @method \Aws\Result confirmConnection(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise confirmConnectionAsync(array $args = [])
|
17 |
+
* @method \Aws\Result confirmPrivateVirtualInterface(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise confirmPrivateVirtualInterfaceAsync(array $args = [])
|
19 |
+
* @method \Aws\Result confirmPublicVirtualInterface(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise confirmPublicVirtualInterfaceAsync(array $args = [])
|
21 |
+
* @method \Aws\Result createConnection(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise createConnectionAsync(array $args = [])
|
23 |
+
* @method \Aws\Result createInterconnect(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise createInterconnectAsync(array $args = [])
|
25 |
+
* @method \Aws\Result createPrivateVirtualInterface(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise createPrivateVirtualInterfaceAsync(array $args = [])
|
27 |
+
* @method \Aws\Result createPublicVirtualInterface(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise createPublicVirtualInterfaceAsync(array $args = [])
|
29 |
+
* @method \Aws\Result deleteConnection(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise deleteConnectionAsync(array $args = [])
|
31 |
+
* @method \Aws\Result deleteInterconnect(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise deleteInterconnectAsync(array $args = [])
|
33 |
+
* @method \Aws\Result deleteVirtualInterface(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise deleteVirtualInterfaceAsync(array $args = [])
|
35 |
+
* @method \Aws\Result describeConnections(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise describeConnectionsAsync(array $args = [])
|
37 |
+
* @method \Aws\Result describeConnectionsOnInterconnect(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise describeConnectionsOnInterconnectAsync(array $args = [])
|
39 |
+
* @method \Aws\Result describeInterconnects(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise describeInterconnectsAsync(array $args = [])
|
41 |
+
* @method \Aws\Result describeLocations(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise describeLocationsAsync(array $args = [])
|
43 |
+
* @method \Aws\Result describeVirtualGateways(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise describeVirtualGatewaysAsync(array $args = [])
|
45 |
+
* @method \Aws\Result describeVirtualInterfaces(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise describeVirtualInterfacesAsync(array $args = [])
|
47 |
+
*/
|
48 |
+
class DirectConnectClient extends AwsClient {}
|
includes/aws/Aws/DirectConnect/Exception/DirectConnectException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DirectConnect\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the AWS Direct Connect service.
|
8 |
+
*/
|
9 |
+
class DirectConnectException extends AwsException {}
|
includes/aws/Aws/DirectoryService/DirectoryServiceClient.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DirectoryService;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS Directory Service client
|
8 |
+
*
|
9 |
+
* @method \Aws\Result connectDirectory(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise connectDirectoryAsync(array $args = [])
|
11 |
+
* @method \Aws\Result createAlias(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise createAliasAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createComputer(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createComputerAsync(array $args = [])
|
15 |
+
* @method \Aws\Result createDirectory(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise createDirectoryAsync(array $args = [])
|
17 |
+
* @method \Aws\Result createMicrosoftAD(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise createMicrosoftADAsync(array $args = [])
|
19 |
+
* @method \Aws\Result createSnapshot(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise createSnapshotAsync(array $args = [])
|
21 |
+
* @method \Aws\Result createTrust(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise createTrustAsync(array $args = [])
|
23 |
+
* @method \Aws\Result deleteDirectory(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise deleteDirectoryAsync(array $args = [])
|
25 |
+
* @method \Aws\Result deleteSnapshot(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise deleteSnapshotAsync(array $args = [])
|
27 |
+
* @method \Aws\Result deleteTrust(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise deleteTrustAsync(array $args = [])
|
29 |
+
* @method \Aws\Result describeDirectories(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise describeDirectoriesAsync(array $args = [])
|
31 |
+
* @method \Aws\Result describeSnapshots(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise describeSnapshotsAsync(array $args = [])
|
33 |
+
* @method \Aws\Result describeTrusts(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise describeTrustsAsync(array $args = [])
|
35 |
+
* @method \Aws\Result disableRadius(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise disableRadiusAsync(array $args = [])
|
37 |
+
* @method \Aws\Result disableSso(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise disableSsoAsync(array $args = [])
|
39 |
+
* @method \Aws\Result enableRadius(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise enableRadiusAsync(array $args = [])
|
41 |
+
* @method \Aws\Result enableSso(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise enableSsoAsync(array $args = [])
|
43 |
+
* @method \Aws\Result getDirectoryLimits(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise getDirectoryLimitsAsync(array $args = [])
|
45 |
+
* @method \Aws\Result getSnapshotLimits(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise getSnapshotLimitsAsync(array $args = [])
|
47 |
+
* @method \Aws\Result restoreFromSnapshot(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise restoreFromSnapshotAsync(array $args = [])
|
49 |
+
* @method \Aws\Result updateRadius(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise updateRadiusAsync(array $args = [])
|
51 |
+
* @method \Aws\Result verifyTrust(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise verifyTrustAsync(array $args = [])
|
53 |
+
*/
|
54 |
+
class DirectoryServiceClient extends AwsClient {}
|
includes/aws/Aws/DirectoryService/Exception/DirectoryServiceException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\DirectoryService\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS Directory Service Exception
|
8 |
+
*/
|
9 |
+
class DirectoryServiceException extends AwsException {}
|
includes/aws/Aws/DoctrineCacheAdapter.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Doctrine\Common\Cache\Cache;
|
5 |
+
|
6 |
+
class DoctrineCacheAdapter implements CacheInterface, Cache
|
7 |
+
{
|
8 |
+
/** @var Cache */
|
9 |
+
private $cache;
|
10 |
+
|
11 |
+
public function __construct(Cache $cache)
|
12 |
+
{
|
13 |
+
$this->cache = $cache;
|
14 |
+
}
|
15 |
+
|
16 |
+
public function get($key)
|
17 |
+
{
|
18 |
+
return $this->cache->fetch($key);
|
19 |
+
}
|
20 |
+
|
21 |
+
public function fetch($key)
|
22 |
+
{
|
23 |
+
return $this->get($key);
|
24 |
+
}
|
25 |
+
|
26 |
+
public function set($key, $value, $ttl = 0)
|
27 |
+
{
|
28 |
+
return $this->cache->save($key, $value, $ttl);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function save($key, $value, $ttl = 0)
|
32 |
+
{
|
33 |
+
return $this->set($key, $value, $ttl);
|
34 |
+
}
|
35 |
+
|
36 |
+
public function remove($key)
|
37 |
+
{
|
38 |
+
return $this->cache->delete($key);
|
39 |
+
}
|
40 |
+
|
41 |
+
public function delete($key)
|
42 |
+
{
|
43 |
+
return $this->remove($key);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function contains($key)
|
47 |
+
{
|
48 |
+
return $this->cache->contains($key);
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getStats()
|
52 |
+
{
|
53 |
+
return $this->cache->getStats();
|
54 |
+
}
|
55 |
+
}
|
includes/aws/Aws/Endpoint/EndpointProvider.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Endpoint;
|
3 |
+
|
4 |
+
use Aws\Exception\UnresolvedEndpointException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Endpoint providers.
|
8 |
+
*
|
9 |
+
* An endpoint provider is a function that accepts a hash of endpoint options,
|
10 |
+
* including but not limited to "service" and "region" key value pairs. The
|
11 |
+
* endpoint provider function returns a hash of endpoint data, which MUST
|
12 |
+
* include an "endpoint" key value pair that represents the resolved endpoint
|
13 |
+
* or NULL if an endpoint cannot be determined.
|
14 |
+
*
|
15 |
+
* You can wrap your calls to an endpoint provider with the
|
16 |
+
* {@see EndpointProvider::resolve} function to ensure that an endpoint hash is
|
17 |
+
* created. If an endpoint hash is not created, then the resolve() function
|
18 |
+
* will throw an {@see Aws\Exception\UnresolvedEndpointException}.
|
19 |
+
*
|
20 |
+
* use Aws\Endpoint\EndpointProvider;
|
21 |
+
* $provider = EndpointProvider::defaultProvider();
|
22 |
+
* // Returns an array or NULL.
|
23 |
+
* $endpoint = $provider(['service' => 'ec2', 'region' => 'us-west-2']);
|
24 |
+
* // Returns an endpoint array or throws.
|
25 |
+
* $endpoint = EndpointProvider::resolve($provider, [
|
26 |
+
* 'service' => 'ec2',
|
27 |
+
* 'region' => 'us-west-2'
|
28 |
+
* ]);
|
29 |
+
*
|
30 |
+
* You can compose multiple providers into a single provider using
|
31 |
+
* {@see Aws\or_chain}. This function accepts providers as arguments and
|
32 |
+
* returns a new function that will invoke each provider until a non-null value
|
33 |
+
* is returned.
|
34 |
+
*
|
35 |
+
* $a = function (array $args) {
|
36 |
+
* if ($args['region'] === 'my-test-region') {
|
37 |
+
* return ['endpoint' => 'http://localhost:123/api'];
|
38 |
+
* }
|
39 |
+
* };
|
40 |
+
* $b = EndpointProvider::defaultProvider();
|
41 |
+
* $c = \Aws\or_chain($a, $b);
|
42 |
+
* $config = ['service' => 'ec2', 'region' => 'my-test-region'];
|
43 |
+
* $res = $c($config); // $a handles this.
|
44 |
+
* $config['region'] = 'us-west-2';
|
45 |
+
* $res = $c($config); // $b handles this.
|
46 |
+
*/
|
47 |
+
class EndpointProvider
|
48 |
+
{
|
49 |
+
/**
|
50 |
+
* Resolves and endpoint provider and ensures a non-null return value.
|
51 |
+
*
|
52 |
+
* @param callable $provider Provider function to invoke.
|
53 |
+
* @param array $args Endpoint arguments to pass to the provider.
|
54 |
+
*
|
55 |
+
* @return array
|
56 |
+
* @throws UnresolvedEndpointException
|
57 |
+
*/
|
58 |
+
public static function resolve(callable $provider, array $args = [])
|
59 |
+
{
|
60 |
+
$result = $provider($args);
|
61 |
+
if (is_array($result)) {
|
62 |
+
return $result;
|
63 |
+
}
|
64 |
+
|
65 |
+
throw new UnresolvedEndpointException(
|
66 |
+
'Unable to resolve an endpoint using the provider arguments: '
|
67 |
+
. json_encode($args) . '. Note: you can provide an "endpoint" '
|
68 |
+
. 'option to a client constructor to bypass invoking an endpoint '
|
69 |
+
. 'provider.');
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Creates and returns the default SDK endpoint provider.
|
74 |
+
*
|
75 |
+
* @return callable
|
76 |
+
*/
|
77 |
+
public static function defaultProvider()
|
78 |
+
{
|
79 |
+
$data = \Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
|
80 |
+
|
81 |
+
return new PatternEndpointProvider($data['endpoints']);
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Creates and returns an endpoint provider that uses patterns from an
|
86 |
+
* array.
|
87 |
+
*
|
88 |
+
* @param array $patterns Endpoint patterns
|
89 |
+
*
|
90 |
+
* @return callable
|
91 |
+
*/
|
92 |
+
public static function patterns(array $patterns)
|
93 |
+
{
|
94 |
+
return new PatternEndpointProvider($patterns);
|
95 |
+
}
|
96 |
+
}
|
includes/aws/Aws/Endpoint/PatternEndpointProvider.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Endpoint;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Provides endpoints based on an endpoint pattern configuration array.
|
6 |
+
*/
|
7 |
+
class PatternEndpointProvider
|
8 |
+
{
|
9 |
+
/** @var array */
|
10 |
+
private $patterns;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @param array $patterns Hash of endpoint patterns mapping to endpoint
|
14 |
+
* configurations.
|
15 |
+
*/
|
16 |
+
public function __construct(array $patterns)
|
17 |
+
{
|
18 |
+
$this->patterns = $patterns;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function __invoke(array $args = [])
|
22 |
+
{
|
23 |
+
$service = isset($args['service']) ? $args['service'] : '';
|
24 |
+
$region = isset($args['region']) ? $args['region'] : '';
|
25 |
+
$keys = ["{$region}/{$service}", "{$region}/*", "*/{$service}", "*/*"];
|
26 |
+
|
27 |
+
foreach ($keys as $key) {
|
28 |
+
if (isset($this->patterns[$key])) {
|
29 |
+
return $this->expand(
|
30 |
+
$this->patterns[$key],
|
31 |
+
isset($args['scheme']) ? $args['scheme'] : 'https',
|
32 |
+
$service,
|
33 |
+
$region
|
34 |
+
);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
return null;
|
39 |
+
}
|
40 |
+
|
41 |
+
private function expand(array $config, $scheme, $service, $region)
|
42 |
+
{
|
43 |
+
$config['endpoint'] = $scheme . '://'
|
44 |
+
. strtr($config['endpoint'], [
|
45 |
+
'{service}' => $service,
|
46 |
+
'{region}' => $region
|
47 |
+
]);
|
48 |
+
|
49 |
+
return $config;
|
50 |
+
}
|
51 |
+
}
|
includes/aws/Aws/Exception/AwsException.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
use Psr\Http\Message\ResponseInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Aws\CommandInterface;
|
7 |
+
use Aws\ResultInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Represents an AWS exception that is thrown when a command fails.
|
11 |
+
*/
|
12 |
+
class AwsException extends \RuntimeException
|
13 |
+
{
|
14 |
+
/** @var ResponseInterface */
|
15 |
+
private $response;
|
16 |
+
private $request;
|
17 |
+
private $result;
|
18 |
+
private $command;
|
19 |
+
private $requestId;
|
20 |
+
private $errorType;
|
21 |
+
private $errorCode;
|
22 |
+
private $connectionError;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param string $message Exception message
|
26 |
+
* @param CommandInterface $command
|
27 |
+
* @param array $context Exception context
|
28 |
+
* @param \Exception $previous Previous exception (if any)
|
29 |
+
*/
|
30 |
+
public function __construct(
|
31 |
+
$message,
|
32 |
+
CommandInterface $command,
|
33 |
+
array $context = [],
|
34 |
+
\Exception $previous = null
|
35 |
+
) {
|
36 |
+
$this->command = $command;
|
37 |
+
$this->response = isset($context['response']) ? $context['response'] : null;
|
38 |
+
$this->request = isset($context['request']) ? $context['request'] : null;
|
39 |
+
$this->requestId = isset($context['request_id'])
|
40 |
+
? $context['request_id']
|
41 |
+
: null;
|
42 |
+
$this->errorType = isset($context['type']) ? $context['type'] : null;
|
43 |
+
$this->errorCode = isset($context['code']) ? $context['code'] : null;
|
44 |
+
$this->connectionError = !empty($context['connection_error']);
|
45 |
+
$this->result = isset($context['result']) ? $context['result'] : null;
|
46 |
+
parent::__construct($message, 0, $previous);
|
47 |
+
}
|
48 |
+
|
49 |
+
public function __toString()
|
50 |
+
{
|
51 |
+
if (!$this->getPrevious()) {
|
52 |
+
return parent::__toString();
|
53 |
+
}
|
54 |
+
|
55 |
+
// PHP strangely shows the innermost exception first before the outer
|
56 |
+
// exception message. It also has a default character limit for
|
57 |
+
// exception message strings such that the "next" exception (this one)
|
58 |
+
// might not even get shown, causing developers to attempt to catch
|
59 |
+
// the inner exception instead of the actual exception because they
|
60 |
+
// can't see the outer exception's __toString output.
|
61 |
+
return sprintf(
|
62 |
+
"exception '%s' with message '%s'\n\n%s",
|
63 |
+
get_class($this),
|
64 |
+
$this->getMessage(),
|
65 |
+
parent::__toString()
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get the command that was executed.
|
71 |
+
*
|
72 |
+
* @return CommandInterface
|
73 |
+
*/
|
74 |
+
public function getCommand()
|
75 |
+
{
|
76 |
+
return $this->command;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get the sent HTTP request if any.
|
81 |
+
*
|
82 |
+
* @return RequestInterface|null
|
83 |
+
*/
|
84 |
+
public function getRequest()
|
85 |
+
{
|
86 |
+
return $this->request;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get the received HTTP response if any.
|
91 |
+
*
|
92 |
+
* @return ResponseInterface|null
|
93 |
+
*/
|
94 |
+
public function getResponse()
|
95 |
+
{
|
96 |
+
return $this->response;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Get the result of the exception if available
|
101 |
+
*
|
102 |
+
* @return ResultInterface|null
|
103 |
+
*/
|
104 |
+
public function getResult()
|
105 |
+
{
|
106 |
+
return $this->result;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Returns true if this is a connection error.
|
111 |
+
*
|
112 |
+
* @return bool
|
113 |
+
*/
|
114 |
+
public function isConnectionError()
|
115 |
+
{
|
116 |
+
return $this->connectionError;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* If available, gets the HTTP status code of the corresponding response
|
121 |
+
*
|
122 |
+
* @return int|null
|
123 |
+
*/
|
124 |
+
public function getStatusCode()
|
125 |
+
{
|
126 |
+
return $this->response ? $this->response->getStatusCode() : null;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Get the request ID of the error. This value is only present if a
|
131 |
+
* response was received and is not present in the event of a networking
|
132 |
+
* error.
|
133 |
+
*
|
134 |
+
* @return string|null Returns null if no response was received
|
135 |
+
*/
|
136 |
+
public function getAwsRequestId()
|
137 |
+
{
|
138 |
+
return $this->requestId;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Get the AWS error type.
|
143 |
+
*
|
144 |
+
* @return string|null Returns null if no response was received
|
145 |
+
*/
|
146 |
+
public function getAwsErrorType()
|
147 |
+
{
|
148 |
+
return $this->errorType;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Get the AWS error code.
|
153 |
+
*
|
154 |
+
* @return string|null Returns null if no response was received
|
155 |
+
*/
|
156 |
+
public function getAwsErrorCode()
|
157 |
+
{
|
158 |
+
return $this->errorCode;
|
159 |
+
}
|
160 |
+
}
|
includes/aws/Aws/Exception/CouldNotCreateChecksumException.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
class CouldNotCreateChecksumException extends \RuntimeException
|
5 |
+
{
|
6 |
+
public function __construct($algorithm, \Exception $previous = null)
|
7 |
+
{
|
8 |
+
$prefix = $algorithm === 'md5' ? "An" : "A";
|
9 |
+
parent::__construct("{$prefix} {$algorithm} checksum could not be "
|
10 |
+
. "calculated for the provided upload body, because it was not "
|
11 |
+
. "seekable. To prevent this error you can either 1) include the "
|
12 |
+
. "ContentMD5 or ContentSHA256 parameters with your request, 2) "
|
13 |
+
. "use a seekable stream for the body, or 3) wrap the non-seekable "
|
14 |
+
. "stream in a GuzzleHttp\\Psr7\\CachingStream object. You "
|
15 |
+
. "should be careful though and remember that the CachingStream "
|
16 |
+
. "utilizes PHP temp streams. This means that the stream will be "
|
17 |
+
. "temporarily stored on the local disk.", 0, $previous);
|
18 |
+
}
|
19 |
+
}
|
includes/aws/Aws/Exception/CredentialsException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
class CredentialsException extends \RuntimeException {}
|
includes/aws/Aws/Exception/MultipartUploadException.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
use Aws\Multipart\UploadState;
|
5 |
+
|
6 |
+
class MultipartUploadException extends \RuntimeException
|
7 |
+
{
|
8 |
+
/** @var UploadState State of the erroneous transfer */
|
9 |
+
private $state;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param UploadState $state Upload state at time of the exception.
|
13 |
+
* @param \Exception|array $prev Exception being thrown.
|
14 |
+
*/
|
15 |
+
public function __construct(UploadState $state, $prev = null) {
|
16 |
+
$msg = 'An exception occurred while performing a multipart upload.';
|
17 |
+
|
18 |
+
if (is_array($prev)) {
|
19 |
+
$msg = strtr($msg, ['performing' => 'uploading parts to']);
|
20 |
+
$msg .= " The following parts had errors:\n";
|
21 |
+
/** @var $error AwsException */
|
22 |
+
foreach ($prev as $part => $error) {
|
23 |
+
$msg .= "- Part {$part}: " . $error->getMessage(). "\n";
|
24 |
+
}
|
25 |
+
} elseif ($prev instanceof AwsException) {
|
26 |
+
switch ($prev->getCommand()->getName()) {
|
27 |
+
case 'CreateMultipartUpload':
|
28 |
+
case 'InitiateMultipartUpload':
|
29 |
+
$action = 'initiating';
|
30 |
+
break;
|
31 |
+
case 'CompleteMultipartUpload':
|
32 |
+
$action = 'completing';
|
33 |
+
break;
|
34 |
+
}
|
35 |
+
if (isset($action)) {
|
36 |
+
$msg = strtr($msg, ['performing' => $action]);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
if (!$prev instanceof \Exception) {
|
41 |
+
$prev = null;
|
42 |
+
}
|
43 |
+
|
44 |
+
parent::__construct($msg, 0, $prev);
|
45 |
+
$this->state = $state;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get the state of the transfer
|
50 |
+
*
|
51 |
+
* @return UploadState
|
52 |
+
*/
|
53 |
+
public function getState()
|
54 |
+
{
|
55 |
+
return $this->state;
|
56 |
+
}
|
57 |
+
}
|
includes/aws/Aws/Exception/UnresolvedApiException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
class UnresolvedApiException extends \RuntimeException {}
|
includes/aws/Aws/Exception/UnresolvedEndpointException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
class UnresolvedEndpointException extends \RuntimeException {}
|
includes/aws/Aws/Exception/UnresolvedSignatureException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Exception;
|
3 |
+
|
4 |
+
class UnresolvedSignatureException extends \RuntimeException {}
|
includes/aws/Aws/Firehose/Exception/FirehoseException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Firehose\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the **Amazon Kinesis Firehose** service.
|
8 |
+
*/
|
9 |
+
class FirehoseException extends AwsException {}
|
includes/aws/Aws/Firehose/FirehoseClient.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Firehose;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **Amazon Kinesis Firehose** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result createDeliveryStream(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise createDeliveryStreamAsync(array $args = [])
|
11 |
+
* @method \Aws\Result deleteDeliveryStream(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise deleteDeliveryStreamAsync(array $args = [])
|
13 |
+
* @method \Aws\Result describeDeliveryStream(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise describeDeliveryStreamAsync(array $args = [])
|
15 |
+
* @method \Aws\Result listDeliveryStreams(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise listDeliveryStreamsAsync(array $args = [])
|
17 |
+
* @method \Aws\Result putRecord(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise putRecordAsync(array $args = [])
|
19 |
+
* @method \Aws\Result putRecordBatch(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise putRecordBatchAsync(array $args = [])
|
21 |
+
* @method \Aws\Result updateDestination(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise updateDestinationAsync(array $args = [])
|
23 |
+
*/
|
24 |
+
class FirehoseClient extends AwsClient {}
|
includes/aws/Aws/Glacier/Exception/GlacierException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Glacier\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the Amazon Glacier service.
|
8 |
+
*/
|
9 |
+
class GlacierException extends AwsException {}
|
includes/aws/Aws/Glacier/GlacierClient.php
ADDED
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Glacier;
|
3 |
+
|
4 |
+
use Aws\Api\ApiProvider;
|
5 |
+
use Aws\Api\DocModel;
|
6 |
+
use Aws\Api\Service;
|
7 |
+
use Aws\AwsClient;
|
8 |
+
use Aws\CommandInterface;
|
9 |
+
use Aws\Exception\CouldNotCreateChecksumException;
|
10 |
+
use Aws\HashingStream;
|
11 |
+
use Aws\Middleware;
|
12 |
+
use Aws\PhpHash;
|
13 |
+
use Psr\Http\Message\RequestInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* This client is used to interact with the **Amazon Glacier** service.
|
17 |
+
*
|
18 |
+
* @method \Aws\Result abortMultipartUpload(array $args = [])
|
19 |
+
* @method \GuzzleHttp\Promise\Promise abortMultipartUploadAsync(array $args = [])
|
20 |
+
* @method \Aws\Result abortVaultLock(array $args = [])
|
21 |
+
* @method \GuzzleHttp\Promise\Promise abortVaultLockAsync(array $args = [])
|
22 |
+
* @method \Aws\Result addTagsToVault(array $args = [])
|
23 |
+
* @method \GuzzleHttp\Promise\Promise addTagsToVaultAsync(array $args = [])
|
24 |
+
* @method \Aws\Result completeMultipartUpload(array $args = [])
|
25 |
+
* @method \GuzzleHttp\Promise\Promise completeMultipartUploadAsync(array $args = [])
|
26 |
+
* @method \Aws\Result completeVaultLock(array $args = [])
|
27 |
+
* @method \GuzzleHttp\Promise\Promise completeVaultLockAsync(array $args = [])
|
28 |
+
* @method \Aws\Result createVault(array $args = [])
|
29 |
+
* @method \GuzzleHttp\Promise\Promise createVaultAsync(array $args = [])
|
30 |
+
* @method \Aws\Result deleteArchive(array $args = [])
|
31 |
+
* @method \GuzzleHttp\Promise\Promise deleteArchiveAsync(array $args = [])
|
32 |
+
* @method \Aws\Result deleteVault(array $args = [])
|
33 |
+
* @method \GuzzleHttp\Promise\Promise deleteVaultAsync(array $args = [])
|
34 |
+
* @method \Aws\Result deleteVaultAccessPolicy(array $args = [])
|
35 |
+
* @method \GuzzleHttp\Promise\Promise deleteVaultAccessPolicyAsync(array $args = [])
|
36 |
+
* @method \Aws\Result deleteVaultNotifications(array $args = [])
|
37 |
+
* @method \GuzzleHttp\Promise\Promise deleteVaultNotificationsAsync(array $args = [])
|
38 |
+
* @method \Aws\Result describeJob(array $args = [])
|
39 |
+
* @method \GuzzleHttp\Promise\Promise describeJobAsync(array $args = [])
|
40 |
+
* @method \Aws\Result describeVault(array $args = [])
|
41 |
+
* @method \GuzzleHttp\Promise\Promise describeVaultAsync(array $args = [])
|
42 |
+
* @method \Aws\Result getDataRetrievalPolicy(array $args = [])
|
43 |
+
* @method \GuzzleHttp\Promise\Promise getDataRetrievalPolicyAsync(array $args = [])
|
44 |
+
* @method \Aws\Result getJobOutput(array $args = [])
|
45 |
+
* @method \GuzzleHttp\Promise\Promise getJobOutputAsync(array $args = [])
|
46 |
+
* @method \Aws\Result getVaultAccessPolicy(array $args = [])
|
47 |
+
* @method \GuzzleHttp\Promise\Promise getVaultAccessPolicyAsync(array $args = [])
|
48 |
+
* @method \Aws\Result getVaultLock(array $args = [])
|
49 |
+
* @method \GuzzleHttp\Promise\Promise getVaultLockAsync(array $args = [])
|
50 |
+
* @method \Aws\Result getVaultNotifications(array $args = [])
|
51 |
+
* @method \GuzzleHttp\Promise\Promise getVaultNotificationsAsync(array $args = [])
|
52 |
+
* @method \Aws\Result initiateJob(array $args = [])
|
53 |
+
* @method \GuzzleHttp\Promise\Promise initiateJobAsync(array $args = [])
|
54 |
+
* @method \Aws\Result initiateMultipartUpload(array $args = [])
|
55 |
+
* @method \GuzzleHttp\Promise\Promise initiateMultipartUploadAsync(array $args = [])
|
56 |
+
* @method \Aws\Result initiateVaultLock(array $args = [])
|
57 |
+
* @method \GuzzleHttp\Promise\Promise initiateVaultLockAsync(array $args = [])
|
58 |
+
* @method \Aws\Result listJobs(array $args = [])
|
59 |
+
* @method \GuzzleHttp\Promise\Promise listJobsAsync(array $args = [])
|
60 |
+
* @method \Aws\Result listMultipartUploads(array $args = [])
|
61 |
+
* @method \GuzzleHttp\Promise\Promise listMultipartUploadsAsync(array $args = [])
|
62 |
+
* @method \Aws\Result listParts(array $args = [])
|
63 |
+
* @method \GuzzleHttp\Promise\Promise listPartsAsync(array $args = [])
|
64 |
+
* @method \Aws\Result listTagsForVault(array $args = [])
|
65 |
+
* @method \GuzzleHttp\Promise\Promise listTagsForVaultAsync(array $args = [])
|
66 |
+
* @method \Aws\Result listVaults(array $args = [])
|
67 |
+
* @method \GuzzleHttp\Promise\Promise listVaultsAsync(array $args = [])
|
68 |
+
* @method \Aws\Result removeTagsFromVault(array $args = [])
|
69 |
+
* @method \GuzzleHttp\Promise\Promise removeTagsFromVaultAsync(array $args = [])
|
70 |
+
* @method \Aws\Result setDataRetrievalPolicy(array $args = [])
|
71 |
+
* @method \GuzzleHttp\Promise\Promise setDataRetrievalPolicyAsync(array $args = [])
|
72 |
+
* @method \Aws\Result setVaultAccessPolicy(array $args = [])
|
73 |
+
* @method \GuzzleHttp\Promise\Promise setVaultAccessPolicyAsync(array $args = [])
|
74 |
+
* @method \Aws\Result setVaultNotifications(array $args = [])
|
75 |
+
* @method \GuzzleHttp\Promise\Promise setVaultNotificationsAsync(array $args = [])
|
76 |
+
* @method \Aws\Result uploadArchive(array $args = [])
|
77 |
+
* @method \GuzzleHttp\Promise\Promise uploadArchiveAsync(array $args = [])
|
78 |
+
* @method \Aws\Result uploadMultipartPart(array $args = [])
|
79 |
+
* @method \GuzzleHttp\Promise\Promise uploadMultipartPartAsync(array $args = [])
|
80 |
+
*/
|
81 |
+
class GlacierClient extends AwsClient
|
82 |
+
{
|
83 |
+
public function __construct(array $args)
|
84 |
+
{
|
85 |
+
parent::__construct($args);
|
86 |
+
|
87 |
+
// Setup middleware.
|
88 |
+
$stack = $this->getHandlerList();
|
89 |
+
$stack->appendBuild($this->getApiVersionMiddleware(), 'glacier.api_version');
|
90 |
+
$stack->appendBuild($this->getChecksumsMiddleware(), 'glacier.checksum');
|
91 |
+
$stack->appendBuild(
|
92 |
+
Middleware::contentType(['UploadArchive', 'UploadPart']),
|
93 |
+
'glacier.content_type'
|
94 |
+
);
|
95 |
+
$stack->appendInit(
|
96 |
+
Middleware::sourceFile($this->getApi(), 'body', 'sourceFile'),
|
97 |
+
'glacier.source_file'
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* {@inheritdoc}
|
103 |
+
*
|
104 |
+
* Sets the default accountId to "-" for all operations.
|
105 |
+
*/
|
106 |
+
public function getCommand($name, array $args = [])
|
107 |
+
{
|
108 |
+
return parent::getCommand($name, $args + ['accountId' => '-']);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Creates a middleware that updates a command with the content and tree
|
113 |
+
* hash headers for upload operations.
|
114 |
+
*
|
115 |
+
* @return callable
|
116 |
+
* @throws CouldNotCreateChecksumException if the body is not seekable.
|
117 |
+
*/
|
118 |
+
private function getChecksumsMiddleware()
|
119 |
+
{
|
120 |
+
return function (callable $handler) {
|
121 |
+
return function (
|
122 |
+
CommandInterface $command,
|
123 |
+
RequestInterface $request = null
|
124 |
+
) use ($handler) {
|
125 |
+
// Accept "ContentSHA256" with a lowercase "c" to match other Glacier params.
|
126 |
+
if (!$command['ContentSHA256'] && $command['contentSHA256']) {
|
127 |
+
$command['ContentSHA256'] = $command['contentSHA256'];
|
128 |
+
unset($command['contentSHA256']);
|
129 |
+
}
|
130 |
+
|
131 |
+
// If uploading, then make sure checksums are added.
|
132 |
+
$name = $command->getName();
|
133 |
+
if (($name === 'UploadArchive' || $name === 'UploadMultipartPart')
|
134 |
+
&& (!$command['checksum'] || !$command['ContentSHA256'])
|
135 |
+
) {
|
136 |
+
$body = $request->getBody();
|
137 |
+
if (!$body->isSeekable()) {
|
138 |
+
throw new CouldNotCreateChecksumException('sha256');
|
139 |
+
}
|
140 |
+
|
141 |
+
// Add a tree hash if not provided.
|
142 |
+
if (!$command['checksum']) {
|
143 |
+
$body = new HashingStream(
|
144 |
+
$body, new TreeHash(),
|
145 |
+
function ($result) use ($command, &$request) {
|
146 |
+
$request = $request->withHeader(
|
147 |
+
'x-amz-sha256-tree-hash',
|
148 |
+
bin2hex($result)
|
149 |
+
);
|
150 |
+
}
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
// Add a linear content hash if not provided.
|
155 |
+
if (!$command['ContentSHA256']) {
|
156 |
+
$body = new HashingStream(
|
157 |
+
$body, new PhpHash('sha256'),
|
158 |
+
function ($result) use ($command) {
|
159 |
+
$command['ContentSHA256'] = bin2hex($result);
|
160 |
+
}
|
161 |
+
);
|
162 |
+
}
|
163 |
+
|
164 |
+
// Read the stream in order to calculate the hashes.
|
165 |
+
while (!$body->eof()) {
|
166 |
+
$body->read(1048576);
|
167 |
+
}
|
168 |
+
$body->seek(0);
|
169 |
+
}
|
170 |
+
|
171 |
+
// Set the content hash header if a value is in the command.
|
172 |
+
if ($command['ContentSHA256']) {
|
173 |
+
$request = $request->withHeader(
|
174 |
+
'x-amz-content-sha256',
|
175 |
+
$command['ContentSHA256']
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
return $handler($command, $request);
|
180 |
+
};
|
181 |
+
};
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Creates a middleware that adds the API version header for all requests.
|
186 |
+
*
|
187 |
+
* @return callable
|
188 |
+
*/
|
189 |
+
private function getApiVersionMiddleware()
|
190 |
+
{
|
191 |
+
return function (callable $handler) {
|
192 |
+
return function (
|
193 |
+
CommandInterface $command,
|
194 |
+
RequestInterface $request = null
|
195 |
+
) use ($handler) {
|
196 |
+
return $handler($command, $request->withHeader(
|
197 |
+
'x-amz-glacier-version',
|
198 |
+
$this->getApi()->getMetadata('apiVersion')
|
199 |
+
));
|
200 |
+
};
|
201 |
+
};
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* @internal
|
206 |
+
* @codeCoverageIgnore
|
207 |
+
*/
|
208 |
+
public static function applyDocFilters(array $api, array $docs)
|
209 |
+
{
|
210 |
+
// Add the SourceFile parameter.
|
211 |
+
$docs['shapes']['SourceFile']['base'] = 'The path to a file on disk to use instead of the body parameter.';
|
212 |
+
$api['shapes']['SourceFile'] = ['type' => 'string'];
|
213 |
+
$api['shapes']['UploadArchiveInput']['members']['sourceFile'] = ['shape' => 'SourceFile'];
|
214 |
+
$api['shapes']['UploadMultipartPartInput']['members']['sourceFile'] = ['shape' => 'SourceFile'];
|
215 |
+
|
216 |
+
// Add the ContentSHA256 parameter.
|
217 |
+
$docs['shapes']['ContentSHA256']['base'] = 'A SHA256 hash of the content of the request body';
|
218 |
+
$api['shapes']['ContentSHA256'] = ['type' => 'string'];
|
219 |
+
$api['shapes']['UploadArchiveInput']['members']['contentSHA256'] = ['shape' => 'ContentSHA256'];
|
220 |
+
$api['shapes']['UploadMultipartPartInput']['members']['contentSHA256'] = ['shape' => 'ContentSHA256'];
|
221 |
+
|
222 |
+
// Add information about "checksum" and "ContentSHA256" being optional.
|
223 |
+
$optional = '<div class="alert alert-info">The SDK will compute this value '
|
224 |
+
. 'for you on your behalf if it is not supplied.</div>';
|
225 |
+
$docs['shapes']['checksum']['append'] = $optional;
|
226 |
+
$docs['shapes']['ContentSHA256']['append'] = $optional;
|
227 |
+
|
228 |
+
// Make "accountId" optional for all operations.
|
229 |
+
foreach ($api['operations'] as $operation) {
|
230 |
+
$inputShape =& $api['shapes'][$operation['input']['shape']];
|
231 |
+
$accountIdIndex = array_search('accountId', $inputShape['required']);
|
232 |
+
unset($inputShape['required'][$accountIdIndex]);
|
233 |
+
}
|
234 |
+
// Add information about the default value for "accountId".
|
235 |
+
$optional = '<div class="alert alert-info">The SDK will set this value to "-" by default.</div>';
|
236 |
+
foreach ($docs['shapes']['string']['refs'] as $name => &$ref) {
|
237 |
+
if (strpos($name, 'accountId')) {
|
238 |
+
$ref .= $optional;
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
return [
|
243 |
+
new Service($api, ApiProvider::defaultProvider()),
|
244 |
+
new DocModel($docs)
|
245 |
+
];
|
246 |
+
}
|
247 |
+
}
|
includes/aws/Aws/Glacier/MultipartUploader.php
ADDED
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Glacier;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Aws\HashingStream;
|
6 |
+
use Aws\Multipart\AbstractUploader;
|
7 |
+
use Aws\Multipart\UploadState;
|
8 |
+
use Aws\PhpHash;
|
9 |
+
use Aws\ResultInterface;
|
10 |
+
use GuzzleHttp\Psr7;
|
11 |
+
use Psr\Http\Message\StreamInterface as Stream;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Encapsulates the execution of a multipart upload to Glacier.
|
15 |
+
*/
|
16 |
+
class MultipartUploader extends AbstractUploader
|
17 |
+
{
|
18 |
+
const PART_MIN_SIZE = 1048576;
|
19 |
+
|
20 |
+
private static $validPartSizes = [
|
21 |
+
1048576, // 1 MB
|
22 |
+
2097152, // 2 MB
|
23 |
+
4194304, // 4 MB
|
24 |
+
8388608, // 8 MB
|
25 |
+
16777216, // 16 MB
|
26 |
+
33554432, // 32 MB
|
27 |
+
67108864, // 64 MB
|
28 |
+
134217728, // 128 MB
|
29 |
+
268435456, // 256 MB
|
30 |
+
536870912, // 512 MB
|
31 |
+
1073741824, // 1 GB
|
32 |
+
2147483648, // 2 GB
|
33 |
+
4294967296, // 4 GB
|
34 |
+
];
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Creates an UploadState object for a multipart upload by querying the
|
38 |
+
* service for the specified upload's information.
|
39 |
+
*
|
40 |
+
* @param GlacierClient $client GlacierClient object to use.
|
41 |
+
* @param string $vaultName Vault name for the multipart upload.
|
42 |
+
* @param string $uploadId Upload ID for the multipart upload.
|
43 |
+
* @param string $accountId Account ID for the multipart upload.
|
44 |
+
*
|
45 |
+
* @return UploadState
|
46 |
+
*/
|
47 |
+
public static function getStateFromService(
|
48 |
+
GlacierClient $client,
|
49 |
+
$vaultName,
|
50 |
+
$uploadId,
|
51 |
+
$accountId = '-'
|
52 |
+
) {
|
53 |
+
$state = new UploadState([
|
54 |
+
'accountId' => $accountId,
|
55 |
+
'vaultName' => $vaultName,
|
56 |
+
'uploadId' => $uploadId,
|
57 |
+
]);
|
58 |
+
|
59 |
+
foreach ($client->getPaginator('ListParts', $state->getId()) as $result) {
|
60 |
+
// Get the part size from the first part in the first result.
|
61 |
+
if (!$state->getPartSize()) {
|
62 |
+
$state->setPartSize($result['PartSizeInBytes']);
|
63 |
+
}
|
64 |
+
// Mark all the parts returned by ListParts as uploaded.
|
65 |
+
foreach ($result['Parts'] as $part) {
|
66 |
+
list($rangeIndex, $rangeSize) = self::parseRange(
|
67 |
+
$part['RangeInBytes'],
|
68 |
+
$state->getPartSize()
|
69 |
+
);
|
70 |
+
$state->markPartAsUploaded($rangeIndex, [
|
71 |
+
'size' => $rangeSize,
|
72 |
+
'checksum' => $part['SHA256TreeHash'],
|
73 |
+
]);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
$state->setStatus(UploadState::INITIATED);
|
78 |
+
|
79 |
+
return $state;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Creates a multipart upload for a Glacier archive.
|
84 |
+
*
|
85 |
+
* The valid configuration options are as follows:
|
86 |
+
*
|
87 |
+
* - account_id: (string, default=string('-')) Account ID for the archive
|
88 |
+
* being uploaded, if different from the account making the request.
|
89 |
+
* - archive_description: (string) Description of the archive.
|
90 |
+
* - before_complete: (callable) Callback to invoke before the
|
91 |
+
* `CompleteMultipartUpload` operation. The callback should have a
|
92 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
93 |
+
* - before_initiate: (callable) Callback to invoke before the
|
94 |
+
* `InitiateMultipartUpload` operation. The callback should have a
|
95 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
96 |
+
* - before_upload: (callable) Callback to invoke before any
|
97 |
+
* `UploadMultipartPart` operations. The callback should have a function
|
98 |
+
* signature like `function (Aws\Command $command) {...}`.
|
99 |
+
* - concurrency: (int, default=int(3)) Maximum number of concurrent
|
100 |
+
* `UploadMultipartPart` operations allowed during the multipart upload.
|
101 |
+
* - part_size: (int, default=int(1048576)) Part size, in bytes, to use when
|
102 |
+
* doing a multipart upload. This must between 1 MB and 4 GB, and must be
|
103 |
+
* a power of 2 (in megabytes).
|
104 |
+
* - state: (Aws\Multipart\UploadState) An object that represents the state
|
105 |
+
* of the multipart upload and that is used to resume a previous upload.
|
106 |
+
* When this options is provided, the `account_id`, `key`, and `part_size`
|
107 |
+
* options are ignored.
|
108 |
+
* - vault_name: (string, required) Vault name to use for the archive being
|
109 |
+
* uploaded.
|
110 |
+
*
|
111 |
+
* @param GlacierClient $client Client used for the upload.
|
112 |
+
* @param mixed $source Source of the data to upload.
|
113 |
+
* @param array $config Configuration used to perform the upload.
|
114 |
+
*/
|
115 |
+
public function __construct(GlacierClient $client, $source, array $config = [])
|
116 |
+
{
|
117 |
+
parent::__construct($client, $source, $config + [
|
118 |
+
'account_id' => '-',
|
119 |
+
'vault_name' => null,
|
120 |
+
]);
|
121 |
+
}
|
122 |
+
|
123 |
+
protected function loadUploadWorkflowInfo()
|
124 |
+
{
|
125 |
+
return [
|
126 |
+
'command' => [
|
127 |
+
'initiate' => 'InitiateMultipartUpload',
|
128 |
+
'upload' => 'UploadMultipartPart',
|
129 |
+
'complete' => 'CompleteMultipartUpload',
|
130 |
+
],
|
131 |
+
'id' => [
|
132 |
+
'account_id' => 'accountId',
|
133 |
+
'vault_name' => 'vaultName',
|
134 |
+
'upload_id' => 'uploadId',
|
135 |
+
],
|
136 |
+
'part_num' => 'range',
|
137 |
+
];
|
138 |
+
}
|
139 |
+
|
140 |
+
protected function determinePartSize()
|
141 |
+
{
|
142 |
+
// Make sure the part size is set.
|
143 |
+
$partSize = $this->config['part_size'] ?: self::PART_MIN_SIZE;
|
144 |
+
|
145 |
+
// Ensure that the part size is valid.
|
146 |
+
if (!in_array($partSize, self::$validPartSizes)) {
|
147 |
+
throw new \InvalidArgumentException('The part_size must be a power '
|
148 |
+
. 'of 2, in megabytes, such that 1 MB <= PART_SIZE <= 4 GB.');
|
149 |
+
}
|
150 |
+
|
151 |
+
return $partSize;
|
152 |
+
}
|
153 |
+
|
154 |
+
protected function createPart($seekable, $number)
|
155 |
+
{
|
156 |
+
$data = [];
|
157 |
+
$firstByte = $this->source->tell();
|
158 |
+
|
159 |
+
// Read from the source to create the body stream. This also
|
160 |
+
// calculates the linear and tree hashes as the data is read.
|
161 |
+
if ($seekable) {
|
162 |
+
// Case 1: Stream is seekable, can make stream from new handle.
|
163 |
+
$body = Psr7\try_fopen($this->source->getMetadata('uri'), 'r');
|
164 |
+
$body = $this->limitPartStream(Psr7\stream_for($body));
|
165 |
+
// Create another stream decorated with hashing streams and read
|
166 |
+
// through it, so we can get the hash values for the part.
|
167 |
+
$decoratedBody = $this->decorateWithHashes($body, $data);
|
168 |
+
while (!$decoratedBody->eof()) $decoratedBody->read(1048576);
|
169 |
+
// Seek the original source forward to the end of the range.
|
170 |
+
$this->source->seek($this->source->tell() + $body->getSize());
|
171 |
+
} else {
|
172 |
+
// Case 2: Stream is not seekable, must store part in temp stream.
|
173 |
+
$source = $this->limitPartStream($this->source);
|
174 |
+
$source = $this->decorateWithHashes($source, $data);
|
175 |
+
$body = Psr7\stream_for();
|
176 |
+
Psr7\copy_to_stream($source, $body);
|
177 |
+
}
|
178 |
+
|
179 |
+
// Do not create a part if the body size is zero.
|
180 |
+
if ($body->getSize() === 0) {
|
181 |
+
return false;
|
182 |
+
}
|
183 |
+
|
184 |
+
$body->seek(0);
|
185 |
+
$data['body'] = $body;
|
186 |
+
$lastByte = $this->source->tell() - 1;
|
187 |
+
$data['range'] = "bytes {$firstByte}-{$lastByte}/*";
|
188 |
+
|
189 |
+
return $data;
|
190 |
+
}
|
191 |
+
|
192 |
+
protected function handleResult(CommandInterface $command, ResultInterface $result)
|
193 |
+
{
|
194 |
+
list($rangeIndex, $rangeSize) = $this->parseRange(
|
195 |
+
$command['range'],
|
196 |
+
$this->state->getPartSize()
|
197 |
+
);
|
198 |
+
|
199 |
+
$this->state->markPartAsUploaded($rangeIndex, [
|
200 |
+
'size' => $rangeSize,
|
201 |
+
'checksum' => $command['checksum']
|
202 |
+
]);
|
203 |
+
}
|
204 |
+
|
205 |
+
protected function getInitiateParams()
|
206 |
+
{
|
207 |
+
$params = ['partSize' => $this->state->getPartSize()];
|
208 |
+
if (isset($this->config['archive_description'])) {
|
209 |
+
$params['archiveDescription'] = $this->config['archive_description'];
|
210 |
+
}
|
211 |
+
|
212 |
+
return $params;
|
213 |
+
}
|
214 |
+
|
215 |
+
protected function getCompleteParams()
|
216 |
+
{
|
217 |
+
$treeHash = new TreeHash();
|
218 |
+
$archiveSize = 0;
|
219 |
+
foreach ($this->state->getUploadedParts() as $part) {
|
220 |
+
$archiveSize += $part['size'];
|
221 |
+
$treeHash->addChecksum($part['checksum']);
|
222 |
+
}
|
223 |
+
|
224 |
+
return [
|
225 |
+
'archiveSize' => $archiveSize,
|
226 |
+
'checksum' => bin2hex($treeHash->complete()),
|
227 |
+
];
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Decorates a stream with a tree AND linear sha256 hashing stream.
|
232 |
+
*
|
233 |
+
* @param Stream $stream Stream to decorate.
|
234 |
+
* @param array $data Data bag that results are injected into.
|
235 |
+
*
|
236 |
+
* @return Stream
|
237 |
+
*/
|
238 |
+
private function decorateWithHashes(Stream $stream, array &$data)
|
239 |
+
{
|
240 |
+
// Make sure that a tree hash is calculated.
|
241 |
+
$stream = new HashingStream($stream, new TreeHash(),
|
242 |
+
function ($result) use (&$data) {
|
243 |
+
$data['checksum'] = bin2hex($result);
|
244 |
+
}
|
245 |
+
);
|
246 |
+
|
247 |
+
// Make sure that a linear SHA256 hash is calculated.
|
248 |
+
$stream = new HashingStream($stream, new PhpHash('sha256'),
|
249 |
+
function ($result) use (&$data) {
|
250 |
+
$data['ContentSHA256'] = bin2hex($result);
|
251 |
+
}
|
252 |
+
);
|
253 |
+
|
254 |
+
return $stream;
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Parses a Glacier range string into a size and part number.
|
259 |
+
*
|
260 |
+
* @param string $range Glacier range string (e.g., "bytes 5-5000/*")
|
261 |
+
* @param int $partSize The chosen part size
|
262 |
+
*
|
263 |
+
* @return array
|
264 |
+
*/
|
265 |
+
private static function parseRange($range, $partSize)
|
266 |
+
{
|
267 |
+
// Strip away the prefix and suffix.
|
268 |
+
if (strpos($range, 'bytes') !== false) {
|
269 |
+
$range = substr($range, 6, -2);
|
270 |
+
}
|
271 |
+
|
272 |
+
// Split that range into it's parts.
|
273 |
+
list($firstByte, $lastByte) = explode('-', $range);
|
274 |
+
|
275 |
+
// Calculate and return range index and range size
|
276 |
+
return [
|
277 |
+
intval($firstByte / $partSize) + 1,
|
278 |
+
$lastByte - $firstByte + 1,
|
279 |
+
];
|
280 |
+
}
|
281 |
+
}
|
includes/aws/Aws/Glacier/TreeHash.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Glacier;
|
3 |
+
|
4 |
+
use Aws\HashInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Encapsulates the creation of a tree hash from streamed data
|
8 |
+
*/
|
9 |
+
class TreeHash implements HashInterface
|
10 |
+
{
|
11 |
+
const MB = 1048576;
|
12 |
+
const EMPTY_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
|
13 |
+
|
14 |
+
/** @var string Algorithm used for hashing. */
|
15 |
+
private $algorithm;
|
16 |
+
|
17 |
+
/** @var string Buffered data that has not yet been hashed. */
|
18 |
+
private $buffer;
|
19 |
+
|
20 |
+
/** @var array Binary checksums from which the tree hash is derived. */
|
21 |
+
private $checksums = [];
|
22 |
+
|
23 |
+
/** @var string Resulting hash in binary form. */
|
24 |
+
private $hash;
|
25 |
+
|
26 |
+
public function __construct($algorithm = 'sha256')
|
27 |
+
{
|
28 |
+
$this->algorithm = $algorithm;
|
29 |
+
$this->reset();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* {@inheritdoc}
|
34 |
+
* @throws \LogicException if the root tree hash is already calculated
|
35 |
+
*/
|
36 |
+
public function update($data)
|
37 |
+
{
|
38 |
+
// Error if hash is already calculated.
|
39 |
+
if ($this->hash) {
|
40 |
+
throw new \LogicException('You may not add more data to a '
|
41 |
+
. 'complete tree hash.');
|
42 |
+
}
|
43 |
+
|
44 |
+
// Buffer incoming data.
|
45 |
+
$this->buffer .= $data;
|
46 |
+
|
47 |
+
// When there is more than a MB of data, create a checksum.
|
48 |
+
while (strlen($this->buffer) >= self::MB) {
|
49 |
+
$data = substr($this->buffer, 0, self::MB);
|
50 |
+
$this->buffer = substr($this->buffer, self::MB) ?: '';
|
51 |
+
$this->checksums[] = hash($this->algorithm, $data, true);
|
52 |
+
}
|
53 |
+
|
54 |
+
return $this;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Add a checksum to the tree hash directly
|
59 |
+
*
|
60 |
+
* @param string $checksum The checksum to add
|
61 |
+
* @param bool $inBinaryForm TRUE if checksum is in binary form
|
62 |
+
*
|
63 |
+
* @return self
|
64 |
+
* @throws \LogicException if the root tree hash is already calculated
|
65 |
+
*/
|
66 |
+
public function addChecksum($checksum, $inBinaryForm = false)
|
67 |
+
{
|
68 |
+
// Error if hash is already calculated
|
69 |
+
if ($this->hash) {
|
70 |
+
throw new \LogicException('You may not add more checksums to a '
|
71 |
+
. 'complete tree hash.');
|
72 |
+
}
|
73 |
+
|
74 |
+
// Convert the checksum to binary form if necessary
|
75 |
+
$this->checksums[] = $inBinaryForm ? $checksum : hex2bin($checksum);
|
76 |
+
|
77 |
+
return $this;
|
78 |
+
}
|
79 |
+
|
80 |
+
public function complete()
|
81 |
+
{
|
82 |
+
if (!$this->hash) {
|
83 |
+
// Clear out the remaining buffer.
|
84 |
+
if ($this->buffer) {
|
85 |
+
$this->checksums[] = hash($this->algorithm, $this->buffer, true);
|
86 |
+
$this->buffer = '';
|
87 |
+
}
|
88 |
+
|
89 |
+
// If no hashes, add the EMPTY_HASH.
|
90 |
+
if (!$this->checksums) {
|
91 |
+
$this->checksums[] = hex2bin(self::EMPTY_HASH);
|
92 |
+
}
|
93 |
+
|
94 |
+
// Perform hashes up the tree to arrive at the root checksum.
|
95 |
+
$hashes = $this->checksums;
|
96 |
+
while (count($hashes) > 1) {
|
97 |
+
$sets = array_chunk($hashes, 2);
|
98 |
+
$hashes = array();
|
99 |
+
foreach ($sets as $set) {
|
100 |
+
$hashes[] = (count($set) === 1)
|
101 |
+
? $set[0]
|
102 |
+
: hash($this->algorithm, $set[0] . $set[1], true);
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
$this->hash = $hashes[0];
|
107 |
+
}
|
108 |
+
|
109 |
+
return $this->hash;
|
110 |
+
}
|
111 |
+
|
112 |
+
public function reset()
|
113 |
+
{
|
114 |
+
$this->hash = null;
|
115 |
+
$this->checksums = [];
|
116 |
+
$this->buffer = '';
|
117 |
+
}
|
118 |
+
}
|
includes/aws/Aws/Handler/GuzzleV5/GuzzleHandler.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Handler\GuzzleV5;
|
3 |
+
|
4 |
+
use Aws\Sdk;
|
5 |
+
use Exception;
|
6 |
+
use GuzzleHttp\Client;
|
7 |
+
use GuzzleHttp\ClientInterface;
|
8 |
+
use GuzzleHttp\Exception\ConnectException;
|
9 |
+
use GuzzleHttp\Exception\RequestException;
|
10 |
+
use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
|
11 |
+
use GuzzleHttp\Promise;
|
12 |
+
use GuzzleHttp\Psr7\Response as Psr7Response;
|
13 |
+
use Psr\Http\Message\RequestInterface as Psr7Request;
|
14 |
+
use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* A request handler that sends PSR-7-compatible requests with Guzzle 5.
|
18 |
+
*
|
19 |
+
* The handler accepts a PSR-7 Request object and an array of transfer options
|
20 |
+
* and returns a Guzzle 6 Promise. The promise is either resolved with a
|
21 |
+
* PSR-7 Response object or rejected with an array of error data.
|
22 |
+
*
|
23 |
+
* @codeCoverageIgnore
|
24 |
+
*/
|
25 |
+
class GuzzleHandler
|
26 |
+
{
|
27 |
+
private static $validOptions = [
|
28 |
+
'proxy' => true,
|
29 |
+
'verify' => true,
|
30 |
+
'timeout' => true,
|
31 |
+
'debug' => true,
|
32 |
+
'connect_timeout' => true,
|
33 |
+
'stream' => true,
|
34 |
+
'delay' => true,
|
35 |
+
'sink' => true,
|
36 |
+
];
|
37 |
+
|
38 |
+
/** @var ClientInterface */
|
39 |
+
private $client;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @param ClientInterface $client
|
43 |
+
*/
|
44 |
+
public function __construct(ClientInterface $client = null)
|
45 |
+
{
|
46 |
+
$this->client = $client ?: new Client();
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param Psr7Request $request
|
51 |
+
* @param array $options
|
52 |
+
*
|
53 |
+
* @return Promise\Promise
|
54 |
+
*/
|
55 |
+
public function __invoke(Psr7Request $request, array $options = [])
|
56 |
+
{
|
57 |
+
// Create and send a Guzzle 5 request
|
58 |
+
$guzzlePromise = $this->client->send(
|
59 |
+
$this->createGuzzleRequest($request, $options)
|
60 |
+
);
|
61 |
+
|
62 |
+
$promise = new Promise\Promise(
|
63 |
+
function () use ($guzzlePromise) {
|
64 |
+
try {
|
65 |
+
$guzzlePromise->wait();
|
66 |
+
} catch (\Exception $e) {
|
67 |
+
// The promise is already delivered when the exception is
|
68 |
+
// thrown, so don't rethrow it.
|
69 |
+
}
|
70 |
+
},
|
71 |
+
[$guzzlePromise, 'cancel']
|
72 |
+
);
|
73 |
+
|
74 |
+
$guzzlePromise->then([$promise, 'resolve'], [$promise, 'reject']);
|
75 |
+
|
76 |
+
return $promise->then(
|
77 |
+
function (GuzzleResponse $response) {
|
78 |
+
// Adapt the Guzzle 5 Future to a Guzzle 6 ResponsePromise.
|
79 |
+
return $this->createPsr7Response($response);
|
80 |
+
},
|
81 |
+
function (Exception $exception) {
|
82 |
+
// Reject with information about the error.
|
83 |
+
return new Promise\RejectedPromise($this->prepareErrorData($exception));
|
84 |
+
}
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
private function createGuzzleRequest(Psr7Request $psrRequest, array $options)
|
89 |
+
{
|
90 |
+
$ringConfig = [];
|
91 |
+
|
92 |
+
// Remove unsupported options.
|
93 |
+
foreach (array_keys($options) as $key) {
|
94 |
+
if (!isset(self::$validOptions[$key])) {
|
95 |
+
unset($options[$key]);
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
// Handle delay option.
|
100 |
+
if (isset($options['delay'])) {
|
101 |
+
$ringConfig['delay'] = $options['delay'];
|
102 |
+
unset($options['delay']);
|
103 |
+
}
|
104 |
+
|
105 |
+
// Prepare sink option.
|
106 |
+
if (isset($options['sink'])) {
|
107 |
+
$ringConfig['save_to'] = ($options['sink'] instanceof Psr7StreamInterface)
|
108 |
+
? new GuzzleStream($options['sink'])
|
109 |
+
: $options['sink'];
|
110 |
+
unset($options['sink']);
|
111 |
+
}
|
112 |
+
|
113 |
+
// Ensure that all requests are async and lazy like Guzzle 6.
|
114 |
+
$options['future'] = 'lazy';
|
115 |
+
|
116 |
+
// Create the Guzzle 5 request from the provided PSR7 request.
|
117 |
+
$request = $this->client->createRequest(
|
118 |
+
$psrRequest->getMethod(),
|
119 |
+
$psrRequest->getUri(),
|
120 |
+
$options
|
121 |
+
);
|
122 |
+
|
123 |
+
// For the request body, adapt the PSR stream to a Guzzle stream.
|
124 |
+
$body = $psrRequest->getBody();
|
125 |
+
if ($body->getSize() === 0) {
|
126 |
+
$request->setBody(null);
|
127 |
+
} else {
|
128 |
+
$request->setBody(new GuzzleStream($body));
|
129 |
+
}
|
130 |
+
|
131 |
+
$request->setHeaders($psrRequest->getHeaders());
|
132 |
+
|
133 |
+
$request->setHeader(
|
134 |
+
'User-Agent',
|
135 |
+
$request->getHeader('User-Agent')
|
136 |
+
. ' ' . Client::getDefaultUserAgent()
|
137 |
+
);
|
138 |
+
|
139 |
+
// Make sure the delay is configured, if provided.
|
140 |
+
if ($ringConfig) {
|
141 |
+
foreach ($ringConfig as $k => $v) {
|
142 |
+
$request->getConfig()->set($k, $v);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
return $request;
|
147 |
+
}
|
148 |
+
|
149 |
+
private function createPsr7Response(GuzzleResponse $response)
|
150 |
+
{
|
151 |
+
if ($body = $response->getBody()) {
|
152 |
+
$body = new PsrStream($body);
|
153 |
+
}
|
154 |
+
|
155 |
+
return new Psr7Response(
|
156 |
+
$response->getStatusCode(),
|
157 |
+
$response->getHeaders(),
|
158 |
+
$body,
|
159 |
+
$response->getReasonPhrase()
|
160 |
+
);
|
161 |
+
}
|
162 |
+
|
163 |
+
private function prepareErrorData(Exception $e)
|
164 |
+
{
|
165 |
+
$error = [
|
166 |
+
'exception' => $e,
|
167 |
+
'connection_error' => false,
|
168 |
+
'response' => null,
|
169 |
+
];
|
170 |
+
|
171 |
+
if ($e instanceof ConnectException) {
|
172 |
+
$error['connection_error'] = true;
|
173 |
+
}
|
174 |
+
|
175 |
+
if ($e instanceof RequestException && $e->getResponse()) {
|
176 |
+
$error['response'] = $this->createPsr7Response($e->getResponse());
|
177 |
+
}
|
178 |
+
|
179 |
+
return $error;
|
180 |
+
}
|
181 |
+
}
|
includes/aws/Aws/Handler/GuzzleV5/GuzzleStream.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Handler\GuzzleV5;
|
3 |
+
|
4 |
+
use GuzzleHttp\Stream\StreamDecoratorTrait;
|
5 |
+
use GuzzleHttp\Stream\StreamInterface as GuzzleStreamInterface;
|
6 |
+
use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Adapts a PSR-7 Stream to a Guzzle 5 Stream.
|
10 |
+
*
|
11 |
+
* @codeCoverageIgnore
|
12 |
+
*/
|
13 |
+
class GuzzleStream implements GuzzleStreamInterface
|
14 |
+
{
|
15 |
+
use StreamDecoratorTrait;
|
16 |
+
|
17 |
+
/** @var Psr7StreamInterface */
|
18 |
+
private $stream;
|
19 |
+
|
20 |
+
public function __construct(Psr7StreamInterface $stream)
|
21 |
+
{
|
22 |
+
$this->stream = $stream;
|
23 |
+
}
|
24 |
+
}
|
includes/aws/Aws/Handler/GuzzleV5/PsrStream.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Handler\GuzzleV5;
|
3 |
+
|
4 |
+
use GuzzleHttp\Stream\StreamDecoratorTrait;
|
5 |
+
use GuzzleHttp\Stream\StreamInterface as GuzzleStreamInterface;
|
6 |
+
use Psr\Http\Message\StreamInterface as Psr7StreamInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Adapts a Guzzle 5 Stream to a PSR-7 Stream.
|
10 |
+
*
|
11 |
+
* @codeCoverageIgnore
|
12 |
+
*/
|
13 |
+
class PsrStream implements Psr7StreamInterface
|
14 |
+
{
|
15 |
+
use StreamDecoratorTrait;
|
16 |
+
|
17 |
+
/** @var GuzzleStreamInterface */
|
18 |
+
private $stream;
|
19 |
+
|
20 |
+
public function __construct(GuzzleStreamInterface $stream)
|
21 |
+
{
|
22 |
+
$this->stream = $stream;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function rewind()
|
26 |
+
{
|
27 |
+
$this->stream->seek(0);
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getContents()
|
31 |
+
{
|
32 |
+
return $this->stream->getContents();
|
33 |
+
}
|
34 |
+
}
|
includes/aws/Aws/Handler/GuzzleV6/GuzzleHandler.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Handler\GuzzleV6;
|
3 |
+
|
4 |
+
use Aws\Sdk;
|
5 |
+
use Exception;
|
6 |
+
use GuzzleHttp\Exception\ConnectException;
|
7 |
+
use GuzzleHttp\Exception\RequestException;
|
8 |
+
use GuzzleHttp\Promise;
|
9 |
+
use GuzzleHttp\Client;
|
10 |
+
use GuzzleHttp\ClientInterface;
|
11 |
+
use Psr\Http\Message\RequestInterface as Psr7Request;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* A request handler that sends PSR-7-compatible requests with Guzzle 6.
|
15 |
+
*/
|
16 |
+
class GuzzleHandler
|
17 |
+
{
|
18 |
+
/** @var ClientInterface */
|
19 |
+
private $client;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param ClientInterface $client
|
23 |
+
*/
|
24 |
+
public function __construct(ClientInterface $client = null)
|
25 |
+
{
|
26 |
+
$this->client = $client ?: new Client();
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param Psr7Request $request
|
31 |
+
* @param array $options
|
32 |
+
*
|
33 |
+
* @return Promise\Promise
|
34 |
+
*/
|
35 |
+
public function __invoke(Psr7Request $request, array $options = [])
|
36 |
+
{
|
37 |
+
$request = $request->withHeader(
|
38 |
+
'User-Agent',
|
39 |
+
$request->getHeaderLine('User-Agent')
|
40 |
+
. ' ' . \GuzzleHttp\default_user_agent()
|
41 |
+
);
|
42 |
+
|
43 |
+
return $this->client->sendAsync($request, $options)->otherwise(
|
44 |
+
static function (\Exception $e) {
|
45 |
+
$error = [
|
46 |
+
'exception' => $e,
|
47 |
+
'connection_error' => $e instanceof ConnectException,
|
48 |
+
'response' => null,
|
49 |
+
];
|
50 |
+
|
51 |
+
if ($e instanceof RequestException && $e->getResponse()) {
|
52 |
+
$error['response'] = $e->getResponse();
|
53 |
+
}
|
54 |
+
|
55 |
+
return new Promise\RejectedPromise($error);
|
56 |
+
}
|
57 |
+
);
|
58 |
+
}
|
59 |
+
}
|
includes/aws/Aws/HandlerList.php
ADDED
@@ -0,0 +1,424 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Builds a single handler function from zero or more middleware functions and
|
6 |
+
* a handler. The handler function is then used to send command objects and
|
7 |
+
* return a promise that is resolved with an AWS result object.
|
8 |
+
*
|
9 |
+
* The "front" of the list is invoked before the "end" of the list. You can add
|
10 |
+
* middleware to the front of the list using one of the "prepend" method, and
|
11 |
+
* the end of the list using one of the "append" method. The last function
|
12 |
+
* invoked in a handler list is the handler (a function that does not accept a
|
13 |
+
* next handler but rather is responsible for returning a promise that is
|
14 |
+
* fulfilled with an Aws\ResultInterface object).
|
15 |
+
*
|
16 |
+
* Handlers are ordered using a "step" that describes the step at which the
|
17 |
+
* SDK is when sending a command. The available steps are:
|
18 |
+
*
|
19 |
+
* - init: The command is being initialized, allowing you to do things like add
|
20 |
+
* default options.
|
21 |
+
* - validate: The command is being validated before it is serialized
|
22 |
+
* - build: The command is being serialized into an HTTP request. A middleware
|
23 |
+
* in this step MUST serialize an HTTP request and populate the "@request"
|
24 |
+
* parameter of a command with the request such that it is available to
|
25 |
+
* subsequent middleware.
|
26 |
+
* - sign: The request is being signed and prepared to be sent over the wire.
|
27 |
+
*
|
28 |
+
* Middleware can be registered with a name to allow you to easily add a
|
29 |
+
* middleware before or after another middleware by name. This also allows you
|
30 |
+
* to remove a middleware by name (in addition to removing by instance).
|
31 |
+
*/
|
32 |
+
class HandlerList implements \Countable
|
33 |
+
{
|
34 |
+
const INIT = 'init';
|
35 |
+
const VALIDATE = 'validate';
|
36 |
+
const BUILD = 'build';
|
37 |
+
const SIGN = 'sign';
|
38 |
+
|
39 |
+
/** @var callable */
|
40 |
+
private $handler;
|
41 |
+
|
42 |
+
/** @var array */
|
43 |
+
private $named = [];
|
44 |
+
|
45 |
+
/** @var array */
|
46 |
+
private $sorted;
|
47 |
+
|
48 |
+
/** @var callable|null */
|
49 |
+
private $interposeFn;
|
50 |
+
|
51 |
+
/** @var array Steps (in reverse order) */
|
52 |
+
private $steps = [
|
53 |
+
self::SIGN => [],
|
54 |
+
self::BUILD => [],
|
55 |
+
self::VALIDATE => [],
|
56 |
+
self::INIT => [],
|
57 |
+
];
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @param callable $handler HTTP handler.
|
61 |
+
*/
|
62 |
+
public function __construct(callable $handler = null)
|
63 |
+
{
|
64 |
+
$this->handler = $handler;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Dumps a string representation of the list.
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function __toString()
|
73 |
+
{
|
74 |
+
$str = '';
|
75 |
+
$i = 0;
|
76 |
+
|
77 |
+
foreach (array_reverse($this->steps) as $k => $step) {
|
78 |
+
foreach (array_reverse($step) as $j => $tuple) {
|
79 |
+
$str .= "{$i}) Step: {$k}, ";
|
80 |
+
if ($tuple[1]) {
|
81 |
+
$str .= "Name: {$tuple[1]}, ";
|
82 |
+
}
|
83 |
+
$str .= "Function: " . $this->debugCallable($tuple[0]) . "\n";
|
84 |
+
$i++;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
if ($this->handler) {
|
89 |
+
$str .= "{$i}) Handler: " . $this->debugCallable($this->handler) . "\n";
|
90 |
+
}
|
91 |
+
|
92 |
+
return $str;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Set the HTTP handler that actually returns a response.
|
97 |
+
*
|
98 |
+
* @param callable $handler Function that accepts a request and array of
|
99 |
+
* options and returns a Promise.
|
100 |
+
*/
|
101 |
+
public function setHandler(callable $handler)
|
102 |
+
{
|
103 |
+
$this->handler = $handler;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Returns true if the builder has a handler.
|
108 |
+
*
|
109 |
+
* @return bool
|
110 |
+
*/
|
111 |
+
public function hasHandler()
|
112 |
+
{
|
113 |
+
return (bool) $this->handler;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Append a middleware to the init step.
|
118 |
+
*
|
119 |
+
* @param callable $middleware Middleware function to add.
|
120 |
+
* @param string $name Name of the middleware.
|
121 |
+
*/
|
122 |
+
public function appendInit(callable $middleware, $name = null)
|
123 |
+
{
|
124 |
+
$this->add(self::INIT, $name, $middleware);
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Prepend a middleware to the init step.
|
129 |
+
*
|
130 |
+
* @param callable $middleware Middleware function to add.
|
131 |
+
* @param string $name Name of the middleware.
|
132 |
+
*/
|
133 |
+
public function prependInit(callable $middleware, $name = null)
|
134 |
+
{
|
135 |
+
$this->add(self::INIT, $name, $middleware, true);
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Append a middleware to the validate step.
|
140 |
+
*
|
141 |
+
* @param callable $middleware Middleware function to add.
|
142 |
+
* @param string $name Name of the middleware.
|
143 |
+
*/
|
144 |
+
public function appendValidate(callable $middleware, $name = null)
|
145 |
+
{
|
146 |
+
$this->add(self::VALIDATE, $name, $middleware);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Prepend a middleware to the validate step.
|
151 |
+
*
|
152 |
+
* @param callable $middleware Middleware function to add.
|
153 |
+
* @param string $name Name of the middleware.
|
154 |
+
*/
|
155 |
+
public function prependValidate(callable $middleware, $name = null)
|
156 |
+
{
|
157 |
+
$this->add(self::VALIDATE, $name, $middleware, true);
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Append a middleware to the build step.
|
162 |
+
*
|
163 |
+
* @param callable $middleware Middleware function to add.
|
164 |
+
* @param string $name Name of the middleware.
|
165 |
+
*/
|
166 |
+
public function appendBuild(callable $middleware, $name = null)
|
167 |
+
{
|
168 |
+
$this->add(self::BUILD, $name, $middleware);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Prepend a middleware to the build step.
|
173 |
+
*
|
174 |
+
* @param callable $middleware Middleware function to add.
|
175 |
+
* @param string $name Name of the middleware.
|
176 |
+
*/
|
177 |
+
public function prependBuild(callable $middleware, $name = null)
|
178 |
+
{
|
179 |
+
$this->add(self::BUILD, $name, $middleware, true);
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Append a middleware to the sign step.
|
184 |
+
*
|
185 |
+
* @param callable $middleware Middleware function to add.
|
186 |
+
* @param string $name Name of the middleware.
|
187 |
+
*/
|
188 |
+
public function appendSign(callable $middleware, $name = null)
|
189 |
+
{
|
190 |
+
$this->add(self::SIGN, $name, $middleware);
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Prepend a middleware to the sign step.
|
195 |
+
*
|
196 |
+
* @param callable $middleware Middleware function to add.
|
197 |
+
* @param string $name Name of the middleware.
|
198 |
+
*/
|
199 |
+
public function prependSign(callable $middleware, $name = null)
|
200 |
+
{
|
201 |
+
$this->add(self::SIGN, $name, $middleware, true);
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Add a middleware before the given middleware by name.
|
206 |
+
*
|
207 |
+
* @param string|callable $findName Add before this
|
208 |
+
* @param string $withName Optional name to give the middleware
|
209 |
+
* @param callable $middleware Middleware to add.
|
210 |
+
*/
|
211 |
+
public function before($findName, $withName, callable $middleware)
|
212 |
+
{
|
213 |
+
$this->splice($findName, $withName, $middleware, true);
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Add a middleware after the given middleware by name.
|
218 |
+
*
|
219 |
+
* @param string|callable $findName Add after this
|
220 |
+
* @param string $withName Optional name to give the middleware
|
221 |
+
* @param callable $middleware Middleware to add.
|
222 |
+
*/
|
223 |
+
public function after($findName, $withName, callable $middleware)
|
224 |
+
{
|
225 |
+
$this->splice($findName, $withName, $middleware, false);
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Remove a middleware by name or by instance from the list.
|
230 |
+
*
|
231 |
+
* @param string|callable $nameOrInstance Middleware to remove.
|
232 |
+
*/
|
233 |
+
public function remove($nameOrInstance)
|
234 |
+
{
|
235 |
+
if (is_callable($nameOrInstance)) {
|
236 |
+
$this->removeByInstance($nameOrInstance);
|
237 |
+
} elseif (is_string($nameOrInstance)) {
|
238 |
+
$this->removeByName($nameOrInstance);
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Interpose a function between each middleware (e.g., allowing for a trace
|
244 |
+
* through the middleware layers).
|
245 |
+
*
|
246 |
+
* The interpose function is a function that accepts a "step" argument as a
|
247 |
+
* string and a "name" argument string. This function must then return a
|
248 |
+
* function that accepts the next handler in the list. This function must
|
249 |
+
* then return a function that accepts a CommandInterface and optional
|
250 |
+
* RequestInterface and returns a promise that is fulfilled with an
|
251 |
+
* Aws\ResultInterface or rejected with an Aws\Exception\AwsException
|
252 |
+
* object.
|
253 |
+
*
|
254 |
+
* @param callable|null $fn Pass null to remove any previously set function
|
255 |
+
*/
|
256 |
+
public function interpose(callable $fn = null)
|
257 |
+
{
|
258 |
+
$this->sorted = null;
|
259 |
+
$this->interposeFn = $fn;
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Compose the middleware and handler into a single callable function.
|
264 |
+
*
|
265 |
+
* @return callable
|
266 |
+
*/
|
267 |
+
public function resolve()
|
268 |
+
{
|
269 |
+
if (!($prev = $this->handler)) {
|
270 |
+
throw new \LogicException('No handler has been specified');
|
271 |
+
}
|
272 |
+
|
273 |
+
if ($this->sorted === null) {
|
274 |
+
$this->sortMiddleware();
|
275 |
+
}
|
276 |
+
|
277 |
+
foreach ($this->sorted as $fn) {
|
278 |
+
$prev = $fn($prev);
|
279 |
+
}
|
280 |
+
|
281 |
+
return $prev;
|
282 |
+
}
|
283 |
+
|
284 |
+
public function count()
|
285 |
+
{
|
286 |
+
return count($this->steps[self::INIT])
|
287 |
+
+ count($this->steps[self::VALIDATE])
|
288 |
+
+ count($this->steps[self::BUILD])
|
289 |
+
+ count($this->steps[self::SIGN]);
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Splices a function into the middleware list at a specific position.
|
294 |
+
*
|
295 |
+
* @param $findName
|
296 |
+
* @param $withName
|
297 |
+
* @param callable $middleware
|
298 |
+
* @param $before
|
299 |
+
*/
|
300 |
+
private function splice($findName, $withName, callable $middleware, $before)
|
301 |
+
{
|
302 |
+
if (!isset($this->named[$findName])) {
|
303 |
+
throw new \InvalidArgumentException("$findName not found");
|
304 |
+
}
|
305 |
+
|
306 |
+
$idx = $this->sorted = null;
|
307 |
+
$step = $this->named[$findName];
|
308 |
+
|
309 |
+
if ($withName) {
|
310 |
+
$this->named[$withName] = $step;
|
311 |
+
}
|
312 |
+
|
313 |
+
foreach ($this->steps[$step] as $i => $tuple) {
|
314 |
+
if ($tuple[1] === $findName) {
|
315 |
+
$idx = $i;
|
316 |
+
break;
|
317 |
+
}
|
318 |
+
}
|
319 |
+
|
320 |
+
$replacement = $before
|
321 |
+
? [$this->steps[$step][$idx], [$middleware, $withName]]
|
322 |
+
: [[$middleware, $withName], $this->steps[$step][$idx]];
|
323 |
+
array_splice($this->steps[$step], $idx, 1, $replacement);
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Provides a debug string for a given callable.
|
328 |
+
*
|
329 |
+
* @param array|callable $fn Function to write as a string.
|
330 |
+
*
|
331 |
+
* @return string
|
332 |
+
*/
|
333 |
+
private function debugCallable($fn)
|
334 |
+
{
|
335 |
+
if (is_string($fn)) {
|
336 |
+
return "callable({$fn})";
|
337 |
+
} elseif (is_array($fn)) {
|
338 |
+
$ele = is_string($fn[0]) ? $fn[0] : get_class($fn[0]);
|
339 |
+
return "callable(['{$ele}', '{$fn[1]}'])";
|
340 |
+
} else {
|
341 |
+
return 'callable(' . spl_object_hash($fn) . ')';
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Sort the middleware, and interpose if needed in the sorted list.
|
347 |
+
*/
|
348 |
+
private function sortMiddleware()
|
349 |
+
{
|
350 |
+
$this->sorted = [];
|
351 |
+
|
352 |
+
if (!$this->interposeFn) {
|
353 |
+
foreach ($this->steps as $step) {
|
354 |
+
foreach ($step as $fn) {
|
355 |
+
$this->sorted[] = $fn[0];
|
356 |
+
}
|
357 |
+
}
|
358 |
+
return;
|
359 |
+
}
|
360 |
+
|
361 |
+
$ifn = $this->interposeFn;
|
362 |
+
// Interpose the interposeFn into the handler stack.
|
363 |
+
foreach ($this->steps as $stepName => $step) {
|
364 |
+
foreach ($step as $fn) {
|
365 |
+
$this->sorted[] = $ifn($stepName, $fn[1]);
|
366 |
+
$this->sorted[] = $fn[0];
|
367 |
+
}
|
368 |
+
}
|
369 |
+
}
|
370 |
+
|
371 |
+
private function removeByName($name)
|
372 |
+
{
|
373 |
+
if (!isset($this->named[$name])) {
|
374 |
+
return;
|
375 |
+
}
|
376 |
+
|
377 |
+
$this->sorted = null;
|
378 |
+
$step = $this->named[$name];
|
379 |
+
$this->steps[$step] = array_values(
|
380 |
+
array_filter(
|
381 |
+
$this->steps[$step],
|
382 |
+
function ($tuple) use ($name) {
|
383 |
+
return $tuple[1] !== $name;
|
384 |
+
}
|
385 |
+
)
|
386 |
+
);
|
387 |
+
}
|
388 |
+
|
389 |
+
private function removeByInstance(callable $fn)
|
390 |
+
{
|
391 |
+
foreach ($this->steps as $k => $step) {
|
392 |
+
foreach ($step as $j => $tuple) {
|
393 |
+
if ($tuple[0] === $fn) {
|
394 |
+
$this->sorted = null;
|
395 |
+
unset($this->named[$this->steps[$k][$j][1]]);
|
396 |
+
unset($this->steps[$k][$j]);
|
397 |
+
}
|
398 |
+
}
|
399 |
+
}
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Add a middleware to a step.
|
404 |
+
*
|
405 |
+
* @param string $step Middleware step.
|
406 |
+
* @param string $name Middleware name.
|
407 |
+
* @param callable $middleware Middleware function to add.
|
408 |
+
* @param bool $prepend Prepend instead of append.
|
409 |
+
*/
|
410 |
+
private function add($step, $name, callable $middleware, $prepend = false)
|
411 |
+
{
|
412 |
+
$this->sorted = null;
|
413 |
+
|
414 |
+
if ($prepend) {
|
415 |
+
$this->steps[$step][] = [$middleware, $name];
|
416 |
+
} else {
|
417 |
+
array_unshift($this->steps[$step], [$middleware, $name]);
|
418 |
+
}
|
419 |
+
|
420 |
+
if ($name) {
|
421 |
+
$this->named[$name] = $step;
|
422 |
+
}
|
423 |
+
}
|
424 |
+
}
|
includes/aws/Aws/HasDataTrait.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Trait implementing ToArrayInterface, \ArrayAccess, \Countable, and
|
6 |
+
* \IteratorAggregate
|
7 |
+
*/
|
8 |
+
trait HasDataTrait
|
9 |
+
{
|
10 |
+
/** @var array */
|
11 |
+
private $data = [];
|
12 |
+
|
13 |
+
public function getIterator()
|
14 |
+
{
|
15 |
+
return new \ArrayIterator($this->data);
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* This method returns a reference to the variable to allow for indirect
|
20 |
+
* array modification (e.g., $foo['bar']['baz'] = 'qux').
|
21 |
+
*
|
22 |
+
* @param $offset
|
23 |
+
*
|
24 |
+
* @return mixed|null
|
25 |
+
*/
|
26 |
+
public function & offsetGet($offset)
|
27 |
+
{
|
28 |
+
if (isset($this->data[$offset])) {
|
29 |
+
return $this->data[$offset];
|
30 |
+
}
|
31 |
+
|
32 |
+
$value = null;
|
33 |
+
return $value;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function offsetSet($offset, $value)
|
37 |
+
{
|
38 |
+
$this->data[$offset] = $value;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function offsetExists($offset)
|
42 |
+
{
|
43 |
+
return isset($this->data[$offset]);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function offsetUnset($offset)
|
47 |
+
{
|
48 |
+
unset($this->data[$offset]);
|
49 |
+
}
|
50 |
+
|
51 |
+
public function toArray()
|
52 |
+
{
|
53 |
+
return $this->data;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function count()
|
57 |
+
{
|
58 |
+
return count($this->data);
|
59 |
+
}
|
60 |
+
}
|
includes/aws/Aws/HashInterface.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Interface that allows implementing various incremental hashes.
|
6 |
+
*/
|
7 |
+
interface HashInterface
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Adds data to the hash.
|
11 |
+
*
|
12 |
+
* @param string $data Data to add to the hash
|
13 |
+
*/
|
14 |
+
public function update($data);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Finalizes the incremental hash and returns the resulting digest.
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
public function complete();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Removes all data from the hash, effectively starting a new hash.
|
25 |
+
*/
|
26 |
+
public function reset();
|
27 |
+
}
|
includes/aws/Aws/HashingStream.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
5 |
+
use Psr\Http\Message\StreamInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Stream decorator that calculates a rolling hash of the stream as it is read.
|
9 |
+
*/
|
10 |
+
class HashingStream implements StreamInterface
|
11 |
+
{
|
12 |
+
use StreamDecoratorTrait;
|
13 |
+
|
14 |
+
/** @var HashInterface */
|
15 |
+
private $hash;
|
16 |
+
|
17 |
+
/** @var callable|null */
|
18 |
+
private $callback;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param StreamInterface $stream Stream that is being read.
|
22 |
+
* @param HashInterface $hash Hash used to calculate checksum.
|
23 |
+
* @param callable $onComplete Optional function invoked when the
|
24 |
+
* hash calculation is completed.
|
25 |
+
*/
|
26 |
+
public function __construct(
|
27 |
+
StreamInterface $stream,
|
28 |
+
HashInterface $hash,
|
29 |
+
callable $onComplete = null
|
30 |
+
) {
|
31 |
+
$this->stream = $stream;
|
32 |
+
$this->hash = $hash;
|
33 |
+
$this->callback = $onComplete;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function read($length)
|
37 |
+
{
|
38 |
+
$data = $this->stream->read($length);
|
39 |
+
$this->hash->update($data);
|
40 |
+
if ($this->eof()) {
|
41 |
+
$result = $this->hash->complete();
|
42 |
+
if ($this->callback) {
|
43 |
+
call_user_func($this->callback, $result);
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
return $data;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function seek($offset, $whence = SEEK_SET)
|
51 |
+
{
|
52 |
+
if ($offset === 0) {
|
53 |
+
$this->hash->reset();
|
54 |
+
return $this->stream->seek($offset);
|
55 |
+
} else {
|
56 |
+
// Seeking arbitrarily is not supported.
|
57 |
+
return false;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
includes/aws/Aws/History.php
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Aws\Exception\AwsException;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Represents a history container that is required when using the history
|
9 |
+
* middleware.
|
10 |
+
*/
|
11 |
+
class History implements \Countable, \IteratorAggregate
|
12 |
+
{
|
13 |
+
private $maxEntries;
|
14 |
+
private $entries;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @param int $maxEntries Maximum number of entries to store.
|
18 |
+
*/
|
19 |
+
public function __construct($maxEntries = 10)
|
20 |
+
{
|
21 |
+
$this->maxEntries = $maxEntries;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function count()
|
25 |
+
{
|
26 |
+
return count($this->entries);
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getIterator()
|
30 |
+
{
|
31 |
+
return new \ArrayIterator(array_values($this->entries));
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Get the last finished command seen by the history container.
|
36 |
+
*
|
37 |
+
* @return CommandInterface
|
38 |
+
* @throws \LogicException if no commands have been seen.
|
39 |
+
*/
|
40 |
+
public function getLastCommand()
|
41 |
+
{
|
42 |
+
if (!$this->entries) {
|
43 |
+
throw new \LogicException('No commands received');
|
44 |
+
}
|
45 |
+
|
46 |
+
return end($this->entries)['command'];
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Get the last finished request seen by the history container.
|
51 |
+
*
|
52 |
+
* @return RequestInterface
|
53 |
+
* @throws \LogicException if no requests have been seen.
|
54 |
+
*/
|
55 |
+
public function getLastRequest()
|
56 |
+
{
|
57 |
+
if (!$this->entries) {
|
58 |
+
throw new \LogicException('No requests received');
|
59 |
+
}
|
60 |
+
|
61 |
+
return end($this->entries)['request'];
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Get the last received result or exception.
|
66 |
+
*
|
67 |
+
* @return ResultInterface|AwsException
|
68 |
+
* @throws \LogicException if no return values have been received.
|
69 |
+
*/
|
70 |
+
public function getLastReturn()
|
71 |
+
{
|
72 |
+
if (!$this->entries) {
|
73 |
+
throw new \LogicException('No entries');
|
74 |
+
}
|
75 |
+
|
76 |
+
$last = end($this->entries);
|
77 |
+
|
78 |
+
if (isset($last['result'])) {
|
79 |
+
return $last['result'];
|
80 |
+
} elseif (isset($last['exception'])) {
|
81 |
+
return $last['exception'];
|
82 |
+
} else {
|
83 |
+
throw new \LogicException('No return value for last entry.');
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Initiate an entry being added to the history.
|
89 |
+
*
|
90 |
+
* @param CommandInterface $cmd Command be executed.
|
91 |
+
* @param RequestInterface $req Request being sent.
|
92 |
+
*
|
93 |
+
* @return string Returns the ticket used to finish the entry.
|
94 |
+
*/
|
95 |
+
public function start(CommandInterface $cmd, RequestInterface $req)
|
96 |
+
{
|
97 |
+
$ticket = uniqid();
|
98 |
+
$this->entries[$ticket] = [
|
99 |
+
'command' => $cmd,
|
100 |
+
'request' => $req,
|
101 |
+
'result' => null,
|
102 |
+
'exception' => null,
|
103 |
+
];
|
104 |
+
|
105 |
+
return $ticket;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Finish adding an entry to the history container.
|
110 |
+
*
|
111 |
+
* @param string $ticket Ticket returned from the start call.
|
112 |
+
* @param mixed $result The result (an exception or AwsResult).
|
113 |
+
*/
|
114 |
+
public function finish($ticket, $result)
|
115 |
+
{
|
116 |
+
if (!isset($this->entries[$ticket])) {
|
117 |
+
throw new \InvalidArgumentException('Invalid history ticket');
|
118 |
+
} elseif (isset($this->entries[$ticket]['result'])
|
119 |
+
|| isset($this->entries[$ticket]['exception'])
|
120 |
+
) {
|
121 |
+
throw new \LogicException('History entry is already finished');
|
122 |
+
}
|
123 |
+
|
124 |
+
if ($result instanceof \Exception) {
|
125 |
+
$this->entries[$ticket]['exception'] = $result;
|
126 |
+
} else {
|
127 |
+
$this->entries[$ticket]['result'] = $result;
|
128 |
+
}
|
129 |
+
|
130 |
+
if (count($this->entries) >= $this->maxEntries) {
|
131 |
+
$this->entries = array_slice($this->entries, -$this->maxEntries, null, true);
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Flush the history
|
137 |
+
*/
|
138 |
+
public function clear()
|
139 |
+
{
|
140 |
+
$this->entries = [];
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Converts the history to an array.
|
145 |
+
*
|
146 |
+
* @return array
|
147 |
+
*/
|
148 |
+
public function toArray()
|
149 |
+
{
|
150 |
+
return array_values($this->entries);
|
151 |
+
}
|
152 |
+
}
|
includes/aws/Aws/Iam/Exception/IamException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Iam\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the AWS Identity and Access Management service.
|
8 |
+
*/
|
9 |
+
class IamException extends AwsException {}
|
includes/aws/Aws/Iam/IamClient.php
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Iam;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **AWS Identity and Access Management (AWS IAM)** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result addClientIDToOpenIDConnectProvider(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise addClientIDToOpenIDConnectProviderAsync(array $args = [])
|
11 |
+
* @method \Aws\Result addRoleToInstanceProfile(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise addRoleToInstanceProfileAsync(array $args = [])
|
13 |
+
* @method \Aws\Result addUserToGroup(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise addUserToGroupAsync(array $args = [])
|
15 |
+
* @method \Aws\Result attachGroupPolicy(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise attachGroupPolicyAsync(array $args = [])
|
17 |
+
* @method \Aws\Result attachRolePolicy(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise attachRolePolicyAsync(array $args = [])
|
19 |
+
* @method \Aws\Result attachUserPolicy(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise attachUserPolicyAsync(array $args = [])
|
21 |
+
* @method \Aws\Result changePassword(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise changePasswordAsync(array $args = [])
|
23 |
+
* @method \Aws\Result createAccessKey(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise createAccessKeyAsync(array $args = [])
|
25 |
+
* @method \Aws\Result createAccountAlias(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise createAccountAliasAsync(array $args = [])
|
27 |
+
* @method \Aws\Result createGroup(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise createGroupAsync(array $args = [])
|
29 |
+
* @method \Aws\Result createInstanceProfile(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise createInstanceProfileAsync(array $args = [])
|
31 |
+
* @method \Aws\Result createLoginProfile(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise createLoginProfileAsync(array $args = [])
|
33 |
+
* @method \Aws\Result createOpenIDConnectProvider(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise createOpenIDConnectProviderAsync(array $args = [])
|
35 |
+
* @method \Aws\Result createPolicy(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise createPolicyAsync(array $args = [])
|
37 |
+
* @method \Aws\Result createPolicyVersion(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise createPolicyVersionAsync(array $args = [])
|
39 |
+
* @method \Aws\Result createRole(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise createRoleAsync(array $args = [])
|
41 |
+
* @method \Aws\Result createSAMLProvider(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise createSAMLProviderAsync(array $args = [])
|
43 |
+
* @method \Aws\Result createUser(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise createUserAsync(array $args = [])
|
45 |
+
* @method \Aws\Result createVirtualMFADevice(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise createVirtualMFADeviceAsync(array $args = [])
|
47 |
+
* @method \Aws\Result deactivateMFADevice(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise deactivateMFADeviceAsync(array $args = [])
|
49 |
+
* @method \Aws\Result deleteAccessKey(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise deleteAccessKeyAsync(array $args = [])
|
51 |
+
* @method \Aws\Result deleteAccountAlias(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise deleteAccountAliasAsync(array $args = [])
|
53 |
+
* @method \Aws\Result deleteAccountPasswordPolicy(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise deleteAccountPasswordPolicyAsync(array $args = [])
|
55 |
+
* @method \Aws\Result deleteGroup(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise deleteGroupAsync(array $args = [])
|
57 |
+
* @method \Aws\Result deleteGroupPolicy(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise deleteGroupPolicyAsync(array $args = [])
|
59 |
+
* @method \Aws\Result deleteInstanceProfile(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise deleteInstanceProfileAsync(array $args = [])
|
61 |
+
* @method \Aws\Result deleteLoginProfile(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise deleteLoginProfileAsync(array $args = [])
|
63 |
+
* @method \Aws\Result deleteOpenIDConnectProvider(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise deleteOpenIDConnectProviderAsync(array $args = [])
|
65 |
+
* @method \Aws\Result deletePolicy(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = [])
|
67 |
+
* @method \Aws\Result deletePolicyVersion(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise deletePolicyVersionAsync(array $args = [])
|
69 |
+
* @method \Aws\Result deleteRole(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise deleteRoleAsync(array $args = [])
|
71 |
+
* @method \Aws\Result deleteRolePolicy(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise deleteRolePolicyAsync(array $args = [])
|
73 |
+
* @method \Aws\Result deleteSAMLProvider(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise deleteSAMLProviderAsync(array $args = [])
|
75 |
+
* @method \Aws\Result deleteSSHPublicKey(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise deleteSSHPublicKeyAsync(array $args = [])
|
77 |
+
* @method \Aws\Result deleteServerCertificate(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise deleteServerCertificateAsync(array $args = [])
|
79 |
+
* @method \Aws\Result deleteSigningCertificate(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise deleteSigningCertificateAsync(array $args = [])
|
81 |
+
* @method \Aws\Result deleteUser(array $args = [])
|
82 |
+
* @method \GuzzleHttp\Promise\Promise deleteUserAsync(array $args = [])
|
83 |
+
* @method \Aws\Result deleteUserPolicy(array $args = [])
|
84 |
+
* @method \GuzzleHttp\Promise\Promise deleteUserPolicyAsync(array $args = [])
|
85 |
+
* @method \Aws\Result deleteVirtualMFADevice(array $args = [])
|
86 |
+
* @method \GuzzleHttp\Promise\Promise deleteVirtualMFADeviceAsync(array $args = [])
|
87 |
+
* @method \Aws\Result detachGroupPolicy(array $args = [])
|
88 |
+
* @method \GuzzleHttp\Promise\Promise detachGroupPolicyAsync(array $args = [])
|
89 |
+
* @method \Aws\Result detachRolePolicy(array $args = [])
|
90 |
+
* @method \GuzzleHttp\Promise\Promise detachRolePolicyAsync(array $args = [])
|
91 |
+
* @method \Aws\Result detachUserPolicy(array $args = [])
|
92 |
+
* @method \GuzzleHttp\Promise\Promise detachUserPolicyAsync(array $args = [])
|
93 |
+
* @method \Aws\Result enableMFADevice(array $args = [])
|
94 |
+
* @method \GuzzleHttp\Promise\Promise enableMFADeviceAsync(array $args = [])
|
95 |
+
* @method \Aws\Result generateCredentialReport(array $args = [])
|
96 |
+
* @method \GuzzleHttp\Promise\Promise generateCredentialReportAsync(array $args = [])
|
97 |
+
* @method \Aws\Result getAccessKeyLastUsed(array $args = [])
|
98 |
+
* @method \GuzzleHttp\Promise\Promise getAccessKeyLastUsedAsync(array $args = [])
|
99 |
+
* @method \Aws\Result getAccountAuthorizationDetails(array $args = [])
|
100 |
+
* @method \GuzzleHttp\Promise\Promise getAccountAuthorizationDetailsAsync(array $args = [])
|
101 |
+
* @method \Aws\Result getAccountPasswordPolicy(array $args = [])
|
102 |
+
* @method \GuzzleHttp\Promise\Promise getAccountPasswordPolicyAsync(array $args = [])
|
103 |
+
* @method \Aws\Result getAccountSummary(array $args = [])
|
104 |
+
* @method \GuzzleHttp\Promise\Promise getAccountSummaryAsync(array $args = [])
|
105 |
+
* @method \Aws\Result getContextKeysForCustomPolicy(array $args = [])
|
106 |
+
* @method \GuzzleHttp\Promise\Promise getContextKeysForCustomPolicyAsync(array $args = [])
|
107 |
+
* @method \Aws\Result getContextKeysForPrincipalPolicy(array $args = [])
|
108 |
+
* @method \GuzzleHttp\Promise\Promise getContextKeysForPrincipalPolicyAsync(array $args = [])
|
109 |
+
* @method \Aws\Result getCredentialReport(array $args = [])
|
110 |
+
* @method \GuzzleHttp\Promise\Promise getCredentialReportAsync(array $args = [])
|
111 |
+
* @method \Aws\Result getGroup(array $args = [])
|
112 |
+
* @method \GuzzleHttp\Promise\Promise getGroupAsync(array $args = [])
|
113 |
+
* @method \Aws\Result getGroupPolicy(array $args = [])
|
114 |
+
* @method \GuzzleHttp\Promise\Promise getGroupPolicyAsync(array $args = [])
|
115 |
+
* @method \Aws\Result getInstanceProfile(array $args = [])
|
116 |
+
* @method \GuzzleHttp\Promise\Promise getInstanceProfileAsync(array $args = [])
|
117 |
+
* @method \Aws\Result getLoginProfile(array $args = [])
|
118 |
+
* @method \GuzzleHttp\Promise\Promise getLoginProfileAsync(array $args = [])
|
119 |
+
* @method \Aws\Result getOpenIDConnectProvider(array $args = [])
|
120 |
+
* @method \GuzzleHttp\Promise\Promise getOpenIDConnectProviderAsync(array $args = [])
|
121 |
+
* @method \Aws\Result getPolicy(array $args = [])
|
122 |
+
* @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = [])
|
123 |
+
* @method \Aws\Result getPolicyVersion(array $args = [])
|
124 |
+
* @method \GuzzleHttp\Promise\Promise getPolicyVersionAsync(array $args = [])
|
125 |
+
* @method \Aws\Result getRole(array $args = [])
|
126 |
+
* @method \GuzzleHttp\Promise\Promise getRoleAsync(array $args = [])
|
127 |
+
* @method \Aws\Result getRolePolicy(array $args = [])
|
128 |
+
* @method \GuzzleHttp\Promise\Promise getRolePolicyAsync(array $args = [])
|
129 |
+
* @method \Aws\Result getSAMLProvider(array $args = [])
|
130 |
+
* @method \GuzzleHttp\Promise\Promise getSAMLProviderAsync(array $args = [])
|
131 |
+
* @method \Aws\Result getSSHPublicKey(array $args = [])
|
132 |
+
* @method \GuzzleHttp\Promise\Promise getSSHPublicKeyAsync(array $args = [])
|
133 |
+
* @method \Aws\Result getServerCertificate(array $args = [])
|
134 |
+
* @method \GuzzleHttp\Promise\Promise getServerCertificateAsync(array $args = [])
|
135 |
+
* @method \Aws\Result getUser(array $args = [])
|
136 |
+
* @method \GuzzleHttp\Promise\Promise getUserAsync(array $args = [])
|
137 |
+
* @method \Aws\Result getUserPolicy(array $args = [])
|
138 |
+
* @method \GuzzleHttp\Promise\Promise getUserPolicyAsync(array $args = [])
|
139 |
+
* @method \Aws\Result listAccessKeys(array $args = [])
|
140 |
+
* @method \GuzzleHttp\Promise\Promise listAccessKeysAsync(array $args = [])
|
141 |
+
* @method \Aws\Result listAccountAliases(array $args = [])
|
142 |
+
* @method \GuzzleHttp\Promise\Promise listAccountAliasesAsync(array $args = [])
|
143 |
+
* @method \Aws\Result listAttachedGroupPolicies(array $args = [])
|
144 |
+
* @method \GuzzleHttp\Promise\Promise listAttachedGroupPoliciesAsync(array $args = [])
|
145 |
+
* @method \Aws\Result listAttachedRolePolicies(array $args = [])
|
146 |
+
* @method \GuzzleHttp\Promise\Promise listAttachedRolePoliciesAsync(array $args = [])
|
147 |
+
* @method \Aws\Result listAttachedUserPolicies(array $args = [])
|
148 |
+
* @method \GuzzleHttp\Promise\Promise listAttachedUserPoliciesAsync(array $args = [])
|
149 |
+
* @method \Aws\Result listEntitiesForPolicy(array $args = [])
|
150 |
+
* @method \GuzzleHttp\Promise\Promise listEntitiesForPolicyAsync(array $args = [])
|
151 |
+
* @method \Aws\Result listGroupPolicies(array $args = [])
|
152 |
+
* @method \GuzzleHttp\Promise\Promise listGroupPoliciesAsync(array $args = [])
|
153 |
+
* @method \Aws\Result listGroups(array $args = [])
|
154 |
+
* @method \GuzzleHttp\Promise\Promise listGroupsAsync(array $args = [])
|
155 |
+
* @method \Aws\Result listGroupsForUser(array $args = [])
|
156 |
+
* @method \GuzzleHttp\Promise\Promise listGroupsForUserAsync(array $args = [])
|
157 |
+
* @method \Aws\Result listInstanceProfiles(array $args = [])
|
158 |
+
* @method \GuzzleHttp\Promise\Promise listInstanceProfilesAsync(array $args = [])
|
159 |
+
* @method \Aws\Result listInstanceProfilesForRole(array $args = [])
|
160 |
+
* @method \GuzzleHttp\Promise\Promise listInstanceProfilesForRoleAsync(array $args = [])
|
161 |
+
* @method \Aws\Result listMFADevices(array $args = [])
|
162 |
+
* @method \GuzzleHttp\Promise\Promise listMFADevicesAsync(array $args = [])
|
163 |
+
* @method \Aws\Result listOpenIDConnectProviders(array $args = [])
|
164 |
+
* @method \GuzzleHttp\Promise\Promise listOpenIDConnectProvidersAsync(array $args = [])
|
165 |
+
* @method \Aws\Result listPolicies(array $args = [])
|
166 |
+
* @method \GuzzleHttp\Promise\Promise listPoliciesAsync(array $args = [])
|
167 |
+
* @method \Aws\Result listPolicyVersions(array $args = [])
|
168 |
+
* @method \GuzzleHttp\Promise\Promise listPolicyVersionsAsync(array $args = [])
|
169 |
+
* @method \Aws\Result listRolePolicies(array $args = [])
|
170 |
+
* @method \GuzzleHttp\Promise\Promise listRolePoliciesAsync(array $args = [])
|
171 |
+
* @method \Aws\Result listRoles(array $args = [])
|
172 |
+
* @method \GuzzleHttp\Promise\Promise listRolesAsync(array $args = [])
|
173 |
+
* @method \Aws\Result listSAMLProviders(array $args = [])
|
174 |
+
* @method \GuzzleHttp\Promise\Promise listSAMLProvidersAsync(array $args = [])
|
175 |
+
* @method \Aws\Result listSSHPublicKeys(array $args = [])
|
176 |
+
* @method \GuzzleHttp\Promise\Promise listSSHPublicKeysAsync(array $args = [])
|
177 |
+
* @method \Aws\Result listServerCertificates(array $args = [])
|
178 |
+
* @method \GuzzleHttp\Promise\Promise listServerCertificatesAsync(array $args = [])
|
179 |
+
* @method \Aws\Result listSigningCertificates(array $args = [])
|
180 |
+
* @method \GuzzleHttp\Promise\Promise listSigningCertificatesAsync(array $args = [])
|
181 |
+
* @method \Aws\Result listUserPolicies(array $args = [])
|
182 |
+
* @method \GuzzleHttp\Promise\Promise listUserPoliciesAsync(array $args = [])
|
183 |
+
* @method \Aws\Result listUsers(array $args = [])
|
184 |
+
* @method \GuzzleHttp\Promise\Promise listUsersAsync(array $args = [])
|
185 |
+
* @method \Aws\Result listVirtualMFADevices(array $args = [])
|
186 |
+
* @method \GuzzleHttp\Promise\Promise listVirtualMFADevicesAsync(array $args = [])
|
187 |
+
* @method \Aws\Result putGroupPolicy(array $args = [])
|
188 |
+
* @method \GuzzleHttp\Promise\Promise putGroupPolicyAsync(array $args = [])
|
189 |
+
* @method \Aws\Result putRolePolicy(array $args = [])
|
190 |
+
* @method \GuzzleHttp\Promise\Promise putRolePolicyAsync(array $args = [])
|
191 |
+
* @method \Aws\Result putUserPolicy(array $args = [])
|
192 |
+
* @method \GuzzleHttp\Promise\Promise putUserPolicyAsync(array $args = [])
|
193 |
+
* @method \Aws\Result removeClientIDFromOpenIDConnectProvider(array $args = [])
|
194 |
+
* @method \GuzzleHttp\Promise\Promise removeClientIDFromOpenIDConnectProviderAsync(array $args = [])
|
195 |
+
* @method \Aws\Result removeRoleFromInstanceProfile(array $args = [])
|
196 |
+
* @method \GuzzleHttp\Promise\Promise removeRoleFromInstanceProfileAsync(array $args = [])
|
197 |
+
* @method \Aws\Result removeUserFromGroup(array $args = [])
|
198 |
+
* @method \GuzzleHttp\Promise\Promise removeUserFromGroupAsync(array $args = [])
|
199 |
+
* @method \Aws\Result resyncMFADevice(array $args = [])
|
200 |
+
* @method \GuzzleHttp\Promise\Promise resyncMFADeviceAsync(array $args = [])
|
201 |
+
* @method \Aws\Result setDefaultPolicyVersion(array $args = [])
|
202 |
+
* @method \GuzzleHttp\Promise\Promise setDefaultPolicyVersionAsync(array $args = [])
|
203 |
+
* @method \Aws\Result simulateCustomPolicy(array $args = [])
|
204 |
+
* @method \GuzzleHttp\Promise\Promise simulateCustomPolicyAsync(array $args = [])
|
205 |
+
* @method \Aws\Result simulatePrincipalPolicy(array $args = [])
|
206 |
+
* @method \GuzzleHttp\Promise\Promise simulatePrincipalPolicyAsync(array $args = [])
|
207 |
+
* @method \Aws\Result updateAccessKey(array $args = [])
|
208 |
+
* @method \GuzzleHttp\Promise\Promise updateAccessKeyAsync(array $args = [])
|
209 |
+
* @method \Aws\Result updateAccountPasswordPolicy(array $args = [])
|
210 |
+
* @method \GuzzleHttp\Promise\Promise updateAccountPasswordPolicyAsync(array $args = [])
|
211 |
+
* @method \Aws\Result updateAssumeRolePolicy(array $args = [])
|
212 |
+
* @method \GuzzleHttp\Promise\Promise updateAssumeRolePolicyAsync(array $args = [])
|
213 |
+
* @method \Aws\Result updateGroup(array $args = [])
|
214 |
+
* @method \GuzzleHttp\Promise\Promise updateGroupAsync(array $args = [])
|
215 |
+
* @method \Aws\Result updateLoginProfile(array $args = [])
|
216 |
+
* @method \GuzzleHttp\Promise\Promise updateLoginProfileAsync(array $args = [])
|
217 |
+
* @method \Aws\Result updateOpenIDConnectProviderThumbprint(array $args = [])
|
218 |
+
* @method \GuzzleHttp\Promise\Promise updateOpenIDConnectProviderThumbprintAsync(array $args = [])
|
219 |
+
* @method \Aws\Result updateSAMLProvider(array $args = [])
|
220 |
+
* @method \GuzzleHttp\Promise\Promise updateSAMLProviderAsync(array $args = [])
|
221 |
+
* @method \Aws\Result updateSSHPublicKey(array $args = [])
|
222 |
+
* @method \GuzzleHttp\Promise\Promise updateSSHPublicKeyAsync(array $args = [])
|
223 |
+
* @method \Aws\Result updateServerCertificate(array $args = [])
|
224 |
+
* @method \GuzzleHttp\Promise\Promise updateServerCertificateAsync(array $args = [])
|
225 |
+
* @method \Aws\Result updateSigningCertificate(array $args = [])
|
226 |
+
* @method \GuzzleHttp\Promise\Promise updateSigningCertificateAsync(array $args = [])
|
227 |
+
* @method \Aws\Result updateUser(array $args = [])
|
228 |
+
* @method \GuzzleHttp\Promise\Promise updateUserAsync(array $args = [])
|
229 |
+
* @method \Aws\Result uploadSSHPublicKey(array $args = [])
|
230 |
+
* @method \GuzzleHttp\Promise\Promise uploadSSHPublicKeyAsync(array $args = [])
|
231 |
+
* @method \Aws\Result uploadServerCertificate(array $args = [])
|
232 |
+
* @method \GuzzleHttp\Promise\Promise uploadServerCertificateAsync(array $args = [])
|
233 |
+
* @method \Aws\Result uploadSigningCertificate(array $args = [])
|
234 |
+
* @method \GuzzleHttp\Promise\Promise uploadSigningCertificateAsync(array $args = [])
|
235 |
+
*/
|
236 |
+
class IamClient extends AwsClient {}
|
includes/aws/Aws/Inspector/Exception/InspectorException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Inspector\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the **Amazon Inspector** service.
|
8 |
+
*/
|
9 |
+
class InspectorException extends AwsException {}
|
includes/aws/Aws/Inspector/InspectorClient.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Inspector;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **Amazon Inspector** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result addAttributesToFindings(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise addAttributesToFindingsAsync(array $args = [])
|
11 |
+
* @method \Aws\Result attachAssessmentAndRulesPackage(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise attachAssessmentAndRulesPackageAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createApplication(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createApplicationAsync(array $args = [])
|
15 |
+
* @method \Aws\Result createAssessment(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise createAssessmentAsync(array $args = [])
|
17 |
+
* @method \Aws\Result createResourceGroup(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise createResourceGroupAsync(array $args = [])
|
19 |
+
* @method \Aws\Result deleteApplication(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise deleteApplicationAsync(array $args = [])
|
21 |
+
* @method \Aws\Result deleteAssessment(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise deleteAssessmentAsync(array $args = [])
|
23 |
+
* @method \Aws\Result deleteRun(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise deleteRunAsync(array $args = [])
|
25 |
+
* @method \Aws\Result describeApplication(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise describeApplicationAsync(array $args = [])
|
27 |
+
* @method \Aws\Result describeAssessment(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise describeAssessmentAsync(array $args = [])
|
29 |
+
* @method \Aws\Result describeCrossAccountAccessRole(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise describeCrossAccountAccessRoleAsync(array $args = [])
|
31 |
+
* @method \Aws\Result describeFinding(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise describeFindingAsync(array $args = [])
|
33 |
+
* @method \Aws\Result describeResourceGroup(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise describeResourceGroupAsync(array $args = [])
|
35 |
+
* @method \Aws\Result describeRulesPackage(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise describeRulesPackageAsync(array $args = [])
|
37 |
+
* @method \Aws\Result describeRun(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise describeRunAsync(array $args = [])
|
39 |
+
* @method \Aws\Result detachAssessmentAndRulesPackage(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise detachAssessmentAndRulesPackageAsync(array $args = [])
|
41 |
+
* @method \Aws\Result getAssessmentTelemetry(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise getAssessmentTelemetryAsync(array $args = [])
|
43 |
+
* @method \Aws\Result listApplications(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise listApplicationsAsync(array $args = [])
|
45 |
+
* @method \Aws\Result listAssessmentAgents(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise listAssessmentAgentsAsync(array $args = [])
|
47 |
+
* @method \Aws\Result listAssessments(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise listAssessmentsAsync(array $args = [])
|
49 |
+
* @method \Aws\Result listAttachedAssessments(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise listAttachedAssessmentsAsync(array $args = [])
|
51 |
+
* @method \Aws\Result listAttachedRulesPackages(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise listAttachedRulesPackagesAsync(array $args = [])
|
53 |
+
* @method \Aws\Result listFindings(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise listFindingsAsync(array $args = [])
|
55 |
+
* @method \Aws\Result listRulesPackages(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise listRulesPackagesAsync(array $args = [])
|
57 |
+
* @method \Aws\Result listRuns(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise listRunsAsync(array $args = [])
|
59 |
+
* @method \Aws\Result listTagsForResource(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
|
61 |
+
* @method \Aws\Result localizeText(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise localizeTextAsync(array $args = [])
|
63 |
+
* @method \Aws\Result previewAgentsForResourceGroup(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise previewAgentsForResourceGroupAsync(array $args = [])
|
65 |
+
* @method \Aws\Result registerCrossAccountAccessRole(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise registerCrossAccountAccessRoleAsync(array $args = [])
|
67 |
+
* @method \Aws\Result removeAttributesFromFindings(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise removeAttributesFromFindingsAsync(array $args = [])
|
69 |
+
* @method \Aws\Result runAssessment(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise runAssessmentAsync(array $args = [])
|
71 |
+
* @method \Aws\Result setTagsForResource(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise setTagsForResourceAsync(array $args = [])
|
73 |
+
* @method \Aws\Result startDataCollection(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise startDataCollectionAsync(array $args = [])
|
75 |
+
* @method \Aws\Result stopDataCollection(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise stopDataCollectionAsync(array $args = [])
|
77 |
+
* @method \Aws\Result updateApplication(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise updateApplicationAsync(array $args = [])
|
79 |
+
* @method \Aws\Result updateAssessment(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise updateAssessmentAsync(array $args = [])
|
81 |
+
*/
|
82 |
+
class InspectorClient extends AwsClient {}
|
includes/aws/Aws/Iot/Exception/IotException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Iot\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the **AWS IoT** service.
|
8 |
+
*/
|
9 |
+
class IotException extends AwsException {}
|
includes/aws/Aws/Iot/IotClient.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Iot;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **AWS IoT** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result acceptCertificateTransfer(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise acceptCertificateTransferAsync(array $args = [])
|
11 |
+
* @method \Aws\Result attachPrincipalPolicy(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise attachPrincipalPolicyAsync(array $args = [])
|
13 |
+
* @method \Aws\Result attachThingPrincipal(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise attachThingPrincipalAsync(array $args = [])
|
15 |
+
* @method \Aws\Result cancelCertificateTransfer(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise cancelCertificateTransferAsync(array $args = [])
|
17 |
+
* @method \Aws\Result createCertificateFromCsr(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise createCertificateFromCsrAsync(array $args = [])
|
19 |
+
* @method \Aws\Result createKeysAndCertificate(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise createKeysAndCertificateAsync(array $args = [])
|
21 |
+
* @method \Aws\Result createPolicy(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise createPolicyAsync(array $args = [])
|
23 |
+
* @method \Aws\Result createPolicyVersion(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise createPolicyVersionAsync(array $args = [])
|
25 |
+
* @method \Aws\Result createThing(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise createThingAsync(array $args = [])
|
27 |
+
* @method \Aws\Result createTopicRule(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise createTopicRuleAsync(array $args = [])
|
29 |
+
* @method \Aws\Result deleteCertificate(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise deleteCertificateAsync(array $args = [])
|
31 |
+
* @method \Aws\Result deletePolicy(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise deletePolicyAsync(array $args = [])
|
33 |
+
* @method \Aws\Result deletePolicyVersion(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise deletePolicyVersionAsync(array $args = [])
|
35 |
+
* @method \Aws\Result deleteThing(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise deleteThingAsync(array $args = [])
|
37 |
+
* @method \Aws\Result deleteTopicRule(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise deleteTopicRuleAsync(array $args = [])
|
39 |
+
* @method \Aws\Result describeCertificate(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise describeCertificateAsync(array $args = [])
|
41 |
+
* @method \Aws\Result describeEndpoint(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise describeEndpointAsync(array $args = [])
|
43 |
+
* @method \Aws\Result describeThing(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise describeThingAsync(array $args = [])
|
45 |
+
* @method \Aws\Result detachPrincipalPolicy(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise detachPrincipalPolicyAsync(array $args = [])
|
47 |
+
* @method \Aws\Result detachThingPrincipal(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise detachThingPrincipalAsync(array $args = [])
|
49 |
+
* @method \Aws\Result getLoggingOptions(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise getLoggingOptionsAsync(array $args = [])
|
51 |
+
* @method \Aws\Result getPolicy(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise getPolicyAsync(array $args = [])
|
53 |
+
* @method \Aws\Result getPolicyVersion(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise getPolicyVersionAsync(array $args = [])
|
55 |
+
* @method \Aws\Result getTopicRule(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise getTopicRuleAsync(array $args = [])
|
57 |
+
* @method \Aws\Result listCertificates(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise listCertificatesAsync(array $args = [])
|
59 |
+
* @method \Aws\Result listPolicies(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise listPoliciesAsync(array $args = [])
|
61 |
+
* @method \Aws\Result listPolicyVersions(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise listPolicyVersionsAsync(array $args = [])
|
63 |
+
* @method \Aws\Result listPrincipalPolicies(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise listPrincipalPoliciesAsync(array $args = [])
|
65 |
+
* @method \Aws\Result listPrincipalThings(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise listPrincipalThingsAsync(array $args = [])
|
67 |
+
* @method \Aws\Result listThingPrincipals(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise listThingPrincipalsAsync(array $args = [])
|
69 |
+
* @method \Aws\Result listThings(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise listThingsAsync(array $args = [])
|
71 |
+
* @method \Aws\Result listTopicRules(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise listTopicRulesAsync(array $args = [])
|
73 |
+
* @method \Aws\Result rejectCertificateTransfer(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise rejectCertificateTransferAsync(array $args = [])
|
75 |
+
* @method \Aws\Result replaceTopicRule(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise replaceTopicRuleAsync(array $args = [])
|
77 |
+
* @method \Aws\Result setDefaultPolicyVersion(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise setDefaultPolicyVersionAsync(array $args = [])
|
79 |
+
* @method \Aws\Result setLoggingOptions(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise setLoggingOptionsAsync(array $args = [])
|
81 |
+
* @method \Aws\Result transferCertificate(array $args = [])
|
82 |
+
* @method \GuzzleHttp\Promise\Promise transferCertificateAsync(array $args = [])
|
83 |
+
* @method \Aws\Result updateCertificate(array $args = [])
|
84 |
+
* @method \GuzzleHttp\Promise\Promise updateCertificateAsync(array $args = [])
|
85 |
+
* @method \Aws\Result updateThing(array $args = [])
|
86 |
+
* @method \GuzzleHttp\Promise\Promise updateThingAsync(array $args = [])
|
87 |
+
*/
|
88 |
+
class IotClient extends AwsClient {}
|
includes/aws/Aws/IotDataPlane/Exception/IotDataPlaneException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\IotDataPlane\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the **AWS IoT Data Plane** service.
|
8 |
+
*/
|
9 |
+
class IotDataPlaneException extends AwsException {}
|
includes/aws/Aws/IotDataPlane/IotDataPlaneClient.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\IotDataPlane;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **AWS IoT Data Plane** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result deleteThingShadow(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise deleteThingShadowAsync(array $args = [])
|
11 |
+
* @method \Aws\Result getThingShadow(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise getThingShadowAsync(array $args = [])
|
13 |
+
* @method \Aws\Result publish(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise publishAsync(array $args = [])
|
15 |
+
* @method \Aws\Result updateThingShadow(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise updateThingShadowAsync(array $args = [])
|
17 |
+
*/
|
18 |
+
class IotDataPlaneClient extends AwsClient {}
|
includes/aws/Aws/JsonCompiler.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Loads JSON files and compiles them into PHP arrays.
|
6 |
+
*
|
7 |
+
* @internal Please use json_decode instead.
|
8 |
+
* @deprecated
|
9 |
+
*/
|
10 |
+
class JsonCompiler
|
11 |
+
{
|
12 |
+
const CACHE_ENV = 'AWS_PHP_CACHE_DIR';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Loads a JSON file from cache or from the JSON file directly.
|
16 |
+
*
|
17 |
+
* @param string $path Path to the JSON file to load.
|
18 |
+
*
|
19 |
+
* @return mixed
|
20 |
+
*/
|
21 |
+
public function load($path)
|
22 |
+
{
|
23 |
+
return load_compiled_json($path);
|
24 |
+
}
|
25 |
+
}
|
includes/aws/Aws/LruArrayCache.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Simple in-memory LRU cache that limits the number of cached entries.
|
6 |
+
*
|
7 |
+
* The LRU cache is implemented using PHP's ordered associative array. When
|
8 |
+
* accessing an element, the element is removed from the hash and re-added to
|
9 |
+
* ensure that recently used items are always at the end of the list while
|
10 |
+
* least recently used are at the beginning. When a value is added to the
|
11 |
+
* cache, if the number of cached items exceeds the allowed number, the first
|
12 |
+
* N number of items are removed from the array.
|
13 |
+
*/
|
14 |
+
class LruArrayCache implements CacheInterface
|
15 |
+
{
|
16 |
+
/** @var int */
|
17 |
+
private $maxItems;
|
18 |
+
|
19 |
+
/** @var array */
|
20 |
+
private $items;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param int $maxItems Maximum number of allowed cache items.
|
24 |
+
*/
|
25 |
+
public function __construct($maxItems = 1000)
|
26 |
+
{
|
27 |
+
$this->maxItems = $maxItems;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function get($key)
|
31 |
+
{
|
32 |
+
if (!isset($this->items[$key])) {
|
33 |
+
return null;
|
34 |
+
}
|
35 |
+
|
36 |
+
$entry = $this->items[$key];
|
37 |
+
|
38 |
+
// Ensure the item is not expired.
|
39 |
+
if (!$entry[1] || time() < $entry[1]) {
|
40 |
+
// LRU: remove the item and push it to the end of the array.
|
41 |
+
unset($this->items[$key]);
|
42 |
+
$this->items[$key] = $entry;
|
43 |
+
return $entry[0];
|
44 |
+
}
|
45 |
+
|
46 |
+
unset($this->items[$key]);
|
47 |
+
return null;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function set($key, $value, $ttl = 0)
|
51 |
+
{
|
52 |
+
// Only call time() if the TTL is not 0/false/null
|
53 |
+
$ttl = $ttl ? time() + $ttl : 0;
|
54 |
+
$this->items[$key] = [$value, $ttl];
|
55 |
+
|
56 |
+
// Determine if there are more items in the cache than allowed.
|
57 |
+
$diff = count($this->items) - $this->maxItems;
|
58 |
+
|
59 |
+
// Clear out least recently used items.
|
60 |
+
if ($diff > 0) {
|
61 |
+
// Reset to the beginning of the array and begin unsetting.
|
62 |
+
reset($this->items);
|
63 |
+
for ($i = 0; $i < $diff; $i++) {
|
64 |
+
unset($this->items[key($this->items)]);
|
65 |
+
next($this->items);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
public function remove($key)
|
71 |
+
{
|
72 |
+
unset($this->items[$key]);
|
73 |
+
}
|
74 |
+
}
|
includes/aws/Aws/Middleware.php
ADDED
@@ -0,0 +1,308 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Api\Service;
|
5 |
+
use Aws\Api\Validator;
|
6 |
+
use Aws\Credentials\CredentialsInterface;
|
7 |
+
use GuzzleHttp\Promise;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\Psr7\LazyOpenStream;
|
10 |
+
use Psr\Http\Message\RequestInterface;
|
11 |
+
|
12 |
+
final class Middleware
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Middleware used to allow a command parameter (e.g., "SourceFile") to
|
16 |
+
* be used to specify the source of data for an upload operation.
|
17 |
+
*
|
18 |
+
* @param Service $api
|
19 |
+
* @param string $bodyParameter
|
20 |
+
* @param string $sourceParameter
|
21 |
+
*
|
22 |
+
* @return callable
|
23 |
+
*/
|
24 |
+
public static function sourceFile(
|
25 |
+
Service $api,
|
26 |
+
$bodyParameter = 'Body',
|
27 |
+
$sourceParameter = 'SourceFile'
|
28 |
+
) {
|
29 |
+
return function (callable $handler) use (
|
30 |
+
$api,
|
31 |
+
$bodyParameter,
|
32 |
+
$sourceParameter
|
33 |
+
) {
|
34 |
+
return function (
|
35 |
+
CommandInterface $command,
|
36 |
+
RequestInterface $request = null)
|
37 |
+
use (
|
38 |
+
$handler,
|
39 |
+
$api,
|
40 |
+
$bodyParameter,
|
41 |
+
$sourceParameter
|
42 |
+
) {
|
43 |
+
$operation = $api->getOperation($command->getName());
|
44 |
+
$source = $command[$sourceParameter];
|
45 |
+
|
46 |
+
if ($source !== null
|
47 |
+
&& $operation->getInput()->hasMember($bodyParameter)
|
48 |
+
) {
|
49 |
+
$command[$bodyParameter] = new LazyOpenStream($source, 'r');
|
50 |
+
unset($command[$sourceParameter]);
|
51 |
+
}
|
52 |
+
|
53 |
+
return $handler($command, $request);
|
54 |
+
};
|
55 |
+
};
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Adds a middleware that uses client-side validation.
|
60 |
+
*
|
61 |
+
* @param Service $api API being accessed.
|
62 |
+
*
|
63 |
+
* @return callable
|
64 |
+
*/
|
65 |
+
public static function validation(Service $api)
|
66 |
+
{
|
67 |
+
$validator = new Validator();
|
68 |
+
return function (callable $handler) use ($api, $validator) {
|
69 |
+
return function (
|
70 |
+
CommandInterface $command,
|
71 |
+
RequestInterface $request = null
|
72 |
+
) use ($api, $validator, $handler) {
|
73 |
+
$operation = $api->getOperation($command->getName());
|
74 |
+
$validator->validate(
|
75 |
+
$command->getName(),
|
76 |
+
$operation->getInput(),
|
77 |
+
$command->toArray()
|
78 |
+
);
|
79 |
+
return $handler($command, $request);
|
80 |
+
};
|
81 |
+
};
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Builds an HTTP request for a command.
|
86 |
+
*
|
87 |
+
* @param callable $serializer Function used to serialize a request for a
|
88 |
+
* command.
|
89 |
+
* @return callable
|
90 |
+
*/
|
91 |
+
public static function requestBuilder(callable $serializer)
|
92 |
+
{
|
93 |
+
return function (callable $handler) use ($serializer) {
|
94 |
+
return function (CommandInterface $command) use ($serializer, $handler) {
|
95 |
+
return $handler($command, $serializer($command));
|
96 |
+
};
|
97 |
+
};
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Creates a middleware that signs requests for a command.
|
102 |
+
*
|
103 |
+
* @param callable $credProvider Credentials provider function that
|
104 |
+
* returns a promise that is resolved
|
105 |
+
* with a CredentialsInterface object.
|
106 |
+
* @param callable $signatureFunction Function that accepts a Command
|
107 |
+
* object and returns a
|
108 |
+
* SignatureInterface.
|
109 |
+
*
|
110 |
+
* @return callable
|
111 |
+
*/
|
112 |
+
public static function signer(callable $credProvider, callable $signatureFunction)
|
113 |
+
{
|
114 |
+
return function (callable $handler) use ($signatureFunction, $credProvider) {
|
115 |
+
return function (
|
116 |
+
CommandInterface $command,
|
117 |
+
RequestInterface $request
|
118 |
+
) use ($handler, $signatureFunction, $credProvider) {
|
119 |
+
$signer = $signatureFunction($command);
|
120 |
+
return $credProvider()->then(
|
121 |
+
function (CredentialsInterface $creds)
|
122 |
+
use ($handler, $command, $signer, $request) {
|
123 |
+
return $handler(
|
124 |
+
$command,
|
125 |
+
$signer->signRequest($request, $creds)
|
126 |
+
);
|
127 |
+
}
|
128 |
+
);
|
129 |
+
};
|
130 |
+
};
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Creates a middleware that invokes a callback at a given step.
|
135 |
+
*
|
136 |
+
* The tap callback accepts a CommandInterface and RequestInterface as
|
137 |
+
* arguments but is not expected to return a new value or proxy to
|
138 |
+
* downstream middleware. It's simply a way to "tap" into the handler chain
|
139 |
+
* to debug or get an intermediate value.
|
140 |
+
*
|
141 |
+
* @param callable $fn Tap function
|
142 |
+
*
|
143 |
+
* @return callable
|
144 |
+
*/
|
145 |
+
public static function tap(callable $fn)
|
146 |
+
{
|
147 |
+
return function (callable $handler) use ($fn) {
|
148 |
+
return function (
|
149 |
+
CommandInterface $command,
|
150 |
+
RequestInterface $request = null
|
151 |
+
) use ($handler, $fn) {
|
152 |
+
$fn($command, $request);
|
153 |
+
return $handler($command, $request);
|
154 |
+
};
|
155 |
+
};
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Middleware wrapper function that retries requests based on the boolean
|
160 |
+
* result of invoking the provided "decider" function.
|
161 |
+
*
|
162 |
+
* If no delay function is provided, a simple implementation of exponential
|
163 |
+
* backoff will be utilized.
|
164 |
+
*
|
165 |
+
* @param callable $decider Function that accepts the number of retries,
|
166 |
+
* a request, [result], and [exception] and
|
167 |
+
* returns true if the command is to be retried.
|
168 |
+
* @param callable $delay Function that accepts the number of retries and
|
169 |
+
* returns the number of milliseconds to delay.
|
170 |
+
*
|
171 |
+
* @return callable
|
172 |
+
*/
|
173 |
+
public static function retry(callable $decider = null, callable $delay = null)
|
174 |
+
{
|
175 |
+
$decider = $decider ?: RetryMiddleware::createDefaultDecider();
|
176 |
+
$delay = $delay ?: [RetryMiddleware::class, 'exponentialDelay'];
|
177 |
+
|
178 |
+
return function (callable $handler) use ($decider, $delay) {
|
179 |
+
return new RetryMiddleware($decider, $delay, $handler);
|
180 |
+
};
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Middleware wrapper function that adds a Content-Type header to requests.
|
185 |
+
* This is only done when the Content-Type has not already been set, and the
|
186 |
+
* request body's URI is available. It then checks the file extension of the
|
187 |
+
* URI to determine the mime-type.
|
188 |
+
*
|
189 |
+
* @param array $operations Operations that Content-Type should be added to.
|
190 |
+
*
|
191 |
+
* @return callable
|
192 |
+
*/
|
193 |
+
public static function contentType(array $operations)
|
194 |
+
{
|
195 |
+
return function (callable $handler) use ($operations) {
|
196 |
+
return function (
|
197 |
+
CommandInterface $command,
|
198 |
+
RequestInterface $request = null
|
199 |
+
) use ($handler, $operations) {
|
200 |
+
if (!$request->hasHeader('Content-Type')
|
201 |
+
&& in_array($command->getName(), $operations, true)
|
202 |
+
&& ($uri = $request->getBody()->getMetadata('uri'))
|
203 |
+
) {
|
204 |
+
$request = $request->withHeader(
|
205 |
+
'Content-Type',
|
206 |
+
Psr7\mimetype_from_filename($uri) ?: 'application/octet-stream'
|
207 |
+
);
|
208 |
+
}
|
209 |
+
|
210 |
+
return $handler($command, $request);
|
211 |
+
};
|
212 |
+
};
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Tracks command and request history using a history container.
|
217 |
+
*
|
218 |
+
* This is useful for testing.
|
219 |
+
*
|
220 |
+
* @param History $history History container to store entries.
|
221 |
+
*
|
222 |
+
* @return callable
|
223 |
+
*/
|
224 |
+
public static function history(History $history)
|
225 |
+
{
|
226 |
+
return function (callable $handler) use ($history) {
|
227 |
+
return function (
|
228 |
+
CommandInterface $command,
|
229 |
+
RequestInterface $request = null
|
230 |
+
) use ($handler, $history) {
|
231 |
+
$ticket = $history->start($command, $request);
|
232 |
+
return $handler($command, $request)
|
233 |
+
->then(
|
234 |
+
function ($result) use ($history, $ticket) {
|
235 |
+
$history->finish($ticket, $result);
|
236 |
+
return $result;
|
237 |
+
},
|
238 |
+
function ($reason) use ($history, $ticket) {
|
239 |
+
$history->finish($ticket, $reason);
|
240 |
+
return Promise\rejection_for($reason);
|
241 |
+
}
|
242 |
+
);
|
243 |
+
};
|
244 |
+
};
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Creates a middleware that applies a map function to requests as they
|
249 |
+
* pass through the middleware.
|
250 |
+
*
|
251 |
+
* @param callable $f Map function that accepts a RequestInterface and
|
252 |
+
* returns a RequestInterface.
|
253 |
+
*
|
254 |
+
* @return callable
|
255 |
+
*/
|
256 |
+
public static function mapRequest(callable $f)
|
257 |
+
{
|
258 |
+
return function (callable $handler) use ($f) {
|
259 |
+
return function (
|
260 |
+
CommandInterface $command,
|
261 |
+
RequestInterface $request = null
|
262 |
+
) use ($handler, $f) {
|
263 |
+
return $handler($command, $f($request));
|
264 |
+
};
|
265 |
+
};
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Creates a middleware that applies a map function to commands as they
|
270 |
+
* pass through the middleware.
|
271 |
+
*
|
272 |
+
* @param callable $f Map function that accepts a command and returns a
|
273 |
+
* command.
|
274 |
+
*
|
275 |
+
* @return callable
|
276 |
+
*/
|
277 |
+
public static function mapCommand(callable $f)
|
278 |
+
{
|
279 |
+
return function (callable $handler) use ($f) {
|
280 |
+
return function (
|
281 |
+
CommandInterface $command,
|
282 |
+
RequestInterface $request = null
|
283 |
+
) use ($handler, $f) {
|
284 |
+
return $handler($f($command), $request);
|
285 |
+
};
|
286 |
+
};
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Creates a middleware that applies a map function to results.
|
291 |
+
*
|
292 |
+
* @param callable $f Map function that accepts an Aws\ResultInterface and
|
293 |
+
* returns an Aws\ResultInterface.
|
294 |
+
*
|
295 |
+
* @return callable
|
296 |
+
*/
|
297 |
+
public static function mapResult(callable $f)
|
298 |
+
{
|
299 |
+
return function (callable $handler) use ($f) {
|
300 |
+
return function (
|
301 |
+
CommandInterface $command,
|
302 |
+
RequestInterface $request = null
|
303 |
+
) use ($handler, $f) {
|
304 |
+
return $handler($command, $request)->then($f);
|
305 |
+
};
|
306 |
+
};
|
307 |
+
}
|
308 |
+
}
|
includes/aws/Aws/MockHandler.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Returns promises that are rejected or fulfilled using a queue of
|
11 |
+
* Aws\ResultInterface and Aws\Exception\AwsException objects.
|
12 |
+
*/
|
13 |
+
class MockHandler implements \Countable
|
14 |
+
{
|
15 |
+
private $queue;
|
16 |
+
private $lastCommand;
|
17 |
+
private $lastRequest;
|
18 |
+
private $onFulfilled;
|
19 |
+
private $onRejected;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* The passed in value must be an array of {@see Aws\ResultInterface} or
|
23 |
+
* {@see AwsException} objects that acts as a queue of results or
|
24 |
+
* exceptions to return each time the handler is invoked.
|
25 |
+
*
|
26 |
+
* @param array $resultOrQueue
|
27 |
+
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
28 |
+
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
29 |
+
*/
|
30 |
+
public function __construct(
|
31 |
+
array $resultOrQueue = [],
|
32 |
+
callable $onFulfilled = null,
|
33 |
+
callable $onRejected = null
|
34 |
+
) {
|
35 |
+
$this->onFulfilled = $onFulfilled;
|
36 |
+
$this->onRejected = $onRejected;
|
37 |
+
|
38 |
+
if ($resultOrQueue) {
|
39 |
+
call_user_func_array([$this, 'append'], $resultOrQueue);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Adds one or more variadic ResultInterface or AwsException objects to the
|
45 |
+
* queue.
|
46 |
+
*/
|
47 |
+
public function append()
|
48 |
+
{
|
49 |
+
foreach (func_get_args() as $value) {
|
50 |
+
if ($value instanceof ResultInterface
|
51 |
+
|| $value instanceof AwsException
|
52 |
+
|| is_callable($value)
|
53 |
+
) {
|
54 |
+
$this->queue[] = $value;
|
55 |
+
} else {
|
56 |
+
throw new \InvalidArgumentException('Expected an Aws\ResultInterface or Aws\Exception\AwsException.');
|
57 |
+
}
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function __invoke(
|
62 |
+
CommandInterface $command,
|
63 |
+
RequestInterface $request
|
64 |
+
) {
|
65 |
+
if (!$this->queue) {
|
66 |
+
$last = $this->lastCommand
|
67 |
+
? ' The last command sent was ' . $this->lastCommand->getName() . '.'
|
68 |
+
: '';
|
69 |
+
throw new \RuntimeException('Mock queue is empty. Trying to send a '
|
70 |
+
. $command->getName() . ' command failed.' . $last);
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->lastCommand = $command;
|
74 |
+
$this->lastRequest = $request;
|
75 |
+
|
76 |
+
$result = array_shift($this->queue);
|
77 |
+
|
78 |
+
if (is_callable($result)) {
|
79 |
+
$result = $result($command, $request);
|
80 |
+
}
|
81 |
+
|
82 |
+
if ($result instanceof \Exception) {
|
83 |
+
$result = new RejectedPromise($result);
|
84 |
+
} else {
|
85 |
+
// Add an effective URI and statusCode if not present.
|
86 |
+
$meta = $result['@metadata'];
|
87 |
+
if (!isset($meta['effectiveUri'])) {
|
88 |
+
$meta['effectiveUri'] = (string) $request->getUri();
|
89 |
+
}
|
90 |
+
if (!isset($meta['statusCode'])) {
|
91 |
+
$meta['statusCode'] = 200;
|
92 |
+
}
|
93 |
+
$result['@metadata'] = $meta;
|
94 |
+
$result = Promise\promise_for($result);
|
95 |
+
}
|
96 |
+
|
97 |
+
$result->then($this->onFulfilled, $this->onRejected);
|
98 |
+
|
99 |
+
return $result;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Get the last received request.
|
104 |
+
*
|
105 |
+
* @return RequestInterface
|
106 |
+
*/
|
107 |
+
public function getLastRequest()
|
108 |
+
{
|
109 |
+
return $this->lastRequest;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Get the last received command.
|
114 |
+
*
|
115 |
+
* @return CommandInterface
|
116 |
+
*/
|
117 |
+
public function getLastCommand()
|
118 |
+
{
|
119 |
+
return $this->lastCommand;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Returns the number of remaining items in the queue.
|
124 |
+
*
|
125 |
+
* @return int
|
126 |
+
*/
|
127 |
+
public function count()
|
128 |
+
{
|
129 |
+
return count($this->queue);
|
130 |
+
}
|
131 |
+
}
|
includes/aws/Aws/Multipart/AbstractUploadManager.php
ADDED
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Multipart;
|
3 |
+
|
4 |
+
use Aws\AwsClientInterface as Client;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Aws\CommandPool;
|
7 |
+
use Aws\Exception\AwsException;
|
8 |
+
use Aws\Exception\MultipartUploadException;
|
9 |
+
use Aws\Result;
|
10 |
+
use Aws\ResultInterface;
|
11 |
+
use GuzzleHttp\Promise;
|
12 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
13 |
+
use GuzzleHttp\Psr7;
|
14 |
+
use InvalidArgumentException as IAE;
|
15 |
+
use Psr\Http\Message\RequestInterface;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Encapsulates the execution of a multipart upload to S3 or Glacier.
|
19 |
+
*
|
20 |
+
* @internal
|
21 |
+
*/
|
22 |
+
abstract class AbstractUploadManager implements Promise\PromisorInterface
|
23 |
+
{
|
24 |
+
const DEFAULT_CONCURRENCY = 5;
|
25 |
+
|
26 |
+
/** @var array Default values for base multipart configuration */
|
27 |
+
private static $defaultConfig = [
|
28 |
+
'part_size' => null,
|
29 |
+
'state' => null,
|
30 |
+
'concurrency' => self::DEFAULT_CONCURRENCY,
|
31 |
+
'before_initiate' => null,
|
32 |
+
'before_upload' => null,
|
33 |
+
'before_complete' => null,
|
34 |
+
];
|
35 |
+
|
36 |
+
/** @var Client Client used for the upload. */
|
37 |
+
protected $client;
|
38 |
+
|
39 |
+
/** @var array Configuration used to perform the upload. */
|
40 |
+
protected $config;
|
41 |
+
|
42 |
+
/** @var array Service-specific information about the upload workflow. */
|
43 |
+
protected $info;
|
44 |
+
|
45 |
+
/** @var PromiseInterface Promise that represents the multipart upload. */
|
46 |
+
protected $promise;
|
47 |
+
|
48 |
+
/** @var UploadState State used to manage the upload. */
|
49 |
+
protected $state;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param Client $client
|
53 |
+
* @param array $config
|
54 |
+
*/
|
55 |
+
public function __construct(Client $client, array $config = [])
|
56 |
+
{
|
57 |
+
$this->client = $client;
|
58 |
+
$this->info = $this->loadUploadWorkflowInfo();
|
59 |
+
$this->config = $config + self::$defaultConfig;
|
60 |
+
$this->state = $this->determineState();
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Returns the current state of the upload
|
65 |
+
*
|
66 |
+
* @return UploadState
|
67 |
+
*/
|
68 |
+
public function getState()
|
69 |
+
{
|
70 |
+
return $this->state;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Upload the source using multipart upload operations.
|
75 |
+
*
|
76 |
+
* @return Result The result of the CompleteMultipartUpload operation.
|
77 |
+
* @throws \LogicException if the upload is already complete or aborted.
|
78 |
+
* @throws MultipartUploadException if an upload operation fails.
|
79 |
+
*/
|
80 |
+
public function upload()
|
81 |
+
{
|
82 |
+
return $this->promise()->wait();
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Upload the source asynchronously using multipart upload operations.
|
87 |
+
*
|
88 |
+
* @return PromiseInterface
|
89 |
+
*/
|
90 |
+
public function promise()
|
91 |
+
{
|
92 |
+
if ($this->promise) {
|
93 |
+
return $this->promise;
|
94 |
+
}
|
95 |
+
|
96 |
+
return $this->promise = Promise\coroutine(function () {
|
97 |
+
// Initiate the upload.
|
98 |
+
if ($this->state->isCompleted()) {
|
99 |
+
throw new \LogicException('This multipart upload has already '
|
100 |
+
. 'been completed or aborted.'
|
101 |
+
);
|
102 |
+
} elseif (!$this->state->isInitiated()) {
|
103 |
+
$result = (yield $this->execCommand('initiate', $this->getInitiateParams()));
|
104 |
+
$this->state->setUploadId(
|
105 |
+
$this->info['id']['upload_id'],
|
106 |
+
$result[$this->info['id']['upload_id']]
|
107 |
+
);
|
108 |
+
$this->state->setStatus(UploadState::INITIATED);
|
109 |
+
}
|
110 |
+
|
111 |
+
// Create a command pool from a generator that yields UploadPart
|
112 |
+
// commands for each upload part.
|
113 |
+
$resultHandler = $this->getResultHandler($errors);
|
114 |
+
$commands = new CommandPool(
|
115 |
+
$this->client,
|
116 |
+
$this->getUploadCommands($resultHandler),
|
117 |
+
[
|
118 |
+
'concurrency' => $this->config['concurrency'],
|
119 |
+
'before' => $this->config['before_upload'],
|
120 |
+
]
|
121 |
+
);
|
122 |
+
|
123 |
+
// Execute the pool of commands concurrently, and process errors.
|
124 |
+
yield $commands->promise();
|
125 |
+
if ($errors) {
|
126 |
+
throw new MultipartUploadException($this->state, $errors);
|
127 |
+
}
|
128 |
+
|
129 |
+
// Complete the multipart upload.
|
130 |
+
yield $this->execCommand('complete', $this->getCompleteParams());
|
131 |
+
$this->state->setStatus(UploadState::COMPLETED);
|
132 |
+
})->otherwise(function (\Exception $e) {
|
133 |
+
// Throw errors from the operations as a specific Multipart error.
|
134 |
+
if ($e instanceof AwsException) {
|
135 |
+
$e = new MultipartUploadException($this->state, $e);
|
136 |
+
}
|
137 |
+
throw $e;
|
138 |
+
});
|
139 |
+
}
|
140 |
+
|
141 |
+
protected function getConfig()
|
142 |
+
{
|
143 |
+
return $this->config;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Provides service-specific information about the multipart upload
|
148 |
+
* workflow.
|
149 |
+
*
|
150 |
+
* This array of data should include the keys: 'command', 'id', and 'part_num'.
|
151 |
+
*
|
152 |
+
* @return array
|
153 |
+
*/
|
154 |
+
abstract protected function loadUploadWorkflowInfo();
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Determines the part size to use for upload parts.
|
158 |
+
*
|
159 |
+
* Examines the provided partSize value and the source to determine the
|
160 |
+
* best possible part size.
|
161 |
+
*
|
162 |
+
* @throws \InvalidArgumentException if the part size is invalid.
|
163 |
+
*
|
164 |
+
* @return int
|
165 |
+
*/
|
166 |
+
abstract protected function determinePartSize();
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Uses information from the Command and Result to determine which part was
|
170 |
+
* uploaded and mark it as uploaded in the upload's state.
|
171 |
+
*
|
172 |
+
* @param CommandInterface $command
|
173 |
+
* @param ResultInterface $result
|
174 |
+
*/
|
175 |
+
abstract protected function handleResult(
|
176 |
+
CommandInterface $command,
|
177 |
+
ResultInterface $result
|
178 |
+
);
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Gets the service-specific parameters used to initiate the upload.
|
182 |
+
*
|
183 |
+
* @return array
|
184 |
+
*/
|
185 |
+
abstract protected function getInitiateParams();
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Gets the service-specific parameters used to complete the upload.
|
189 |
+
*
|
190 |
+
* @return array
|
191 |
+
*/
|
192 |
+
abstract protected function getCompleteParams();
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Based on the config and service-specific workflow info, creates a
|
196 |
+
* `Promise` for an `UploadState` object.
|
197 |
+
*
|
198 |
+
* @return PromiseInterface A `Promise` that resolves to an `UploadState`.
|
199 |
+
*/
|
200 |
+
private function determineState()
|
201 |
+
{
|
202 |
+
// If the state was provided via config, then just use it.
|
203 |
+
if ($this->config['state'] instanceof UploadState) {
|
204 |
+
return $this->config['state'];
|
205 |
+
}
|
206 |
+
|
207 |
+
// Otherwise, construct a new state from the provided identifiers.
|
208 |
+
$required = $this->info['id'];
|
209 |
+
$id = [$required['upload_id'] => null];
|
210 |
+
unset($required['upload_id']);
|
211 |
+
foreach ($required as $key => $param) {
|
212 |
+
if (!$this->config[$key]) {
|
213 |
+
throw new IAE('You must provide a value for "' . $key . '" in '
|
214 |
+
. 'your config for the MultipartUploader for '
|
215 |
+
. $this->client->getApi()->getServiceFullName() . '.');
|
216 |
+
}
|
217 |
+
$id[$param] = $this->config[$key];
|
218 |
+
}
|
219 |
+
$state = new UploadState($id);
|
220 |
+
$state->setPartSize($this->determinePartSize());
|
221 |
+
|
222 |
+
return $state;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Executes a MUP command with all of the parameters for the operation.
|
227 |
+
*
|
228 |
+
* @param string $operation Name of the operation.
|
229 |
+
* @param array $params Service-specific params for the operation.
|
230 |
+
*
|
231 |
+
* @return PromiseInterface
|
232 |
+
*/
|
233 |
+
private function execCommand($operation, array $params)
|
234 |
+
{
|
235 |
+
// Create the command.
|
236 |
+
$command = $this->client->getCommand(
|
237 |
+
$this->info['command'][$operation],
|
238 |
+
$params + $this->state->getId()
|
239 |
+
);
|
240 |
+
|
241 |
+
// Execute the before callback.
|
242 |
+
if (is_callable($this->config["before_{$operation}"])) {
|
243 |
+
$this->config["before_{$operation}"]($command);
|
244 |
+
}
|
245 |
+
|
246 |
+
// Execute the command asynchronously and return the promise.
|
247 |
+
return $this->client->executeAsync($command);
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Returns a middleware for processing responses of part upload operations.
|
252 |
+
*
|
253 |
+
* - Adds an onFulfilled callback that calls the service-specific
|
254 |
+
* handleResult method on the Result of the operation.
|
255 |
+
* - Adds an onRejected callback that adds the error to an array of errors.
|
256 |
+
* - Has a passedByRef $errors arg that the exceptions get added to. The
|
257 |
+
* caller should use that &$errors array to do error handling.
|
258 |
+
*
|
259 |
+
* @param array $errors Errors from upload operations are added to this.
|
260 |
+
*
|
261 |
+
* @return callable
|
262 |
+
*/
|
263 |
+
private function getResultHandler(&$errors = [])
|
264 |
+
{
|
265 |
+
return function (callable $handler) use (&$errors) {
|
266 |
+
return function (
|
267 |
+
CommandInterface $command,
|
268 |
+
RequestInterface $request = null
|
269 |
+
) use ($handler, &$errors) {
|
270 |
+
return $handler($command, $request)->then(
|
271 |
+
function (ResultInterface $result) use ($command) {
|
272 |
+
$this->handleResult($command, $result);
|
273 |
+
return $result;
|
274 |
+
},
|
275 |
+
function (AwsException $e) use (&$errors) {
|
276 |
+
$errors[$e->getCommand()[$this->info['part_num']]] = $e;
|
277 |
+
return new Result();
|
278 |
+
}
|
279 |
+
);
|
280 |
+
};
|
281 |
+
};
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Creates a generator that yields part data for the upload's source.
|
286 |
+
*
|
287 |
+
* Yields associative arrays of parameters that are ultimately merged in
|
288 |
+
* with others to form the complete parameters of a command. This can
|
289 |
+
* include the Body parameter, which is a limited stream (i.e., a Stream
|
290 |
+
* object, decorated with a LimitStream).
|
291 |
+
*
|
292 |
+
* @param callable $resultHandler
|
293 |
+
*
|
294 |
+
* @return \Generator
|
295 |
+
*/
|
296 |
+
abstract protected function getUploadCommands(callable $resultHandler);
|
297 |
+
}
|
includes/aws/Aws/Multipart/AbstractUploader.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Multipart;
|
3 |
+
|
4 |
+
use Aws\AwsClientInterface as Client;
|
5 |
+
use GuzzleHttp\Psr7;
|
6 |
+
use InvalidArgumentException as IAE;
|
7 |
+
use Psr\Http\Message\StreamInterface as Stream;
|
8 |
+
|
9 |
+
abstract class AbstractUploader extends AbstractUploadManager
|
10 |
+
{
|
11 |
+
/** @var Stream Source of the data to be uploaded. */
|
12 |
+
protected $source;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param Client $client
|
16 |
+
* @param mixed $source
|
17 |
+
* @param array $config
|
18 |
+
*/
|
19 |
+
public function __construct(Client $client, $source, array $config = [])
|
20 |
+
{
|
21 |
+
$this->source = $this->determineSource($source);
|
22 |
+
parent::__construct($client, $config);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Create a stream for a part that starts at the current position and
|
27 |
+
* has a length of the upload part size (or less with the final part).
|
28 |
+
*
|
29 |
+
* @param Stream $stream
|
30 |
+
*
|
31 |
+
* @return Psr7\LimitStream
|
32 |
+
*/
|
33 |
+
protected function limitPartStream(Stream $stream)
|
34 |
+
{
|
35 |
+
// Limit what is read from the stream to the part size.
|
36 |
+
return new Psr7\LimitStream(
|
37 |
+
$stream,
|
38 |
+
$this->state->getPartSize(),
|
39 |
+
$this->source->tell()
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function getUploadCommands(callable $resultHandler)
|
44 |
+
{
|
45 |
+
// Determine if the source can be seeked.
|
46 |
+
$seekable = $this->source->isSeekable()
|
47 |
+
&& $this->source->getMetadata('wrapper_type') === 'plainfile';
|
48 |
+
|
49 |
+
for ($partNumber = 1; $this->isEof($seekable); $partNumber++) {
|
50 |
+
// If we haven't already uploaded this part, yield a new part.
|
51 |
+
if (!$this->state->hasPartBeenUploaded($partNumber)) {
|
52 |
+
$partStartPos = $this->source->tell();
|
53 |
+
if (!($data = $this->createPart($seekable, $partNumber))) {
|
54 |
+
break;
|
55 |
+
}
|
56 |
+
$command = $this->client->getCommand(
|
57 |
+
$this->info['command']['upload'],
|
58 |
+
$data + $this->state->getId()
|
59 |
+
);
|
60 |
+
$command->getHandlerList()->appendSign($resultHandler, 'mup');
|
61 |
+
yield $command;
|
62 |
+
if ($this->source->tell() > $partStartPos) {
|
63 |
+
continue;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
// Advance the source's offset if not already advanced.
|
68 |
+
if ($seekable) {
|
69 |
+
$this->source->seek(min(
|
70 |
+
$this->source->tell() + $this->state->getPartSize(),
|
71 |
+
$this->source->getSize()
|
72 |
+
));
|
73 |
+
} else {
|
74 |
+
$this->source->read($this->state->getPartSize());
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Generates the parameters for an upload part by analyzing a range of the
|
81 |
+
* source starting from the current offset up to the part size.
|
82 |
+
*
|
83 |
+
* @param bool $seekable
|
84 |
+
* @param int $number
|
85 |
+
*
|
86 |
+
* @return array|null
|
87 |
+
*/
|
88 |
+
abstract protected function createPart($seekable, $number);
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Checks if the source is at EOF.
|
92 |
+
*
|
93 |
+
* @param bool $seekable
|
94 |
+
*
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
+
private function isEof($seekable)
|
98 |
+
{
|
99 |
+
return $seekable
|
100 |
+
? $this->source->tell() < $this->source->getSize()
|
101 |
+
: !$this->source->eof();
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Turns the provided source into a stream and stores it.
|
106 |
+
*
|
107 |
+
* If a string is provided, it is assumed to be a filename, otherwise, it
|
108 |
+
* passes the value directly to `Psr7\stream_for()`.
|
109 |
+
*
|
110 |
+
* @param mixed $source
|
111 |
+
*
|
112 |
+
* @return Stream
|
113 |
+
*/
|
114 |
+
private function determineSource($source)
|
115 |
+
{
|
116 |
+
// Use the contents of a file as the data source.
|
117 |
+
if (is_string($source)) {
|
118 |
+
$source = Psr7\try_fopen($source, 'r');
|
119 |
+
}
|
120 |
+
|
121 |
+
// Create a source stream.
|
122 |
+
$stream = Psr7\stream_for($source);
|
123 |
+
if (!$stream->isReadable()) {
|
124 |
+
throw new IAE('Source stream must be readable.');
|
125 |
+
}
|
126 |
+
|
127 |
+
return $stream;
|
128 |
+
}
|
129 |
+
}
|
includes/aws/Aws/Multipart/UploadState.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Multipart;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Representation of the multipart upload.
|
6 |
+
*
|
7 |
+
* This object keeps track of the state of the upload, including the status and
|
8 |
+
* which parts have been uploaded.
|
9 |
+
*/
|
10 |
+
class UploadState
|
11 |
+
{
|
12 |
+
const CREATED = 0;
|
13 |
+
const INITIATED = 1;
|
14 |
+
const COMPLETED = 2;
|
15 |
+
|
16 |
+
/** @var array Params used to identity the upload. */
|
17 |
+
private $id;
|
18 |
+
|
19 |
+
/** @var int Part size being used by the upload. */
|
20 |
+
private $partSize;
|
21 |
+
|
22 |
+
/** @var array Parts that have been uploaded. */
|
23 |
+
private $uploadedParts = [];
|
24 |
+
|
25 |
+
/** @var int Identifies the status the upload. */
|
26 |
+
private $status = self::CREATED;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param array $id Params used to identity the upload.
|
30 |
+
*/
|
31 |
+
public function __construct(array $id)
|
32 |
+
{
|
33 |
+
$this->id = $id;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Get the upload's ID, which is a tuple of parameters that can uniquely
|
38 |
+
* identify the upload.
|
39 |
+
*
|
40 |
+
* @return array
|
41 |
+
*/
|
42 |
+
public function getId()
|
43 |
+
{
|
44 |
+
return $this->id;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Set's the "upload_id", or 3rd part of the upload's ID. This typically
|
49 |
+
* only needs to be done after initiating an upload.
|
50 |
+
*
|
51 |
+
* @param string $key The param key of the upload_id.
|
52 |
+
* @param string $value The param value of the upload_id.
|
53 |
+
*/
|
54 |
+
public function setUploadId($key, $value)
|
55 |
+
{
|
56 |
+
$this->id[$key] = $value;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Get the part size.
|
61 |
+
*
|
62 |
+
* @return int
|
63 |
+
*/
|
64 |
+
public function getPartSize()
|
65 |
+
{
|
66 |
+
return $this->partSize;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Set the part size.
|
71 |
+
*
|
72 |
+
* @param $partSize int Size of upload parts.
|
73 |
+
*/
|
74 |
+
public function setPartSize($partSize)
|
75 |
+
{
|
76 |
+
$this->partSize = $partSize;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Marks a part as being uploaded.
|
81 |
+
*
|
82 |
+
* @param int $partNumber The part number.
|
83 |
+
* @param array $partData Data from the upload operation that needs to be
|
84 |
+
* recalled during the complete operation.
|
85 |
+
*/
|
86 |
+
public function markPartAsUploaded($partNumber, array $partData = [])
|
87 |
+
{
|
88 |
+
$this->uploadedParts[$partNumber] = $partData;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Returns whether a part has been uploaded.
|
93 |
+
*
|
94 |
+
* @param int $partNumber The part number.
|
95 |
+
*
|
96 |
+
* @return bool
|
97 |
+
*/
|
98 |
+
public function hasPartBeenUploaded($partNumber)
|
99 |
+
{
|
100 |
+
return isset($this->uploadedParts[$partNumber]);
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Returns a sorted list of all the uploaded parts.
|
105 |
+
*
|
106 |
+
* @return array
|
107 |
+
*/
|
108 |
+
public function getUploadedParts()
|
109 |
+
{
|
110 |
+
ksort($this->uploadedParts);
|
111 |
+
|
112 |
+
return $this->uploadedParts;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Set the status of the upload.
|
117 |
+
*
|
118 |
+
* @param int $status Status is an integer code defined by the constants
|
119 |
+
* CREATED, INITIATED, and COMPLETED on this class.
|
120 |
+
*/
|
121 |
+
public function setStatus($status)
|
122 |
+
{
|
123 |
+
$this->status = $status;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Determines whether the upload state is in the INITIATED status.
|
128 |
+
*
|
129 |
+
* @return bool
|
130 |
+
*/
|
131 |
+
public function isInitiated()
|
132 |
+
{
|
133 |
+
return $this->status === self::INITIATED;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Determines whether the upload state is in the COMPLETED status.
|
138 |
+
*
|
139 |
+
* @return bool
|
140 |
+
*/
|
141 |
+
public function isCompleted()
|
142 |
+
{
|
143 |
+
return $this->status === self::COMPLETED;
|
144 |
+
}
|
145 |
+
}
|
includes/aws/Aws/PhpHash.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Incremental hashing using PHP's hash functions.
|
6 |
+
*/
|
7 |
+
class PhpHash implements HashInterface
|
8 |
+
{
|
9 |
+
/** @var resource */
|
10 |
+
private $context;
|
11 |
+
|
12 |
+
/** @var string */
|
13 |
+
private $algo;
|
14 |
+
|
15 |
+
/** @var array */
|
16 |
+
private $options;
|
17 |
+
|
18 |
+
/** @var string */
|
19 |
+
private $hash;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param string $algo Hashing algorithm. One of PHP's hash_algos()
|
23 |
+
* return values (e.g. md5, sha1, etc...).
|
24 |
+
* @param array $options Associative array of hashing options:
|
25 |
+
* - key: Secret key used with the hashing algorithm.
|
26 |
+
* - base64: Set to true to base64 encode the value when complete.
|
27 |
+
*/
|
28 |
+
public function __construct($algo, array $options = [])
|
29 |
+
{
|
30 |
+
$this->algo = $algo;
|
31 |
+
$this->options = $options;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function update($data)
|
35 |
+
{
|
36 |
+
if ($this->hash !== null) {
|
37 |
+
$this->reset();
|
38 |
+
}
|
39 |
+
|
40 |
+
hash_update($this->getContext(), $data);
|
41 |
+
}
|
42 |
+
|
43 |
+
public function complete()
|
44 |
+
{
|
45 |
+
if ($this->hash) {
|
46 |
+
return $this->hash;
|
47 |
+
}
|
48 |
+
|
49 |
+
$this->hash = hash_final($this->getContext(), true);
|
50 |
+
|
51 |
+
if (isset($this->options['base64']) && $this->options['base64']) {
|
52 |
+
$this->hash = base64_encode($this->hash);
|
53 |
+
}
|
54 |
+
|
55 |
+
return $this->hash;
|
56 |
+
}
|
57 |
+
|
58 |
+
public function reset()
|
59 |
+
{
|
60 |
+
$this->context = $this->hash = null;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Get a hash context or create one if needed
|
65 |
+
*
|
66 |
+
* @return resource
|
67 |
+
*/
|
68 |
+
private function getContext()
|
69 |
+
{
|
70 |
+
if (!$this->context) {
|
71 |
+
$key = isset($this->options['key']) ? $this->options['key'] : null;
|
72 |
+
$this->context = hash_init(
|
73 |
+
$this->algo,
|
74 |
+
$key ? HASH_HMAC : 0,
|
75 |
+
$key
|
76 |
+
);
|
77 |
+
}
|
78 |
+
|
79 |
+
return $this->context;
|
80 |
+
}
|
81 |
+
}
|
includes/aws/Aws/Result.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use JmesPath\Env as JmesPath;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS result.
|
8 |
+
*/
|
9 |
+
class Result implements ResultInterface
|
10 |
+
{
|
11 |
+
use HasDataTrait;
|
12 |
+
|
13 |
+
public function __construct(array $data = [])
|
14 |
+
{
|
15 |
+
$this->data = $data;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function hasKey($name)
|
19 |
+
{
|
20 |
+
return isset($this->data[$name]);
|
21 |
+
}
|
22 |
+
|
23 |
+
public function get($key)
|
24 |
+
{
|
25 |
+
return $this[$key];
|
26 |
+
}
|
27 |
+
|
28 |
+
public function search($expression)
|
29 |
+
{
|
30 |
+
return JmesPath::search($expression, $this->toArray());
|
31 |
+
}
|
32 |
+
|
33 |
+
public function __toString()
|
34 |
+
{
|
35 |
+
$jsonData = json_encode($this->toArray(), JSON_PRETTY_PRINT);
|
36 |
+
return <<<EOT
|
37 |
+
Model Data
|
38 |
+
----------
|
39 |
+
Data can be retrieved from the model object using the get() method of the
|
40 |
+
model (e.g., `\$result->get(\$key)`) or "accessing the result like an
|
41 |
+
associative array (e.g. `\$result['key']`). You can also execute JMESPath
|
42 |
+
expressions on the result data using the search() method.
|
43 |
+
|
44 |
+
{$jsonData}
|
45 |
+
|
46 |
+
EOT;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @deprecated
|
51 |
+
*/
|
52 |
+
public function getPath($path)
|
53 |
+
{
|
54 |
+
return $this->search(str_replace('/', '.', $path));
|
55 |
+
}
|
56 |
+
}
|
includes/aws/Aws/ResultInterface.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents an AWS result object that is returned from executing an operation.
|
6 |
+
*/
|
7 |
+
interface ResultInterface extends \ArrayAccess, \IteratorAggregate, \Countable
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Provides debug information about the result object
|
11 |
+
*
|
12 |
+
* @return string
|
13 |
+
*/
|
14 |
+
public function __toString();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Convert the result to an array.
|
18 |
+
*
|
19 |
+
* @return array
|
20 |
+
*/
|
21 |
+
public function toArray();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Check if the model contains a key by name
|
25 |
+
*
|
26 |
+
* @param string $name Name of the key to retrieve
|
27 |
+
*
|
28 |
+
* @return bool
|
29 |
+
*/
|
30 |
+
public function hasKey($name);
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Get a specific key value from the result model.
|
34 |
+
*
|
35 |
+
* @param string $key Key to retrieve.
|
36 |
+
*
|
37 |
+
* @return mixed|null Value of the key or NULL if not found.
|
38 |
+
*/
|
39 |
+
public function get($key);
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Returns the result of executing a JMESPath expression on the contents
|
43 |
+
* of the Result model.
|
44 |
+
*
|
45 |
+
* $result = $client->execute($command);
|
46 |
+
* $jpResult = $result->search('foo.*.bar[?baz > `10`]');
|
47 |
+
*
|
48 |
+
* @param string $expression JMESPath expression to execute
|
49 |
+
*
|
50 |
+
* @return mixed Returns the result of the JMESPath expression.
|
51 |
+
* @link http://jmespath.readthedocs.org/en/latest/ JMESPath documentation
|
52 |
+
*/
|
53 |
+
public function search($expression);
|
54 |
+
};
|
includes/aws/Aws/ResultPaginator.php
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Iterator that yields each page of results of a pageable operation.
|
8 |
+
*/
|
9 |
+
class ResultPaginator implements \Iterator
|
10 |
+
{
|
11 |
+
/** @var AwsClientInterface Client performing operations. */
|
12 |
+
private $client;
|
13 |
+
|
14 |
+
/** @var string Name of the operation being paginated. */
|
15 |
+
private $operation;
|
16 |
+
|
17 |
+
/** @var array Args for the operation. */
|
18 |
+
private $args;
|
19 |
+
|
20 |
+
/** @var array Configuration for the paginator. */
|
21 |
+
private $config;
|
22 |
+
|
23 |
+
/** @var Result Most recent result from the client. */
|
24 |
+
private $result;
|
25 |
+
|
26 |
+
/** @var string|array Next token to use for pagination. */
|
27 |
+
private $nextToken;
|
28 |
+
|
29 |
+
/** @var int Number of operations/requests performed. */
|
30 |
+
private $requestCount = 0;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param AwsClientInterface $client
|
34 |
+
* @param string $operation
|
35 |
+
* @param array $args
|
36 |
+
* @param array $config
|
37 |
+
*/
|
38 |
+
public function __construct(
|
39 |
+
AwsClientInterface $client,
|
40 |
+
$operation,
|
41 |
+
array $args,
|
42 |
+
array $config
|
43 |
+
) {
|
44 |
+
$this->client = $client;
|
45 |
+
$this->operation = $operation;
|
46 |
+
$this->args = $args;
|
47 |
+
$this->config = $config;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Runs a paginator asynchronously and uses a callback to handle results.
|
52 |
+
*
|
53 |
+
* The callback should have the signature: function (Aws\Result $result).
|
54 |
+
* A non-null return value from the callback will be yielded by the
|
55 |
+
* promise. This means that you can return promises from the callback that
|
56 |
+
* will need to be resolved before continuing iteration over the remaining
|
57 |
+
* items, essentially merging in other promises to the iteration. The last
|
58 |
+
* non-null value returned by the callback will be the result that fulfills
|
59 |
+
* the promise to any downstream promises.
|
60 |
+
*
|
61 |
+
* @param callable $handleResult Callback for handling each page of results.
|
62 |
+
* The callback accepts the result that was
|
63 |
+
* yielded as a single argument. If the
|
64 |
+
* callback returns a promise, the promise
|
65 |
+
* will be merged into the coroutine.
|
66 |
+
*
|
67 |
+
* @return Promise\Promise
|
68 |
+
*/
|
69 |
+
public function each(callable $handleResult)
|
70 |
+
{
|
71 |
+
return Promise\coroutine(function () use ($handleResult) {
|
72 |
+
$nextToken = null;
|
73 |
+
do {
|
74 |
+
$command = $this->createNextCommand($this->args, $nextToken);
|
75 |
+
$result = (yield $this->client->executeAsync($command));
|
76 |
+
$nextToken = $this->determineNextToken($result);
|
77 |
+
$retVal = $handleResult($result);
|
78 |
+
if ($retVal !== null) {
|
79 |
+
yield Promise\promise_for($retVal);
|
80 |
+
}
|
81 |
+
} while ($nextToken);
|
82 |
+
});
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Returns an iterator that iterates over the values of applying a JMESPath
|
87 |
+
* search to each result yielded by the iterator as a flat sequence.
|
88 |
+
*
|
89 |
+
* @param string $expression JMESPath expression to apply to each result.
|
90 |
+
*
|
91 |
+
* @return \Iterator
|
92 |
+
*/
|
93 |
+
public function search($expression)
|
94 |
+
{
|
95 |
+
// Apply JMESPath expression on each result, but as a flat sequence.
|
96 |
+
return flatmap($this, function (Result $result) use ($expression) {
|
97 |
+
return (array) $result->search($expression);
|
98 |
+
});
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* @return Result
|
103 |
+
*/
|
104 |
+
public function current()
|
105 |
+
{
|
106 |
+
return $this->valid() ? $this->result : false;
|
107 |
+
}
|
108 |
+
|
109 |
+
public function key()
|
110 |
+
{
|
111 |
+
return $this->valid() ? $this->requestCount - 1 : null;
|
112 |
+
}
|
113 |
+
|
114 |
+
public function next()
|
115 |
+
{
|
116 |
+
$this->result = null;
|
117 |
+
}
|
118 |
+
|
119 |
+
public function valid()
|
120 |
+
{
|
121 |
+
if ($this->result) {
|
122 |
+
return true;
|
123 |
+
}
|
124 |
+
|
125 |
+
if ($this->nextToken || !$this->requestCount) {
|
126 |
+
$this->result = $this->client->execute(
|
127 |
+
$this->createNextCommand($this->args, $this->nextToken)
|
128 |
+
);
|
129 |
+
$this->nextToken = $this->determineNextToken($this->result);
|
130 |
+
$this->requestCount++;
|
131 |
+
return true;
|
132 |
+
}
|
133 |
+
|
134 |
+
return false;
|
135 |
+
}
|
136 |
+
|
137 |
+
public function rewind()
|
138 |
+
{
|
139 |
+
$this->requestCount = 0;
|
140 |
+
$this->nextToken = null;
|
141 |
+
$this->result = null;
|
142 |
+
}
|
143 |
+
|
144 |
+
private function createNextCommand(array $args, $nextToken)
|
145 |
+
{
|
146 |
+
// Prepare arguments
|
147 |
+
if ($nextToken) {
|
148 |
+
$inputArg = $this->config['input_token'];
|
149 |
+
if (is_array($nextToken) && is_array($inputArg)) {
|
150 |
+
foreach ($inputArg as $index => $key) {
|
151 |
+
$args[$key] = $nextToken[$index];
|
152 |
+
}
|
153 |
+
} else {
|
154 |
+
$args[$inputArg] = $nextToken;
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
return $this->client->getCommand($this->operation, $args);
|
159 |
+
}
|
160 |
+
|
161 |
+
private function determineNextToken(Result $result)
|
162 |
+
{
|
163 |
+
if (!$this->config['output_token']) {
|
164 |
+
return null;
|
165 |
+
}
|
166 |
+
|
167 |
+
if ($this->config['more_results']
|
168 |
+
&& !$result->search($this->config['more_results'])
|
169 |
+
) {
|
170 |
+
return null;
|
171 |
+
}
|
172 |
+
|
173 |
+
$nextToken = is_array($this->config['output_token'])
|
174 |
+
? array_filter($result->search(json_encode($this->config['output_token'])))
|
175 |
+
: $result->search($this->config['output_token']);
|
176 |
+
|
177 |
+
return $nextToken;
|
178 |
+
}
|
179 |
+
}
|
includes/aws/Aws/RetryMiddleware.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @internal Middleware that retries failures.
|
11 |
+
*/
|
12 |
+
class RetryMiddleware
|
13 |
+
{
|
14 |
+
private static $retryStatusCodes = [
|
15 |
+
500 => true,
|
16 |
+
503 => true
|
17 |
+
];
|
18 |
+
|
19 |
+
private static $retryCodes = [
|
20 |
+
'RequestLimitExceeded' => true,
|
21 |
+
'Throttling' => true,
|
22 |
+
'ThrottlingException' => true,
|
23 |
+
'ProvisionedThroughputExceededException' => true,
|
24 |
+
'RequestThrottled' => true,
|
25 |
+
];
|
26 |
+
|
27 |
+
private $decider;
|
28 |
+
private $delay;
|
29 |
+
private $nextHandler;
|
30 |
+
|
31 |
+
public function __construct(
|
32 |
+
callable $decider,
|
33 |
+
callable $delay,
|
34 |
+
callable $nextHandler
|
35 |
+
) {
|
36 |
+
$this->decider = $decider;
|
37 |
+
$this->delay = $delay;
|
38 |
+
$this->nextHandler = $nextHandler;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Creates a default AWS retry decider function.
|
43 |
+
*
|
44 |
+
* @param int $maxRetries
|
45 |
+
*
|
46 |
+
* @return callable
|
47 |
+
*/
|
48 |
+
public static function createDefaultDecider($maxRetries = 3)
|
49 |
+
{
|
50 |
+
return function (
|
51 |
+
$retries,
|
52 |
+
CommandInterface $command,
|
53 |
+
RequestInterface $request,
|
54 |
+
ResultInterface $result = null,
|
55 |
+
$error = null
|
56 |
+
) use ($maxRetries) {
|
57 |
+
// Allow command-level options to override this value
|
58 |
+
$maxRetries = null !== $command['@retries'] ?
|
59 |
+
$command['@retries']
|
60 |
+
: $maxRetries;
|
61 |
+
|
62 |
+
if ($retries >= $maxRetries) {
|
63 |
+
return false;
|
64 |
+
} elseif (!$error) {
|
65 |
+
return isset(self::$retryStatusCodes[$result['@metadata']['statusCode']]);
|
66 |
+
} elseif (!($error instanceof AwsException)) {
|
67 |
+
return false;
|
68 |
+
} elseif ($error->isConnectionError()) {
|
69 |
+
return true;
|
70 |
+
} elseif (isset(self::$retryCodes[$error->getAwsErrorCode()])) {
|
71 |
+
return true;
|
72 |
+
} elseif (isset(self::$retryStatusCodes[$error->getStatusCode()])) {
|
73 |
+
return true;
|
74 |
+
} else {
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
};
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Delay function that calculates an exponential delay.
|
82 |
+
*
|
83 |
+
* @param $retries
|
84 |
+
*
|
85 |
+
* @return int
|
86 |
+
*/
|
87 |
+
public static function exponentialDelay($retries)
|
88 |
+
{
|
89 |
+
return mt_rand(0, (int) pow(2, $retries - 1) * 100);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* @param CommandInterface $command
|
94 |
+
* @param RequestInterface $request
|
95 |
+
*
|
96 |
+
* @return PromiseInterface
|
97 |
+
*/
|
98 |
+
public function __invoke(
|
99 |
+
CommandInterface $command,
|
100 |
+
RequestInterface $request = null
|
101 |
+
) {
|
102 |
+
$retries = 0;
|
103 |
+
$handler = $this->nextHandler;
|
104 |
+
$decider = $this->decider;
|
105 |
+
$delay = $this->delay;
|
106 |
+
|
107 |
+
$g = function ($value) use ($handler, $decider, $delay, $command, $request, &$retries, &$g) {
|
108 |
+
if ($value instanceof \Exception) {
|
109 |
+
if (!$decider($retries, $command, $request, null, $value)) {
|
110 |
+
return \GuzzleHttp\Promise\rejection_for($value);
|
111 |
+
}
|
112 |
+
} elseif ($value instanceof ResultInterface
|
113 |
+
&& !$decider($retries, $command, $request, $value, null)
|
114 |
+
) {
|
115 |
+
return $value;
|
116 |
+
}
|
117 |
+
|
118 |
+
// Delay fn is called with 0, 1, ... so increment after the call.
|
119 |
+
$command['@http']['delay'] = $delay($retries++);
|
120 |
+
return $handler($command, $request)->then($g, $g);
|
121 |
+
};
|
122 |
+
|
123 |
+
return $handler($command, $request)->then($g, $g);
|
124 |
+
}
|
125 |
+
}
|
includes/aws/Aws/S3/AmbiguousSuccessParser.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\AbstractParser;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Aws\Exception\AwsException;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Converts errors returned with a status code of 200 to a retryable error type.
|
11 |
+
*
|
12 |
+
* @internal
|
13 |
+
*/
|
14 |
+
class AmbiguousSuccessParser extends AbstractParser
|
15 |
+
{
|
16 |
+
private static $ambiguousSuccesses = [
|
17 |
+
'UploadPartCopy' => true,
|
18 |
+
'CopyObject' => true,
|
19 |
+
'CompleteMultipartUpload' => true,
|
20 |
+
];
|
21 |
+
|
22 |
+
/** @var callable */
|
23 |
+
private $parser;
|
24 |
+
/** @var callable */
|
25 |
+
private $errorParser;
|
26 |
+
/** @var string */
|
27 |
+
private $exceptionClass;
|
28 |
+
|
29 |
+
public function __construct(
|
30 |
+
callable $parser,
|
31 |
+
callable $errorParser,
|
32 |
+
$exceptionClass = AwsException::class
|
33 |
+
) {
|
34 |
+
$this->parser = $parser;
|
35 |
+
$this->errorParser = $errorParser;
|
36 |
+
$this->exceptionClass = $exceptionClass;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function __invoke(
|
40 |
+
CommandInterface $command,
|
41 |
+
ResponseInterface $response
|
42 |
+
) {
|
43 |
+
if (200 === $response->getStatusCode()
|
44 |
+
&& isset(self::$ambiguousSuccesses[$command->getName()])
|
45 |
+
) {
|
46 |
+
$errorParser = $this->errorParser;
|
47 |
+
$parsed = $errorParser($response);
|
48 |
+
if (isset($parsed['code']) && isset($parsed['message'])) {
|
49 |
+
throw new $this->exceptionClass(
|
50 |
+
$parsed['message'],
|
51 |
+
$command,
|
52 |
+
['connection_error' => true]
|
53 |
+
);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
$fn = $this->parser;
|
58 |
+
return $fn($command, $response);
|
59 |
+
}
|
60 |
+
}
|
includes/aws/Aws/S3/ApplyChecksumMiddleware.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use GuzzleHttp\Psr7;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Apply required or optional MD5s to requests before sending.
|
10 |
+
*
|
11 |
+
* IMPORTANT: This middleware must be added after the "build" step.
|
12 |
+
*
|
13 |
+
* @internal
|
14 |
+
*/
|
15 |
+
class ApplyChecksumMiddleware
|
16 |
+
{
|
17 |
+
private static $md5 = [
|
18 |
+
'DeleteObjects',
|
19 |
+
'PutBucketCors',
|
20 |
+
'PutBucketLifecycle',
|
21 |
+
'PutBucketLifecycleConfiguration',
|
22 |
+
'PutBucketPolicy',
|
23 |
+
'PutBucketTagging',
|
24 |
+
];
|
25 |
+
|
26 |
+
private static $sha256 = [
|
27 |
+
'PutObject',
|
28 |
+
'UploadPart',
|
29 |
+
];
|
30 |
+
|
31 |
+
private $nextHandler;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Create a middleware wrapper function.
|
35 |
+
*
|
36 |
+
* @return callable
|
37 |
+
*/
|
38 |
+
public static function wrap()
|
39 |
+
{
|
40 |
+
return function (callable $handler) {
|
41 |
+
return new self($handler);
|
42 |
+
};
|
43 |
+
}
|
44 |
+
|
45 |
+
public function __construct(callable $nextHandler)
|
46 |
+
{
|
47 |
+
$this->nextHandler = $nextHandler;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function __invoke(
|
51 |
+
CommandInterface $command,
|
52 |
+
RequestInterface $request
|
53 |
+
) {
|
54 |
+
$next = $this->nextHandler;
|
55 |
+
$name = $command->getName();
|
56 |
+
$body = $request->getBody();
|
57 |
+
|
58 |
+
if (in_array($name, self::$md5) && !$request->hasHeader('Content-MD5')) {
|
59 |
+
// Set the content MD5 header for operations that require it.
|
60 |
+
$request = $request->withHeader(
|
61 |
+
'Content-MD5',
|
62 |
+
base64_encode(Psr7\hash($body, 'md5', true))
|
63 |
+
);
|
64 |
+
} elseif (in_array($name, self::$sha256) && $command['ContentSHA256']) {
|
65 |
+
// Set the content hash header if provided in the parameters.
|
66 |
+
$request = $request->withHeader(
|
67 |
+
'X-Amz-Content-Sha256',
|
68 |
+
$command['ContentSHA256']
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
return $next($command, $request);
|
73 |
+
}
|
74 |
+
}
|
includes/aws/Aws/S3/BatchDelete.php
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\AwsClientInterface;
|
5 |
+
use Aws\S3\Exception\DeleteMultipleObjectsException;
|
6 |
+
use GuzzleHttp\Promise;
|
7 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
8 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Efficiently deletes many objects from a single Amazon S3 bucket using an
|
12 |
+
* iterator that yields keys. Deletes are made using the DeleteObjects API
|
13 |
+
* operation.
|
14 |
+
*
|
15 |
+
* $s3 = new Aws\S3\Client([
|
16 |
+
* 'region' => 'us-west-2',
|
17 |
+
* 'version' => 'latest'
|
18 |
+
* ]);
|
19 |
+
*
|
20 |
+
* $listObjectsParams = ['Bucket' => 'foo', 'Prefix' => 'starts/with/'];
|
21 |
+
* $delete = Aws\S3\BatchDelete::fromListObjects($s3, $listObjectsParams);
|
22 |
+
* // Asynchronously delete
|
23 |
+
* $promise = $delete->promise();
|
24 |
+
* // Force synchronous completion
|
25 |
+
* $delete->delete();
|
26 |
+
*
|
27 |
+
* When using one of the batch delete creational static methods, you can supply
|
28 |
+
* an associative array of options:
|
29 |
+
*
|
30 |
+
* - before: Function invoked before executing a command. The function is
|
31 |
+
* passed the command that is about to be executed. This can be useful
|
32 |
+
* for logging, adding custom request headers, etc.
|
33 |
+
* - batch_size: The size of each delete batch. Defaults to 1000.
|
34 |
+
*
|
35 |
+
* @link http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
36 |
+
*/
|
37 |
+
class BatchDelete implements PromisorInterface
|
38 |
+
{
|
39 |
+
private $bucket;
|
40 |
+
/** @var AwsClientInterface */
|
41 |
+
private $client;
|
42 |
+
/** @var callable */
|
43 |
+
private $before;
|
44 |
+
/** @var PromiseInterface */
|
45 |
+
private $cachedPromise;
|
46 |
+
/** @var callable */
|
47 |
+
private $promiseCreator;
|
48 |
+
private $batchSize = 1000;
|
49 |
+
private $queue = [];
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Creates a BatchDelete object from all of the paginated results of a
|
53 |
+
* ListObjects operation. Each result that is returned by the ListObjects
|
54 |
+
* operation will be deleted.
|
55 |
+
*
|
56 |
+
* @param AwsClientInterface $client AWS Client to use.
|
57 |
+
* @param array $listObjectsParams ListObjects API parameters
|
58 |
+
* @param array $options BatchDelete options.
|
59 |
+
*
|
60 |
+
* @return BatchDelete
|
61 |
+
*/
|
62 |
+
public static function fromListObjects(
|
63 |
+
AwsClientInterface $client,
|
64 |
+
array $listObjectsParams,
|
65 |
+
array $options = []
|
66 |
+
) {
|
67 |
+
$iter = $client->getPaginator('ListObjects', $listObjectsParams);
|
68 |
+
$bucket = $listObjectsParams['Bucket'];
|
69 |
+
$fn = function (BatchDelete $that) use ($iter) {
|
70 |
+
return $iter->each(function ($result) use ($that) {
|
71 |
+
$promises = [];
|
72 |
+
if (is_array($result['Contents'])) {
|
73 |
+
foreach ($result['Contents'] as $object) {
|
74 |
+
if ($promise = $that->enqueue($object)) {
|
75 |
+
$promises[] = $promise;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
return $promises ? Promise\all($promises) : null;
|
80 |
+
});
|
81 |
+
};
|
82 |
+
|
83 |
+
return new self($client, $bucket, $fn, $options);
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Creates a BatchDelete object from an iterator that yields results.
|
88 |
+
*
|
89 |
+
* @param AwsClientInterface $client AWS Client to use to execute commands
|
90 |
+
* @param string $bucket Bucket where the objects are stored
|
91 |
+
* @param \Iterator $iter Iterator that yields assoc arrays
|
92 |
+
* @param array $options BatchDelete options
|
93 |
+
*
|
94 |
+
* @return BatchDelete
|
95 |
+
*/
|
96 |
+
public static function fromIterator(
|
97 |
+
AwsClientInterface $client,
|
98 |
+
$bucket,
|
99 |
+
\Iterator $iter,
|
100 |
+
array $options = []
|
101 |
+
) {
|
102 |
+
$fn = function (BatchDelete $that) use ($iter) {
|
103 |
+
return \GuzzleHttp\Promise\coroutine(function () use ($that, $iter) {
|
104 |
+
foreach ($iter as $obj) {
|
105 |
+
if ($promise = $that->enqueue($obj)) {
|
106 |
+
yield $promise;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
});
|
110 |
+
};
|
111 |
+
|
112 |
+
return new self($client, $bucket, $fn, $options);
|
113 |
+
}
|
114 |
+
|
115 |
+
public function promise()
|
116 |
+
{
|
117 |
+
if (!$this->cachedPromise) {
|
118 |
+
$this->cachedPromise = $this->createPromise();
|
119 |
+
}
|
120 |
+
|
121 |
+
return $this->cachedPromise;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Synchronously deletes all of the objects.
|
126 |
+
*
|
127 |
+
* @throws DeleteMultipleObjectsException on error.
|
128 |
+
*/
|
129 |
+
public function delete()
|
130 |
+
{
|
131 |
+
$this->promise()->wait();
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* @param AwsClientInterface $client Client used to transfer the requests
|
136 |
+
* @param string $bucket Bucket to delete from.
|
137 |
+
* @param callable $promiseFn Creates a promise.
|
138 |
+
* @param array $options Hash of options used with the batch
|
139 |
+
*
|
140 |
+
* @throws \InvalidArgumentException if the provided batch_size is <= 0
|
141 |
+
*/
|
142 |
+
private function __construct(
|
143 |
+
AwsClientInterface $client,
|
144 |
+
$bucket,
|
145 |
+
callable $promiseFn,
|
146 |
+
array $options = []
|
147 |
+
) {
|
148 |
+
$this->client = $client;
|
149 |
+
$this->bucket = $bucket;
|
150 |
+
$this->promiseCreator = $promiseFn;
|
151 |
+
|
152 |
+
if (isset($options['before'])) {
|
153 |
+
if (!is_callable($options['before'])) {
|
154 |
+
throw new \InvalidArgumentException('before must be callable');
|
155 |
+
}
|
156 |
+
$this->before = $options['before'];
|
157 |
+
}
|
158 |
+
|
159 |
+
if (isset($options['batch_size'])) {
|
160 |
+
if ($options['batch_size'] <= 0) {
|
161 |
+
throw new \InvalidArgumentException('batch_size is not > 0');
|
162 |
+
}
|
163 |
+
$this->batchSize = min($options['batch_size'], 1000);
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
private function enqueue(array $obj)
|
168 |
+
{
|
169 |
+
$this->queue[] = $obj;
|
170 |
+
return count($this->queue) >= $this->batchSize
|
171 |
+
? $this->flushQueue()
|
172 |
+
: null;
|
173 |
+
}
|
174 |
+
|
175 |
+
private function flushQueue()
|
176 |
+
{
|
177 |
+
static $validKeys = ['Key' => true, 'VersionId' => true];
|
178 |
+
|
179 |
+
if (count($this->queue) === 0) {
|
180 |
+
return null;
|
181 |
+
}
|
182 |
+
|
183 |
+
$batch = [];
|
184 |
+
while ($obj = array_shift($this->queue)) {
|
185 |
+
$batch[] = array_intersect_key($obj, $validKeys);
|
186 |
+
}
|
187 |
+
|
188 |
+
$command = $this->client->getCommand('DeleteObjects', [
|
189 |
+
'Bucket' => $this->bucket,
|
190 |
+
'Delete' => ['Objects' => $batch]
|
191 |
+
]);
|
192 |
+
|
193 |
+
if ($this->before) {
|
194 |
+
call_user_func($this->before, $command);
|
195 |
+
}
|
196 |
+
|
197 |
+
return $this->client->executeAsync($command)
|
198 |
+
->then(function ($result) {
|
199 |
+
if (!empty($result['Errors'])) {
|
200 |
+
throw new DeleteMultipleObjectsException(
|
201 |
+
$result['Deleted'] ?: [],
|
202 |
+
$result['Errors']
|
203 |
+
);
|
204 |
+
}
|
205 |
+
return $result;
|
206 |
+
});
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Returns a promise that will clean up any references when it completes.
|
211 |
+
*
|
212 |
+
* @return PromiseInterface
|
213 |
+
*/
|
214 |
+
private function createPromise()
|
215 |
+
{
|
216 |
+
// Create the promise
|
217 |
+
$promise = call_user_func($this->promiseCreator, $this);
|
218 |
+
$this->promiseCreator = null;
|
219 |
+
|
220 |
+
// Cleans up the promise state and references.
|
221 |
+
$cleanup = function () {
|
222 |
+
$this->before = $this->client = $this->queue = null;
|
223 |
+
};
|
224 |
+
|
225 |
+
// When done, ensure cleanup and that any remaining are processed.
|
226 |
+
return $promise->then(
|
227 |
+
function () use ($cleanup) {
|
228 |
+
return Promise\promise_for($this->flushQueue())
|
229 |
+
->then($cleanup);
|
230 |
+
},
|
231 |
+
function ($reason) use ($cleanup) {
|
232 |
+
$cleanup();
|
233 |
+
return Promise\rejection_for($reason);
|
234 |
+
}
|
235 |
+
);
|
236 |
+
}
|
237 |
+
}
|
includes/aws/Aws/S3/BucketEndpointMiddleware.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Used to update the host used for S3 requests in the case of using a
|
9 |
+
* "bucket endpoint" or CNAME bucket.
|
10 |
+
*
|
11 |
+
* IMPORTANT: this middleware must be added after the "build" step.
|
12 |
+
*
|
13 |
+
* @internal
|
14 |
+
*/
|
15 |
+
class BucketEndpointMiddleware
|
16 |
+
{
|
17 |
+
private static $exclusions = ['GetBucketLocation' => true];
|
18 |
+
private $nextHandler;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Create a middleware wrapper function.
|
22 |
+
*
|
23 |
+
* @return callable
|
24 |
+
*/
|
25 |
+
public static function wrap()
|
26 |
+
{
|
27 |
+
return function (callable $handler) {
|
28 |
+
return new self($handler);
|
29 |
+
};
|
30 |
+
}
|
31 |
+
|
32 |
+
public function __construct(callable $nextHandler)
|
33 |
+
{
|
34 |
+
$this->nextHandler = $nextHandler;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function __invoke(CommandInterface $command, RequestInterface $request)
|
38 |
+
{
|
39 |
+
$nextHandler = $this->nextHandler;
|
40 |
+
$bucket = $command['Bucket'];
|
41 |
+
|
42 |
+
if ($bucket && !isset(self::$exclusions[$command->getName()])) {
|
43 |
+
$request = $this->modifyRequest($request, $command);
|
44 |
+
}
|
45 |
+
|
46 |
+
return $nextHandler($command, $request);
|
47 |
+
}
|
48 |
+
|
49 |
+
private function removeBucketFromPath($path, $bucket)
|
50 |
+
{
|
51 |
+
$len = strlen($bucket) + 1;
|
52 |
+
if (substr($path, 0, $len) === "/{$bucket}") {
|
53 |
+
$path = substr($path, $len);
|
54 |
+
}
|
55 |
+
|
56 |
+
return $path ?: '/';
|
57 |
+
}
|
58 |
+
|
59 |
+
private function modifyRequest(
|
60 |
+
RequestInterface $request,
|
61 |
+
CommandInterface $command
|
62 |
+
) {
|
63 |
+
$uri = $request->getUri();
|
64 |
+
$path = $uri->getPath();
|
65 |
+
$bucket = $command['Bucket'];
|
66 |
+
$path = $this->removeBucketFromPath($path, $bucket);
|
67 |
+
|
68 |
+
// Modify the Key to make sure the key is encoded, but slashes are not.
|
69 |
+
if ($command['Key']) {
|
70 |
+
$path = S3Client::encodeKey(rawurldecode($path));
|
71 |
+
}
|
72 |
+
|
73 |
+
return $request->withUri($uri->withPath($path));
|
74 |
+
}
|
75 |
+
}
|
includes/aws/Aws/S3/Exception/DeleteMultipleObjectsException.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3\Exception;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Exception thrown when errors occur while deleting objects using a
|
6 |
+
* {@see S3\BatchDelete} object.
|
7 |
+
*/
|
8 |
+
class DeleteMultipleObjectsException extends \Exception
|
9 |
+
{
|
10 |
+
private $deleted = [];
|
11 |
+
private $errors = [];
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @param array $deleted Array of successfully deleted keys
|
15 |
+
* @param array $errors Array of errors that were encountered
|
16 |
+
*/
|
17 |
+
public function __construct(array $deleted, array $errors)
|
18 |
+
{
|
19 |
+
$this->deleted = array_values($deleted);
|
20 |
+
$this->errors = array_values($errors);
|
21 |
+
parent::__construct('Unable to delete certain keys when executing a'
|
22 |
+
. ' DeleteMultipleObjects request: '
|
23 |
+
. self::createMessageFromErrors($errors));
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Create a single error message from multiple errors.
|
28 |
+
*
|
29 |
+
* @param array $errors Errors encountered
|
30 |
+
*
|
31 |
+
* @return string
|
32 |
+
*/
|
33 |
+
public static function createMessageFromErrors(array $errors)
|
34 |
+
{
|
35 |
+
return "\n- " . implode("\n- ", array_map(function ($key) {
|
36 |
+
return json_encode($key);
|
37 |
+
}, $errors));
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Get the errored objects
|
42 |
+
*
|
43 |
+
* @return array Returns an array of associative arrays, each containing
|
44 |
+
* a 'Code', 'Message', and 'Key' key.
|
45 |
+
*/
|
46 |
+
public function getErrors()
|
47 |
+
{
|
48 |
+
return $this->errors;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get the successfully deleted objects
|
53 |
+
*
|
54 |
+
* @return array Returns an array of associative arrays, each containing
|
55 |
+
* a 'Key' and optionally 'DeleteMarker' and
|
56 |
+
* 'DeleterMarkerVersionId'
|
57 |
+
*/
|
58 |
+
public function getDeleted()
|
59 |
+
{
|
60 |
+
return $this->deleted;
|
61 |
+
}
|
62 |
+
}
|
includes/aws/Aws/S3/Exception/PermanentRedirectException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3\Exception;
|
3 |
+
|
4 |
+
class PermanentRedirectException extends S3Exception {}
|
includes/aws/Aws/S3/Exception/S3Exception.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the Amazon Simple Storage Service.
|
8 |
+
*/
|
9 |
+
class S3Exception extends AwsException {}
|
includes/aws/Aws/S3/GetBucketLocationParser.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\AbstractParser;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @internal Decorates a parser for the S3 service to correctly handle the
|
10 |
+
* GetBucketLocation operation.
|
11 |
+
*/
|
12 |
+
class GetBucketLocationParser extends AbstractParser
|
13 |
+
{
|
14 |
+
/** @var callable */
|
15 |
+
private $parser;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param callable $parser Parser to wrap.
|
19 |
+
*/
|
20 |
+
public function __construct(callable $parser)
|
21 |
+
{
|
22 |
+
$this->parser = $parser;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function __invoke(
|
26 |
+
CommandInterface $command,
|
27 |
+
ResponseInterface $response
|
28 |
+
) {
|
29 |
+
$fn = $this->parser;
|
30 |
+
$result = $fn($command, $response);
|
31 |
+
|
32 |
+
if ($command->getName() === 'GetBucketLocation') {
|
33 |
+
$location = 'us-east-1';
|
34 |
+
if (preg_match('/>(.+?)<\/LocationConstraint>/', $response->getBody(), $matches)) {
|
35 |
+
$location = $matches[1] === 'EU' ? 'eu-west-1' : $matches[1];
|
36 |
+
}
|
37 |
+
$result['LocationConstraint'] = $location;
|
38 |
+
}
|
39 |
+
|
40 |
+
return $result;
|
41 |
+
}
|
42 |
+
}
|
includes/aws/Aws/S3/MultipartCopy.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Multipart\AbstractUploadManager;
|
5 |
+
use Aws\ResultInterface;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
|
8 |
+
class MultipartCopy extends AbstractUploadManager
|
9 |
+
{
|
10 |
+
use MultipartUploadingTrait;
|
11 |
+
|
12 |
+
/** @var string */
|
13 |
+
private $source;
|
14 |
+
/** @var ResultInterface */
|
15 |
+
private $sourceMetadata;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Creates a multipart upload for copying an S3 object.
|
19 |
+
*
|
20 |
+
* The valid configuration options are as follows:
|
21 |
+
*
|
22 |
+
* - acl: (string) ACL to set on the object being upload. Objects are
|
23 |
+
* private by default.
|
24 |
+
* - before_complete: (callable) Callback to invoke before the
|
25 |
+
* `CompleteMultipartUpload` operation. The callback should have a
|
26 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
27 |
+
* - before_initiate: (callable) Callback to invoke before the
|
28 |
+
* `CreateMultipartUpload` operation. The callback should have a function
|
29 |
+
* signature like `function (Aws\Command $command) {...}`.
|
30 |
+
* - before_upload: (callable) Callback to invoke before `UploadPartCopy`
|
31 |
+
* operations. The callback should have a function signature like
|
32 |
+
* `function (Aws\Command $command) {...}`.
|
33 |
+
* - bucket: (string, required) Name of the bucket to which the object is
|
34 |
+
* being uploaded.
|
35 |
+
* - concurrency: (int, default=int(5)) Maximum number of concurrent
|
36 |
+
* `UploadPart` operations allowed during the multipart upload.
|
37 |
+
* - key: (string, required) Key to use for the object being uploaded.
|
38 |
+
* - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
|
39 |
+
* doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
|
40 |
+
* - state: (Aws\Multipart\UploadState) An object that represents the state
|
41 |
+
* of the multipart upload and that is used to resume a previous upload.
|
42 |
+
* When this option is provided, the `bucket`, `key`, and `part_size`
|
43 |
+
* options are ignored.
|
44 |
+
* - source_metadata: (Aws\ResultInterface) An object that represents the
|
45 |
+
* result of executing a HeadObject command on the copy source.
|
46 |
+
*
|
47 |
+
* @param S3Client $client Client used for the upload.
|
48 |
+
* @param string $source Location of the data to be copied
|
49 |
+
* (in the form /<bucket>/<key>).
|
50 |
+
* @param array $config Configuration used to perform the upload.
|
51 |
+
*/
|
52 |
+
public function __construct(S3Client $client, $source, array $config = [])
|
53 |
+
{
|
54 |
+
$this->source = '/' . ltrim($source, '/');
|
55 |
+
parent::__construct($client, array_change_key_case($config) + [
|
56 |
+
'source_metadata' => null
|
57 |
+
]);
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* An alias of the self::upload method.
|
62 |
+
*
|
63 |
+
* @see self::upload
|
64 |
+
*/
|
65 |
+
public function copy()
|
66 |
+
{
|
67 |
+
return $this->upload();
|
68 |
+
}
|
69 |
+
|
70 |
+
protected function loadUploadWorkflowInfo()
|
71 |
+
{
|
72 |
+
return [
|
73 |
+
'command' => [
|
74 |
+
'initiate' => 'CreateMultipartUpload',
|
75 |
+
'upload' => 'UploadPartCopy',
|
76 |
+
'complete' => 'CompleteMultipartUpload',
|
77 |
+
],
|
78 |
+
'id' => [
|
79 |
+
'bucket' => 'Bucket',
|
80 |
+
'key' => 'Key',
|
81 |
+
'upload_id' => 'UploadId',
|
82 |
+
],
|
83 |
+
'part_num' => 'PartNumber',
|
84 |
+
];
|
85 |
+
}
|
86 |
+
|
87 |
+
protected function getUploadCommands(callable $resultHandler)
|
88 |
+
{
|
89 |
+
$parts = ceil($this->getSourceSize() / $this->determinePartSize());
|
90 |
+
|
91 |
+
for ($partNumber = 1; $partNumber <= $parts; $partNumber++) {
|
92 |
+
// If we haven't already uploaded this part, yield a new part.
|
93 |
+
if (!$this->state->hasPartBeenUploaded($partNumber)) {
|
94 |
+
$command = $this->client->getCommand(
|
95 |
+
$this->info['command']['upload'],
|
96 |
+
$this->createPart($partNumber, $parts)
|
97 |
+
+ $this->getState()->getId()
|
98 |
+
);
|
99 |
+
$command->getHandlerList()->appendSign($resultHandler, 'mup');
|
100 |
+
yield $command;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
private function createPart($partNumber, $partsCount)
|
106 |
+
{
|
107 |
+
$defaultPartSize = $this->determinePartSize();
|
108 |
+
$startByte = $defaultPartSize * ($partNumber - 1);
|
109 |
+
$partSize = $partNumber < $partsCount
|
110 |
+
? $defaultPartSize
|
111 |
+
: $this->getSourceSize() - ($defaultPartSize * ($partsCount - 1));
|
112 |
+
$endByte = $startByte + $partSize - 1;
|
113 |
+
|
114 |
+
return [
|
115 |
+
'ContentLength' => $partSize,
|
116 |
+
'CopySource' => $this->source,
|
117 |
+
'CopySourceRange' => "bytes=$startByte-$endByte",
|
118 |
+
'PartNumber' => $partNumber,
|
119 |
+
];
|
120 |
+
}
|
121 |
+
|
122 |
+
protected function extractETag(ResultInterface $result)
|
123 |
+
{
|
124 |
+
return $result->search('CopyPartResult.ETag');
|
125 |
+
}
|
126 |
+
|
127 |
+
protected function getSourceMimeType()
|
128 |
+
{
|
129 |
+
return $this->getSourceMetadata()['ContentType'];
|
130 |
+
}
|
131 |
+
|
132 |
+
protected function getSourceSize()
|
133 |
+
{
|
134 |
+
return $this->getSourceMetadata()['ContentLength'];
|
135 |
+
}
|
136 |
+
|
137 |
+
private function getSourceMetadata()
|
138 |
+
{
|
139 |
+
if (empty($this->sourceMetadata)) {
|
140 |
+
$this->sourceMetadata = $this->fetchSourceMetadata();
|
141 |
+
}
|
142 |
+
|
143 |
+
return $this->sourceMetadata;
|
144 |
+
}
|
145 |
+
|
146 |
+
private function fetchSourceMetadata()
|
147 |
+
{
|
148 |
+
if ($this->config['source_metadata'] instanceof ResultInterface) {
|
149 |
+
return $this->config['source_metadata'];
|
150 |
+
}
|
151 |
+
|
152 |
+
list($bucket, $key) = explode('/', ltrim($this->source, '/'), 2);
|
153 |
+
$headParams = [
|
154 |
+
'Bucket' => $bucket,
|
155 |
+
'Key' => $key,
|
156 |
+
];
|
157 |
+
if (strpos($key, '?')) {
|
158 |
+
list($key, $query) = explode('?', $key, 2);
|
159 |
+
$headParams['Key'] = $key;
|
160 |
+
$query = Psr7\parse_query($query, false);
|
161 |
+
if (isset($query['versionId'])) {
|
162 |
+
$headParams['VersionId'] = $query['versionId'];
|
163 |
+
}
|
164 |
+
}
|
165 |
+
return $this->client->headObject($headParams);
|
166 |
+
}
|
167 |
+
}
|
includes/aws/Aws/S3/MultipartUploader.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\HashingStream;
|
5 |
+
use Aws\Multipart\AbstractUploader;
|
6 |
+
use Aws\PhpHash;
|
7 |
+
use Aws\ResultInterface;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use Psr\Http\Message\StreamInterface as Stream;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Encapsulates the execution of a multipart upload to S3 or Glacier.
|
13 |
+
*/
|
14 |
+
class MultipartUploader extends AbstractUploader
|
15 |
+
{
|
16 |
+
use MultipartUploadingTrait;
|
17 |
+
|
18 |
+
const PART_MIN_SIZE = 5242880;
|
19 |
+
const PART_MAX_SIZE = 5368709120;
|
20 |
+
const PART_MAX_NUM = 10000;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Creates a multipart upload for an S3 object.
|
24 |
+
*
|
25 |
+
* The valid configuration options are as follows:
|
26 |
+
*
|
27 |
+
* - acl: (string) ACL to set on the object being upload. Objects are
|
28 |
+
* private by default.
|
29 |
+
* - before_complete: (callable) Callback to invoke before the
|
30 |
+
* `CompleteMultipartUpload` operation. The callback should have a
|
31 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
32 |
+
* - before_initiate: (callable) Callback to invoke before the
|
33 |
+
* `CreateMultipartUpload` operation. The callback should have a function
|
34 |
+
* signature like `function (Aws\Command $command) {...}`.
|
35 |
+
* - before_upload: (callable) Callback to invoke before any `UploadPart`
|
36 |
+
* operations. The callback should have a function signature like
|
37 |
+
* `function (Aws\Command $command) {...}`.
|
38 |
+
* - bucket: (string, required) Name of the bucket to which the object is
|
39 |
+
* being uploaded.
|
40 |
+
* - concurrency: (int, default=int(5)) Maximum number of concurrent
|
41 |
+
* `UploadPart` operations allowed during the multipart upload.
|
42 |
+
* - key: (string, required) Key to use for the object being uploaded.
|
43 |
+
* - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
|
44 |
+
* doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
|
45 |
+
* - state: (Aws\Multipart\UploadState) An object that represents the state
|
46 |
+
* of the multipart upload and that is used to resume a previous upload.
|
47 |
+
* When this option is provided, the `bucket`, `key`, and `part_size`
|
48 |
+
* options are ignored.
|
49 |
+
*
|
50 |
+
* @param S3Client $client Client used for the upload.
|
51 |
+
* @param mixed $source Source of the data to upload.
|
52 |
+
* @param array $config Configuration used to perform the upload.
|
53 |
+
*/
|
54 |
+
public function __construct(S3Client $client, $source, array $config = [])
|
55 |
+
{
|
56 |
+
parent::__construct($client, $source, array_change_key_case($config) + [
|
57 |
+
'bucket' => null,
|
58 |
+
'key' => null,
|
59 |
+
]);
|
60 |
+
}
|
61 |
+
|
62 |
+
protected function loadUploadWorkflowInfo()
|
63 |
+
{
|
64 |
+
return [
|
65 |
+
'command' => [
|
66 |
+
'initiate' => 'CreateMultipartUpload',
|
67 |
+
'upload' => 'UploadPart',
|
68 |
+
'complete' => 'CompleteMultipartUpload',
|
69 |
+
],
|
70 |
+
'id' => [
|
71 |
+
'bucket' => 'Bucket',
|
72 |
+
'key' => 'Key',
|
73 |
+
'upload_id' => 'UploadId',
|
74 |
+
],
|
75 |
+
'part_num' => 'PartNumber',
|
76 |
+
];
|
77 |
+
}
|
78 |
+
|
79 |
+
protected function createPart($seekable, $number)
|
80 |
+
{
|
81 |
+
// Initialize the array of part data that will be returned.
|
82 |
+
$data = ['PartNumber' => $number];
|
83 |
+
|
84 |
+
// Read from the source to create the body stream.
|
85 |
+
if ($seekable) {
|
86 |
+
// Case 1: Source is seekable, use lazy stream to defer work.
|
87 |
+
$body = $this->limitPartStream(
|
88 |
+
new Psr7\LazyOpenStream($this->source->getMetadata('uri'), 'r')
|
89 |
+
);
|
90 |
+
} else {
|
91 |
+
// Case 2: Stream is not seekable; must store in temp stream.
|
92 |
+
$source = $this->limitPartStream($this->source);
|
93 |
+
$source = $this->decorateWithHashes($source, $data);
|
94 |
+
$body = Psr7\stream_for();
|
95 |
+
Psr7\copy_to_stream($source, $body);
|
96 |
+
$data['ContentLength'] = $body->getSize();
|
97 |
+
}
|
98 |
+
|
99 |
+
// Do not create a part if the body size is zero.
|
100 |
+
if ($body->getSize() === 0) {
|
101 |
+
return false;
|
102 |
+
}
|
103 |
+
|
104 |
+
$body->seek(0);
|
105 |
+
$data['Body'] = $body;
|
106 |
+
|
107 |
+
return $data;
|
108 |
+
}
|
109 |
+
|
110 |
+
protected function extractETag(ResultInterface $result)
|
111 |
+
{
|
112 |
+
return $result['ETag'];
|
113 |
+
}
|
114 |
+
|
115 |
+
protected function getSourceMimeType()
|
116 |
+
{
|
117 |
+
if ($uri = $this->source->getMetadata('uri')) {
|
118 |
+
return Psr7\mimetype_from_filename($uri)
|
119 |
+
?: 'application/octet-stream';
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
protected function getSourceSize()
|
124 |
+
{
|
125 |
+
return $this->source->getSize();
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Decorates a stream with a sha256 linear hashing stream.
|
130 |
+
*
|
131 |
+
* @param Stream $stream Stream to decorate.
|
132 |
+
* @param array $data Part data to augment with the hash result.
|
133 |
+
*
|
134 |
+
* @return Stream
|
135 |
+
*/
|
136 |
+
private function decorateWithHashes(Stream $stream, array &$data)
|
137 |
+
{
|
138 |
+
// Decorate source with a hashing stream
|
139 |
+
$hash = new PhpHash('sha256');
|
140 |
+
return new HashingStream($stream, $hash, function ($result) use (&$data) {
|
141 |
+
$data['ContentSHA256'] = bin2hex($result);
|
142 |
+
});
|
143 |
+
}
|
144 |
+
}
|
includes/aws/Aws/S3/MultipartUploadingTrait.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Aws\Multipart\UploadState;
|
6 |
+
use Aws\ResultInterface;
|
7 |
+
|
8 |
+
trait MultipartUploadingTrait
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Creates an UploadState object for a multipart upload by querying the
|
12 |
+
* service for the specified upload's information.
|
13 |
+
*
|
14 |
+
* @param S3Client $client S3Client used for the upload.
|
15 |
+
* @param string $bucket Bucket for the multipart upload.
|
16 |
+
* @param string $key Object key for the multipart upload.
|
17 |
+
* @param string $uploadId Upload ID for the multipart upload.
|
18 |
+
*
|
19 |
+
* @return UploadState
|
20 |
+
*/
|
21 |
+
public static function getStateFromService(
|
22 |
+
S3Client $client,
|
23 |
+
$bucket,
|
24 |
+
$key,
|
25 |
+
$uploadId
|
26 |
+
) {
|
27 |
+
$state = new UploadState([
|
28 |
+
'Bucket' => $bucket,
|
29 |
+
'Key' => $key,
|
30 |
+
'UploadId' => $uploadId,
|
31 |
+
]);
|
32 |
+
|
33 |
+
foreach ($client->getPaginator('ListParts', $state->getId()) as $result) {
|
34 |
+
// Get the part size from the first part in the first result.
|
35 |
+
if (!$state->getPartSize()) {
|
36 |
+
$state->setPartSize($result->search('Parts[0].Size'));
|
37 |
+
}
|
38 |
+
// Mark all the parts returned by ListParts as uploaded.
|
39 |
+
foreach ($result['Parts'] as $part) {
|
40 |
+
$state->markPartAsUploaded($part['PartNumber'], [
|
41 |
+
'PartNumber' => $part['PartNumber'],
|
42 |
+
'ETag' => $part['ETag']
|
43 |
+
]);
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
$state->setStatus(UploadState::INITIATED);
|
48 |
+
|
49 |
+
return $state;
|
50 |
+
}
|
51 |
+
|
52 |
+
protected function handleResult(CommandInterface $command, ResultInterface $result)
|
53 |
+
{
|
54 |
+
$this->getState()->markPartAsUploaded($command['PartNumber'], [
|
55 |
+
'PartNumber' => $command['PartNumber'],
|
56 |
+
'ETag' => $this->extractETag($result),
|
57 |
+
]);
|
58 |
+
}
|
59 |
+
|
60 |
+
abstract protected function extractETag(ResultInterface $result);
|
61 |
+
|
62 |
+
protected function getCompleteParams()
|
63 |
+
{
|
64 |
+
return ['MultipartUpload' => [
|
65 |
+
'Parts' => $this->getState()->getUploadedParts()
|
66 |
+
]];
|
67 |
+
}
|
68 |
+
|
69 |
+
protected function determinePartSize()
|
70 |
+
{
|
71 |
+
// Make sure the part size is set.
|
72 |
+
$partSize = $this->getConfig()['part_size'] ?: MultipartUploader::PART_MIN_SIZE;
|
73 |
+
|
74 |
+
// Adjust the part size to be larger for known, x-large uploads.
|
75 |
+
if ($sourceSize = $this->getSourceSize()) {
|
76 |
+
$partSize = (int) max(
|
77 |
+
$partSize,
|
78 |
+
ceil($sourceSize / MultipartUploader::PART_MAX_NUM)
|
79 |
+
);
|
80 |
+
}
|
81 |
+
|
82 |
+
// Ensure that the part size follows the rules: 5 MB <= size <= 5 GB.
|
83 |
+
if ($partSize < MultipartUploader::PART_MIN_SIZE || $partSize > MultipartUploader::PART_MAX_SIZE) {
|
84 |
+
throw new \InvalidArgumentException('The part size must be no less '
|
85 |
+
. 'than 5 MB and no greater than 5 GB.');
|
86 |
+
}
|
87 |
+
|
88 |
+
return $partSize;
|
89 |
+
}
|
90 |
+
|
91 |
+
protected function getInitiateParams()
|
92 |
+
{
|
93 |
+
$params = [];
|
94 |
+
|
95 |
+
if (isset($this->getConfig()['acl'])) {
|
96 |
+
$params['ACL'] = $this->getConfig()['acl'];
|
97 |
+
}
|
98 |
+
|
99 |
+
// Set the content type
|
100 |
+
if ($type = $this->getSourceMimeType()) {
|
101 |
+
$params['ContentType'] = $type;
|
102 |
+
}
|
103 |
+
|
104 |
+
return $params;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @return UploadState
|
109 |
+
*/
|
110 |
+
abstract protected function getState();
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @return array
|
114 |
+
*/
|
115 |
+
abstract protected function getConfig();
|
116 |
+
|
117 |
+
/**
|
118 |
+
* @return int
|
119 |
+
*/
|
120 |
+
abstract protected function getSourceSize();
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @return string|null
|
124 |
+
*/
|
125 |
+
abstract protected function getSourceMimeType();
|
126 |
+
}
|
includes/aws/Aws/S3/PermanentRedirectMiddleware.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Aws\ResultInterface;
|
6 |
+
use Aws\S3\Exception\PermanentRedirectException;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Throws a PermanentRedirectException exception when a 301 redirect is
|
11 |
+
* encountered.
|
12 |
+
*
|
13 |
+
* @internal
|
14 |
+
*/
|
15 |
+
class PermanentRedirectMiddleware
|
16 |
+
{
|
17 |
+
/** @var callable */
|
18 |
+
private $nextHandler;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Create a middleware wrapper function.
|
22 |
+
*
|
23 |
+
* @return callable
|
24 |
+
*/
|
25 |
+
public static function wrap()
|
26 |
+
{
|
27 |
+
return function (callable $handler) {
|
28 |
+
return new self($handler);
|
29 |
+
};
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param callable $nextHandler Next handler to invoke.
|
34 |
+
*/
|
35 |
+
public function __construct(callable $nextHandler)
|
36 |
+
{
|
37 |
+
$this->nextHandler = $nextHandler;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function __invoke(CommandInterface $command, RequestInterface $request = null)
|
41 |
+
{
|
42 |
+
$next = $this->nextHandler;
|
43 |
+
return $next($command, $request)->then(
|
44 |
+
function (ResultInterface $result) use ($command) {
|
45 |
+
$status = isset($result['@metadata']['statusCode'])
|
46 |
+
? $result['@metadata']['statusCode']
|
47 |
+
: null;
|
48 |
+
if ($status == 301) {
|
49 |
+
throw new PermanentRedirectException(
|
50 |
+
'Encountered a permanent redirect while requesting '
|
51 |
+
. $result->search('"@metadata".effectiveUri') . '. '
|
52 |
+
. 'Are you sure you are using the correct region for '
|
53 |
+
. 'this bucket?',
|
54 |
+
$command,
|
55 |
+
['result' => $result]
|
56 |
+
);
|
57 |
+
}
|
58 |
+
return $result;
|
59 |
+
}
|
60 |
+
);
|
61 |
+
}
|
62 |
+
}
|
includes/aws/Aws/S3/PostObject.php
ADDED
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Credentials\CredentialsInterface;
|
5 |
+
use GuzzleHttp\Psr7\Uri;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Encapsulates the logic for getting the data for an S3 object POST upload form
|
9 |
+
*
|
10 |
+
* @link http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html
|
11 |
+
*/
|
12 |
+
class PostObject
|
13 |
+
{
|
14 |
+
private $client;
|
15 |
+
private $bucket;
|
16 |
+
private $formAttributes;
|
17 |
+
private $formInputs;
|
18 |
+
private $jsonPolicy;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Constructs the PostObject.
|
22 |
+
*
|
23 |
+
* @param S3Client $client Client used with the POST object
|
24 |
+
* @param string $bucket Bucket to use
|
25 |
+
* @param array $formInputs Associative array of form input fields.
|
26 |
+
* @param string|array $jsonPolicy JSON encoded POST policy document. The
|
27 |
+
* policy will be base64 encoded and applied
|
28 |
+
* to the form on your behalf.
|
29 |
+
*/
|
30 |
+
public function __construct(
|
31 |
+
S3Client $client,
|
32 |
+
$bucket,
|
33 |
+
array $formInputs,
|
34 |
+
$jsonPolicy
|
35 |
+
) {
|
36 |
+
$this->client = $client;
|
37 |
+
$this->bucket = $bucket;
|
38 |
+
|
39 |
+
if (is_array($jsonPolicy)) {
|
40 |
+
$jsonPolicy = json_encode($jsonPolicy);
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->jsonPolicy = $jsonPolicy;
|
44 |
+
$this->formAttributes = [
|
45 |
+
'action' => $this->generateUri(),
|
46 |
+
'method' => 'POST',
|
47 |
+
'enctype' => 'multipart/form-data'
|
48 |
+
];
|
49 |
+
|
50 |
+
$this->formInputs = $formInputs + ['key' => '${filename}'];
|
51 |
+
$credentials = $client->getCredentials()->wait();
|
52 |
+
$this->formInputs += $this->getPolicyAndSignature($credentials);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Gets the S3 client.
|
57 |
+
*
|
58 |
+
* @return S3Client
|
59 |
+
*/
|
60 |
+
public function getClient()
|
61 |
+
{
|
62 |
+
return $this->client;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Gets the bucket name.
|
67 |
+
*
|
68 |
+
* @return string
|
69 |
+
*/
|
70 |
+
public function getBucket()
|
71 |
+
{
|
72 |
+
return $this->bucket;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Gets the form attributes as an array.
|
77 |
+
*
|
78 |
+
* @return array
|
79 |
+
*/
|
80 |
+
public function getFormAttributes()
|
81 |
+
{
|
82 |
+
return $this->formAttributes;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set a form attribute.
|
87 |
+
*
|
88 |
+
* @param string $attribute Form attribute to set.
|
89 |
+
* @param string $value Value to set.
|
90 |
+
*/
|
91 |
+
public function setFormAttribute($attribute, $value)
|
92 |
+
{
|
93 |
+
$this->formAttributes[$attribute] = $value;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Gets the form inputs as an array.
|
98 |
+
*
|
99 |
+
* @return array
|
100 |
+
*/
|
101 |
+
public function getFormInputs()
|
102 |
+
{
|
103 |
+
return $this->formInputs;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Set a form input.
|
108 |
+
*
|
109 |
+
* @param string $field Field name to set
|
110 |
+
* @param string $value Value to set.
|
111 |
+
*/
|
112 |
+
public function setFormInput($field, $value)
|
113 |
+
{
|
114 |
+
$this->formInputs[$field] = $value;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Gets the raw JSON policy.
|
119 |
+
*
|
120 |
+
* @return string
|
121 |
+
*/
|
122 |
+
public function getJsonPolicy()
|
123 |
+
{
|
124 |
+
return $this->jsonPolicy;
|
125 |
+
}
|
126 |
+
|
127 |
+
private function generateUri()
|
128 |
+
{
|
129 |
+
$uri = new Uri($this->client->getEndpoint());
|
130 |
+
|
131 |
+
if ($uri->getScheme() === 'https'
|
132 |
+
&& strpos($this->bucket, '.') !== false
|
133 |
+
) {
|
134 |
+
// Use path-style URLs
|
135 |
+
$uri = $uri->withPath($this->bucket);
|
136 |
+
} else {
|
137 |
+
// Use virtual-style URLs
|
138 |
+
$uri = $uri->withHost($this->bucket . '.' . $uri->getHost());
|
139 |
+
}
|
140 |
+
|
141 |
+
return (string) $uri;
|
142 |
+
}
|
143 |
+
|
144 |
+
protected function getPolicyAndSignature(CredentialsInterface $creds)
|
145 |
+
{
|
146 |
+
$jsonPolicy64 = base64_encode($this->jsonPolicy);
|
147 |
+
|
148 |
+
return [
|
149 |
+
'AWSAccessKeyId' => $creds->getAccessKeyId(),
|
150 |
+
'policy' => $jsonPolicy64,
|
151 |
+
'signature' => base64_encode(hash_hmac(
|
152 |
+
'sha1',
|
153 |
+
$jsonPolicy64,
|
154 |
+
$creds->getSecretKey(),
|
155 |
+
true
|
156 |
+
))
|
157 |
+
];
|
158 |
+
}
|
159 |
+
}
|
includes/aws/Aws/S3/PutObjectUrlMiddleware.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Aws\ResultInterface;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Injects ObjectURL into the result of the PutObject operation.
|
10 |
+
*
|
11 |
+
* @internal
|
12 |
+
*/
|
13 |
+
class PutObjectUrlMiddleware
|
14 |
+
{
|
15 |
+
/** @var callable */
|
16 |
+
private $nextHandler;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Create a middleware wrapper function.
|
20 |
+
*
|
21 |
+
* @return callable
|
22 |
+
*/
|
23 |
+
public static function wrap()
|
24 |
+
{
|
25 |
+
return function (callable $handler) {
|
26 |
+
return new self($handler);
|
27 |
+
};
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param callable $nextHandler Next handler to invoke.
|
32 |
+
*/
|
33 |
+
public function __construct(callable $nextHandler)
|
34 |
+
{
|
35 |
+
$this->nextHandler = $nextHandler;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function __invoke(CommandInterface $command, RequestInterface $request = null)
|
39 |
+
{
|
40 |
+
$next = $this->nextHandler;
|
41 |
+
return $next($command, $request)->then(
|
42 |
+
function (ResultInterface $result) use ($command) {
|
43 |
+
$name = $command->getName();
|
44 |
+
switch ($name) {
|
45 |
+
case 'PutObject':
|
46 |
+
case 'CopyObject':
|
47 |
+
$result['ObjectURL'] = $result['@metadata']['effectiveUri'];
|
48 |
+
break;
|
49 |
+
case 'CompleteMultipartUpload':
|
50 |
+
$result['ObjectURL'] = $result['Location'];
|
51 |
+
break;
|
52 |
+
}
|
53 |
+
return $result;
|
54 |
+
}
|
55 |
+
);
|
56 |
+
}
|
57 |
+
}
|
includes/aws/Aws/S3/RetryableMalformedResponseParser.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\AbstractParser;
|
5 |
+
use Aws\Api\Parser\Exception\ParserException;
|
6 |
+
use Aws\CommandInterface;
|
7 |
+
use Aws\Exception\AwsException;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Converts malformed responses to a retryable error type.
|
12 |
+
*
|
13 |
+
* @internal
|
14 |
+
*/
|
15 |
+
class RetryableMalformedResponseParser extends AbstractParser
|
16 |
+
{
|
17 |
+
/** @var callable */
|
18 |
+
private $parser;
|
19 |
+
/** @var string */
|
20 |
+
private $exceptionClass;
|
21 |
+
|
22 |
+
public function __construct(
|
23 |
+
callable $parser,
|
24 |
+
$exceptionClass = AwsException::class
|
25 |
+
) {
|
26 |
+
$this->parser = $parser;
|
27 |
+
$this->exceptionClass = $exceptionClass;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function __invoke(
|
31 |
+
CommandInterface $command,
|
32 |
+
ResponseInterface $response
|
33 |
+
) {
|
34 |
+
$fn = $this->parser;
|
35 |
+
|
36 |
+
try {
|
37 |
+
return $fn($command, $response);
|
38 |
+
} catch (ParserException $e) {
|
39 |
+
throw new $this->exceptionClass(
|
40 |
+
"Error parsing response for {$command->getName()}:"
|
41 |
+
. " AWS parsing error: {$e->getMessage()}",
|
42 |
+
$command,
|
43 |
+
['connection_error' => true, 'exception' => $e],
|
44 |
+
$e
|
45 |
+
);
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
includes/aws/Aws/S3/S3Client.php
ADDED
@@ -0,0 +1,855 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\Api\ApiProvider;
|
5 |
+
use Aws\Api\DocModel;
|
6 |
+
use Aws\Api\Service;
|
7 |
+
use Aws\AwsClient;
|
8 |
+
use Aws\ClientResolver;
|
9 |
+
use Aws\Command;
|
10 |
+
use Aws\Exception\AwsException;
|
11 |
+
use Aws\HandlerList;
|
12 |
+
use Aws\Middleware;
|
13 |
+
use Aws\RetryMiddleware;
|
14 |
+
use Aws\S3\Exception\S3Exception;
|
15 |
+
use Aws\ResultInterface;
|
16 |
+
use Aws\CommandInterface;
|
17 |
+
use GuzzleHttp\Exception\RequestException;
|
18 |
+
use GuzzleHttp\Promise;
|
19 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
20 |
+
use GuzzleHttp\Psr7;
|
21 |
+
use Psr\Http\Message\RequestInterface;
|
22 |
+
use Psr\Http\Message\StreamInterface;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
|
26 |
+
*
|
27 |
+
* @method \Aws\Result abortMultipartUpload(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise abortMultipartUploadAsync(array $args = [])
|
29 |
+
* @method \Aws\Result completeMultipartUpload(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise completeMultipartUploadAsync(array $args = [])
|
31 |
+
* @method \Aws\Result copyObject(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise copyObjectAsync(array $args = [])
|
33 |
+
* @method \Aws\Result createBucket(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise createBucketAsync(array $args = [])
|
35 |
+
* @method \Aws\Result createMultipartUpload(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise createMultipartUploadAsync(array $args = [])
|
37 |
+
* @method \Aws\Result deleteBucket(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketAsync(array $args = [])
|
39 |
+
* @method \Aws\Result deleteBucketCors(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketCorsAsync(array $args = [])
|
41 |
+
* @method \Aws\Result deleteBucketLifecycle(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketLifecycleAsync(array $args = [])
|
43 |
+
* @method \Aws\Result deleteBucketPolicy(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketPolicyAsync(array $args = [])
|
45 |
+
* @method \Aws\Result deleteBucketReplication(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketReplicationAsync(array $args = [])
|
47 |
+
* @method \Aws\Result deleteBucketTagging(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketTaggingAsync(array $args = [])
|
49 |
+
* @method \Aws\Result deleteBucketWebsite(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise deleteBucketWebsiteAsync(array $args = [])
|
51 |
+
* @method \Aws\Result deleteObject(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise deleteObjectAsync(array $args = [])
|
53 |
+
* @method \Aws\Result deleteObjects(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise deleteObjectsAsync(array $args = [])
|
55 |
+
* @method \Aws\Result getBucketAcl(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise getBucketAclAsync(array $args = [])
|
57 |
+
* @method \Aws\Result getBucketCors(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise getBucketCorsAsync(array $args = [])
|
59 |
+
* @method \Aws\Result getBucketLifecycle(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise getBucketLifecycleAsync(array $args = [])
|
61 |
+
* @method \Aws\Result getBucketLifecycleConfiguration(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise getBucketLifecycleConfigurationAsync(array $args = [])
|
63 |
+
* @method \Aws\Result getBucketLocation(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise getBucketLocationAsync(array $args = [])
|
65 |
+
* @method \Aws\Result getBucketLogging(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise getBucketLoggingAsync(array $args = [])
|
67 |
+
* @method \Aws\Result getBucketNotification(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise getBucketNotificationAsync(array $args = [])
|
69 |
+
* @method \Aws\Result getBucketNotificationConfiguration(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise getBucketNotificationConfigurationAsync(array $args = [])
|
71 |
+
* @method \Aws\Result getBucketPolicy(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise getBucketPolicyAsync(array $args = [])
|
73 |
+
* @method \Aws\Result getBucketReplication(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise getBucketReplicationAsync(array $args = [])
|
75 |
+
* @method \Aws\Result getBucketRequestPayment(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise getBucketRequestPaymentAsync(array $args = [])
|
77 |
+
* @method \Aws\Result getBucketTagging(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise getBucketTaggingAsync(array $args = [])
|
79 |
+
* @method \Aws\Result getBucketVersioning(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise getBucketVersioningAsync(array $args = [])
|
81 |
+
* @method \Aws\Result getBucketWebsite(array $args = [])
|
82 |
+
* @method \GuzzleHttp\Promise\Promise getBucketWebsiteAsync(array $args = [])
|
83 |
+
* @method \Aws\Result getObject(array $args = [])
|
84 |
+
* @method \GuzzleHttp\Promise\Promise getObjectAsync(array $args = [])
|
85 |
+
* @method \Aws\Result getObjectAcl(array $args = [])
|
86 |
+
* @method \GuzzleHttp\Promise\Promise getObjectAclAsync(array $args = [])
|
87 |
+
* @method \Aws\Result getObjectTorrent(array $args = [])
|
88 |
+
* @method \GuzzleHttp\Promise\Promise getObjectTorrentAsync(array $args = [])
|
89 |
+
* @method \Aws\Result headBucket(array $args = [])
|
90 |
+
* @method \GuzzleHttp\Promise\Promise headBucketAsync(array $args = [])
|
91 |
+
* @method \Aws\Result headObject(array $args = [])
|
92 |
+
* @method \GuzzleHttp\Promise\Promise headObjectAsync(array $args = [])
|
93 |
+
* @method \Aws\Result listBuckets(array $args = [])
|
94 |
+
* @method \GuzzleHttp\Promise\Promise listBucketsAsync(array $args = [])
|
95 |
+
* @method \Aws\Result listMultipartUploads(array $args = [])
|
96 |
+
* @method \GuzzleHttp\Promise\Promise listMultipartUploadsAsync(array $args = [])
|
97 |
+
* @method \Aws\Result listObjectVersions(array $args = [])
|
98 |
+
* @method \GuzzleHttp\Promise\Promise listObjectVersionsAsync(array $args = [])
|
99 |
+
* @method \Aws\Result listObjects(array $args = [])
|
100 |
+
* @method \GuzzleHttp\Promise\Promise listObjectsAsync(array $args = [])
|
101 |
+
* @method \Aws\Result listParts(array $args = [])
|
102 |
+
* @method \GuzzleHttp\Promise\Promise listPartsAsync(array $args = [])
|
103 |
+
* @method \Aws\Result putBucketAcl(array $args = [])
|
104 |
+
* @method \GuzzleHttp\Promise\Promise putBucketAclAsync(array $args = [])
|
105 |
+
* @method \Aws\Result putBucketCors(array $args = [])
|
106 |
+
* @method \GuzzleHttp\Promise\Promise putBucketCorsAsync(array $args = [])
|
107 |
+
* @method \Aws\Result putBucketLifecycle(array $args = [])
|
108 |
+
* @method \GuzzleHttp\Promise\Promise putBucketLifecycleAsync(array $args = [])
|
109 |
+
* @method \Aws\Result putBucketLifecycleConfiguration(array $args = [])
|
110 |
+
* @method \GuzzleHttp\Promise\Promise putBucketLifecycleConfigurationAsync(array $args = [])
|
111 |
+
* @method \Aws\Result putBucketLogging(array $args = [])
|
112 |
+
* @method \GuzzleHttp\Promise\Promise putBucketLoggingAsync(array $args = [])
|
113 |
+
* @method \Aws\Result putBucketNotification(array $args = [])
|
114 |
+
* @method \GuzzleHttp\Promise\Promise putBucketNotificationAsync(array $args = [])
|
115 |
+
* @method \Aws\Result putBucketNotificationConfiguration(array $args = [])
|
116 |
+
* @method \GuzzleHttp\Promise\Promise putBucketNotificationConfigurationAsync(array $args = [])
|
117 |
+
* @method \Aws\Result putBucketPolicy(array $args = [])
|
118 |
+
* @method \GuzzleHttp\Promise\Promise putBucketPolicyAsync(array $args = [])
|
119 |
+
* @method \Aws\Result putBucketReplication(array $args = [])
|
120 |
+
* @method \GuzzleHttp\Promise\Promise putBucketReplicationAsync(array $args = [])
|
121 |
+
* @method \Aws\Result putBucketRequestPayment(array $args = [])
|
122 |
+
* @method \GuzzleHttp\Promise\Promise putBucketRequestPaymentAsync(array $args = [])
|
123 |
+
* @method \Aws\Result putBucketTagging(array $args = [])
|
124 |
+
* @method \GuzzleHttp\Promise\Promise putBucketTaggingAsync(array $args = [])
|
125 |
+
* @method \Aws\Result putBucketVersioning(array $args = [])
|
126 |
+
* @method \GuzzleHttp\Promise\Promise putBucketVersioningAsync(array $args = [])
|
127 |
+
* @method \Aws\Result putBucketWebsite(array $args = [])
|
128 |
+
* @method \GuzzleHttp\Promise\Promise putBucketWebsiteAsync(array $args = [])
|
129 |
+
* @method \Aws\Result putObject(array $args = [])
|
130 |
+
* @method \GuzzleHttp\Promise\Promise putObjectAsync(array $args = [])
|
131 |
+
* @method \Aws\Result putObjectAcl(array $args = [])
|
132 |
+
* @method \GuzzleHttp\Promise\Promise putObjectAclAsync(array $args = [])
|
133 |
+
* @method \Aws\Result restoreObject(array $args = [])
|
134 |
+
* @method \GuzzleHttp\Promise\Promise restoreObjectAsync(array $args = [])
|
135 |
+
* @method \Aws\Result uploadPart(array $args = [])
|
136 |
+
* @method \GuzzleHttp\Promise\Promise uploadPartAsync(array $args = [])
|
137 |
+
* @method \Aws\Result uploadPartCopy(array $args = [])
|
138 |
+
* @method \GuzzleHttp\Promise\Promise uploadPartCopyAsync(array $args = [])
|
139 |
+
*/
|
140 |
+
class S3Client extends AwsClient
|
141 |
+
{
|
142 |
+
public static function getArguments()
|
143 |
+
{
|
144 |
+
$args = parent::getArguments();
|
145 |
+
$args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
|
146 |
+
$args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
|
147 |
+
|
148 |
+
return $args + [
|
149 |
+
'bucket_endpoint' => [
|
150 |
+
'type' => 'config',
|
151 |
+
'valid' => ['bool'],
|
152 |
+
'doc' => 'Set to true to send requests to a hardcoded '
|
153 |
+
. 'bucket endpoint rather than create an endpoint as a '
|
154 |
+
. 'result of injecting the bucket into the URL. This '
|
155 |
+
. 'option is useful for interacting with CNAME endpoints.',
|
156 |
+
],
|
157 |
+
];
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* {@inheritdoc}
|
162 |
+
*
|
163 |
+
* In addition to the options available to
|
164 |
+
* {@see Aws\AwsClient::__construct}, S3Client accepts the following
|
165 |
+
* options:
|
166 |
+
*
|
167 |
+
* - bucket_endpoint: (bool) Set to true to send requests to a
|
168 |
+
* hardcoded bucket endpoint rather than create an endpoint as a result
|
169 |
+
* of injecting the bucket into the URL. This option is useful for
|
170 |
+
* interacting with CNAME endpoints.
|
171 |
+
* - calculate_md5: (bool) Set to false to disable calculating an MD5
|
172 |
+
* for all Amazon S3 signed uploads.
|
173 |
+
*
|
174 |
+
* @param array $args
|
175 |
+
*/
|
176 |
+
public function __construct(array $args)
|
177 |
+
{
|
178 |
+
parent::__construct($args);
|
179 |
+
$stack = $this->getHandlerList();
|
180 |
+
$stack->appendInit(SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
|
181 |
+
$stack->appendBuild(ApplyChecksumMiddleware::wrap(), 's3.checksum');
|
182 |
+
$stack->appendBuild(
|
183 |
+
Middleware::contentType(['PutObject', 'UploadPart']),
|
184 |
+
's3.content_type'
|
185 |
+
);
|
186 |
+
|
187 |
+
// Use the bucket style middleware when using a "bucket_endpoint" (for cnames)
|
188 |
+
if ($this->getConfig('bucket_endpoint')) {
|
189 |
+
$stack->appendBuild(BucketEndpointMiddleware::wrap(), 's3.bucket_endpoint');
|
190 |
+
}
|
191 |
+
|
192 |
+
$stack->appendSign(PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
|
193 |
+
$stack->appendSign(PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
|
194 |
+
$stack->appendInit(Middleware::sourceFile($this->getApi()), 's3.source_file');
|
195 |
+
$stack->appendInit($this->getSaveAsParameter(), 's3.save_as');
|
196 |
+
$stack->appendInit($this->getLocationConstraintMiddleware(), 's3.location');
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Determine if a string is a valid name for a DNS compatible Amazon S3
|
201 |
+
* bucket.
|
202 |
+
*
|
203 |
+
* DNS compatible bucket names can be used as a subdomain in a URL (e.g.,
|
204 |
+
* "<bucket>.s3.amazonaws.com").
|
205 |
+
*
|
206 |
+
* @param string $bucket Bucket name to check.
|
207 |
+
*
|
208 |
+
* @return bool
|
209 |
+
*/
|
210 |
+
public static function isBucketDnsCompatible($bucket)
|
211 |
+
{
|
212 |
+
$bucketLen = strlen($bucket);
|
213 |
+
|
214 |
+
return ($bucketLen >= 3 && $bucketLen <= 63) &&
|
215 |
+
// Cannot look like an IP address
|
216 |
+
!filter_var($bucket, FILTER_VALIDATE_IP) &&
|
217 |
+
preg_match('/^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$/', $bucket);
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Create a pre-signed URL for the given S3 command object.
|
222 |
+
*
|
223 |
+
* @param CommandInterface $command Command to create a pre-signed
|
224 |
+
* URL for.
|
225 |
+
* @param int|string|\DateTime $expires The time at which the URL should
|
226 |
+
* expire. This can be a Unix
|
227 |
+
* timestamp, a PHP DateTime object,
|
228 |
+
* or a string that can be evaluated
|
229 |
+
* by strtotime().
|
230 |
+
*
|
231 |
+
* @return RequestInterface
|
232 |
+
*/
|
233 |
+
public function createPresignedRequest(CommandInterface $command, $expires)
|
234 |
+
{
|
235 |
+
/** @var \Aws\Signature\SignatureInterface $signer */
|
236 |
+
$signer = call_user_func(
|
237 |
+
$this->getSignatureProvider(),
|
238 |
+
$this->getConfig('signature_version'),
|
239 |
+
$this->getApi()->getSigningName(),
|
240 |
+
$this->getRegion()
|
241 |
+
);
|
242 |
+
|
243 |
+
return $signer->presign(
|
244 |
+
\Aws\serialize($command),
|
245 |
+
$this->getCredentials()->wait(),
|
246 |
+
$expires
|
247 |
+
);
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Returns the URL to an object identified by its bucket and key.
|
252 |
+
*
|
253 |
+
* The URL returned by this method is not signed nor does it ensure the the
|
254 |
+
* bucket and key given to the method exist. If you need a signed URL, then
|
255 |
+
* use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
|
256 |
+
* the URI of the signed request.
|
257 |
+
*
|
258 |
+
* @param string $bucket The name of the bucket where the object is located
|
259 |
+
* @param string $key The key of the object
|
260 |
+
*
|
261 |
+
* @return string The URL to the object
|
262 |
+
*/
|
263 |
+
public function getObjectUrl($bucket, $key)
|
264 |
+
{
|
265 |
+
$command = $this->getCommand('GetObject', [
|
266 |
+
'Bucket' => $bucket,
|
267 |
+
'Key' => $key
|
268 |
+
]);
|
269 |
+
|
270 |
+
return (string) \Aws\serialize($command)->getUri();
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Determines whether or not a bucket exists by name.
|
275 |
+
*
|
276 |
+
* @param string $bucket The name of the bucket
|
277 |
+
*
|
278 |
+
* @return bool
|
279 |
+
*/
|
280 |
+
public function doesBucketExist($bucket)
|
281 |
+
{
|
282 |
+
return $this->checkExistenceWithCommand(
|
283 |
+
$this->getCommand('HeadBucket', ['Bucket' => $bucket])
|
284 |
+
);
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Determines whether or not an object exists by name.
|
289 |
+
*
|
290 |
+
* @param string $bucket The name of the bucket
|
291 |
+
* @param string $key The key of the object
|
292 |
+
* @param array $options Additional options available in the HeadObject
|
293 |
+
* operation (e.g., VersionId).
|
294 |
+
*
|
295 |
+
* @return bool
|
296 |
+
*/
|
297 |
+
public function doesObjectExist($bucket, $key, array $options = [])
|
298 |
+
{
|
299 |
+
return $this->checkExistenceWithCommand(
|
300 |
+
$this->getCommand('HeadObject', [
|
301 |
+
'Bucket' => $bucket,
|
302 |
+
'Key' => $key
|
303 |
+
] + $options)
|
304 |
+
);
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Raw URL encode a key and allow for '/' characters
|
309 |
+
*
|
310 |
+
* @param string $key Key to encode
|
311 |
+
*
|
312 |
+
* @return string Returns the encoded key
|
313 |
+
*/
|
314 |
+
public static function encodeKey($key)
|
315 |
+
{
|
316 |
+
return str_replace('%2F', '/', rawurlencode($key));
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Register the Amazon S3 stream wrapper with this client instance.
|
321 |
+
*/
|
322 |
+
public function registerStreamWrapper()
|
323 |
+
{
|
324 |
+
StreamWrapper::register($this);
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Deletes objects from Amazon S3 that match the result of a ListObjects
|
329 |
+
* operation. For example, this allows you to do things like delete all
|
330 |
+
* objects that match a specific key prefix.
|
331 |
+
*
|
332 |
+
* @param string $bucket Bucket that contains the object keys
|
333 |
+
* @param string $prefix Optionally delete only objects under this key prefix
|
334 |
+
* @param string $regex Delete only objects that match this regex
|
335 |
+
* @param array $options Aws\S3\BatchDelete options array.
|
336 |
+
*
|
337 |
+
* @see Aws\S3\S3Client::listObjects
|
338 |
+
* @throws \RuntimeException if no prefix and no regex is given
|
339 |
+
*/
|
340 |
+
public function deleteMatchingObjects(
|
341 |
+
$bucket,
|
342 |
+
$prefix = '',
|
343 |
+
$regex = '',
|
344 |
+
array $options = []
|
345 |
+
) {
|
346 |
+
if (!$prefix && !$regex) {
|
347 |
+
throw new \RuntimeException('A prefix or regex is required.');
|
348 |
+
}
|
349 |
+
|
350 |
+
$params = ['Bucket' => $bucket, 'Prefix' => $prefix];
|
351 |
+
$iter = $this->getIterator('ListObjects', $params);
|
352 |
+
|
353 |
+
if ($regex) {
|
354 |
+
$iter = \Aws\filter($iter, function ($c) use ($regex) {
|
355 |
+
return preg_match($regex, $c['Key']);
|
356 |
+
});
|
357 |
+
}
|
358 |
+
|
359 |
+
BatchDelete::fromIterator($this, $bucket, $iter, $options)->delete();
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Upload a file, stream, or string to a bucket.
|
364 |
+
*
|
365 |
+
* If the upload size exceeds the specified threshold, the upload will be
|
366 |
+
* performed using concurrent multipart uploads.
|
367 |
+
*
|
368 |
+
* The options array accepts the following options:
|
369 |
+
*
|
370 |
+
* - before_upload: (callable) Callback to invoke before any upload
|
371 |
+
* operations during the upload process. The callback should have a
|
372 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
373 |
+
* - concurrency: (int, default=int(3)) Maximum number of concurrent
|
374 |
+
* `UploadPart` operations allowed during a multipart upload.
|
375 |
+
* - mup_threshold: (int, default=int(16777216)) The size, in bytes, allowed
|
376 |
+
* before the upload must be sent via a multipart upload. Default: 16 MB.
|
377 |
+
* - params: (array, default=array([])) Custom parameters to use with the
|
378 |
+
* upload. For single uploads, they must correspond to those used for the
|
379 |
+
* `PutObject` operation. For multipart uploads, they correspond to the
|
380 |
+
* parameters of the `CreateMultipartUpload` operation.
|
381 |
+
* - part_size: (int) Part size to use when doing a multipart upload.
|
382 |
+
*
|
383 |
+
* @param string $bucket Bucket to upload the object.
|
384 |
+
* @param string $key Key of the object.
|
385 |
+
* @param mixed $body Object data to upload. Can be a
|
386 |
+
* StreamInterface, PHP stream resource, or a
|
387 |
+
* string of data to upload.
|
388 |
+
* @param string $acl ACL to apply to the object (default: private).
|
389 |
+
* @param array $options Options used to configure the upload process.
|
390 |
+
*
|
391 |
+
* @see Aws\S3\MultipartUploader for more info about multipart uploads.
|
392 |
+
* @return ResultInterface Returns the result of the upload.
|
393 |
+
*/
|
394 |
+
public function upload(
|
395 |
+
$bucket,
|
396 |
+
$key,
|
397 |
+
$body,
|
398 |
+
$acl = 'private',
|
399 |
+
array $options = []
|
400 |
+
) {
|
401 |
+
return $this
|
402 |
+
->uploadAsync($bucket, $key, $body, $acl, $options)
|
403 |
+
->wait();
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Upload a file, stream, or string to a bucket asynchronously.
|
408 |
+
*
|
409 |
+
* @param string $bucket Bucket to upload the object.
|
410 |
+
* @param string $key Key of the object.
|
411 |
+
* @param mixed $body Object data to upload. Can be a
|
412 |
+
* StreamInterface, PHP stream resource, or a
|
413 |
+
* string of data to upload.
|
414 |
+
* @param string $acl ACL to apply to the object (default: private).
|
415 |
+
* @param array $options Options used to configure the upload process.
|
416 |
+
*
|
417 |
+
* @see self::upload
|
418 |
+
* @return PromiseInterface Returns a promise that will be fulfilled
|
419 |
+
* with the result of the upload.
|
420 |
+
*/
|
421 |
+
public function uploadAsync(
|
422 |
+
$bucket,
|
423 |
+
$key,
|
424 |
+
$body,
|
425 |
+
$acl = 'private',
|
426 |
+
array $options = []
|
427 |
+
) {
|
428 |
+
// Prepare the options.
|
429 |
+
static $defaults = [
|
430 |
+
'before_upload' => null,
|
431 |
+
'concurrency' => 3,
|
432 |
+
'mup_threshold' => 16777216,
|
433 |
+
'params' => [],
|
434 |
+
'part_size' => null,
|
435 |
+
];
|
436 |
+
$options = array_intersect_key($options + $defaults, $defaults);
|
437 |
+
|
438 |
+
// Perform the required operations to upload the S3 Object.
|
439 |
+
$body = Psr7\stream_for($body);
|
440 |
+
if ($this->requiresMultipart($body, $options['mup_threshold'])) {
|
441 |
+
// Perform a multipart upload.
|
442 |
+
$options['before_initiate'] = function ($command) use ($options) {
|
443 |
+
foreach ($options['params'] as $k => $v) {
|
444 |
+
$command[$k] = $v;
|
445 |
+
}
|
446 |
+
};
|
447 |
+
return (new MultipartUploader($this, $body, [
|
448 |
+
'bucket' => $bucket,
|
449 |
+
'key' => $key,
|
450 |
+
'acl' => $acl
|
451 |
+
] + $options))->promise();
|
452 |
+
} else {
|
453 |
+
// Perform a regular PutObject operation.
|
454 |
+
$command = $this->getCommand('PutObject', [
|
455 |
+
'Bucket' => $bucket,
|
456 |
+
'Key' => $key,
|
457 |
+
'Body' => $body,
|
458 |
+
'ACL' => $acl,
|
459 |
+
] + $options['params']);
|
460 |
+
if (is_callable($options['before_upload'])) {
|
461 |
+
$options['before_upload']($command);
|
462 |
+
}
|
463 |
+
return $this->executeAsync($command);
|
464 |
+
}
|
465 |
+
}
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Copy an object of any size to a different location.
|
469 |
+
*
|
470 |
+
* If the upload size exceeds the maximum allowable size for direct S3
|
471 |
+
* copying, a multipart copy will be used.
|
472 |
+
*
|
473 |
+
* The options array accepts the following options:
|
474 |
+
*
|
475 |
+
* - before_upload: (callable) Callback to invoke before any upload
|
476 |
+
* operations during the upload process. The callback should have a
|
477 |
+
* function signature like `function (Aws\Command $command) {...}`.
|
478 |
+
* - concurrency: (int, default=int(5)) Maximum number of concurrent
|
479 |
+
* `UploadPart` operations allowed during a multipart upload.
|
480 |
+
* - params: (array, default=array([])) Custom parameters to use with the
|
481 |
+
* upload. For single uploads, they must correspond to those used for the
|
482 |
+
* `CopyObject` operation. For multipart uploads, they correspond to the
|
483 |
+
* parameters of the `CreateMultipartUpload` operation.
|
484 |
+
* - part_size: (int) Part size to use when doing a multipart upload.
|
485 |
+
*
|
486 |
+
* @param string $fromBucket Bucket where the copy source resides.
|
487 |
+
* @param string $fromKey Key of the copy source.
|
488 |
+
* @param string $destBucket Bucket to which to copy the object.
|
489 |
+
* @param string $destKey Key to which to copy the object.
|
490 |
+
* @param string $acl ACL to apply to the copy (default: private).
|
491 |
+
* @param array $options Options used to configure the upload process.
|
492 |
+
*
|
493 |
+
* @see Aws\S3\MultipartCopy for more info about multipart uploads.
|
494 |
+
* @return ResultInterface Returns the result of the copy.
|
495 |
+
*/
|
496 |
+
public function copy(
|
497 |
+
$fromBucket,
|
498 |
+
$fromKey,
|
499 |
+
$destBucket,
|
500 |
+
$destKey,
|
501 |
+
$acl = 'private',
|
502 |
+
array $options = []
|
503 |
+
) {
|
504 |
+
return $this
|
505 |
+
->copyAsync($fromBucket, $fromKey, $destBucket, $destKey, $acl, $options)
|
506 |
+
->wait();
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Copy an object of any size to a different location asynchronously.
|
511 |
+
*
|
512 |
+
* @param string $fromBucket Bucket where the copy source resides.
|
513 |
+
* @param string $fromKey Key of the copy source.
|
514 |
+
* @param string $destBucket Bucket to which to copy the object.
|
515 |
+
* @param string $destKey Key to which to copy the object.
|
516 |
+
* @param string $acl ACL to apply to the copy (default: private).
|
517 |
+
* @param array $options Options used to configure the upload process.
|
518 |
+
*
|
519 |
+
* @see self::copy for more info about the parameters above.
|
520 |
+
* @return PromiseInterface Returns a promise that will be fulfilled
|
521 |
+
* with the result of the copy.
|
522 |
+
*/
|
523 |
+
public function copyAsync(
|
524 |
+
$fromBucket,
|
525 |
+
$fromKey,
|
526 |
+
$destBucket,
|
527 |
+
$destKey,
|
528 |
+
$acl = 'private',
|
529 |
+
array $options = []
|
530 |
+
) {
|
531 |
+
// Prepare the options.
|
532 |
+
static $defaults = [
|
533 |
+
'before_upload' => null,
|
534 |
+
'concurrency' => 5,
|
535 |
+
'mup_threshold' => MultipartUploader::PART_MAX_SIZE,
|
536 |
+
'params' => [],
|
537 |
+
'part_size' => null,
|
538 |
+
'version_id' => null,
|
539 |
+
];
|
540 |
+
|
541 |
+
return Promise\coroutine($this->doCopyAsync(
|
542 |
+
['Bucket' => $fromBucket, 'Key' => $fromKey],
|
543 |
+
['Bucket' => $destBucket, 'Key' => $destKey],
|
544 |
+
$acl,
|
545 |
+
$options + $defaults
|
546 |
+
));
|
547 |
+
}
|
548 |
+
|
549 |
+
private function doCopyAsync(
|
550 |
+
array $source,
|
551 |
+
array $destination,
|
552 |
+
$acl,
|
553 |
+
array $options
|
554 |
+
) {
|
555 |
+
return function () use ($source, $destination, $acl, $options) {
|
556 |
+
$sourcePath = '/' . $source['Bucket'] . '/' . rawurlencode($source['Key']);
|
557 |
+
if ($options['version_id']) {
|
558 |
+
$sourcePath .= "?versionId={$options['version_id']}";
|
559 |
+
$source['VersionId'] = $options['version_id'];
|
560 |
+
}
|
561 |
+
|
562 |
+
$objectStats = (yield $this->headObjectAsync($source));
|
563 |
+
|
564 |
+
if ($objectStats['ContentLength'] > $options['mup_threshold']) {
|
565 |
+
$mup = new MultipartCopy($this, $sourcePath, $destination + [
|
566 |
+
'source_metadata' => $objectStats,
|
567 |
+
'acl' => $acl,
|
568 |
+
] + $options);
|
569 |
+
|
570 |
+
yield $mup->promise();
|
571 |
+
} else {
|
572 |
+
yield $this->copyObjectAsync($options + $destination + [
|
573 |
+
'ACL' => $acl,
|
574 |
+
'MetadataDirective' => 'COPY',
|
575 |
+
'CopySource' => $sourcePath,
|
576 |
+
] + $options['params']);
|
577 |
+
}
|
578 |
+
};
|
579 |
+
}
|
580 |
+
|
581 |
+
/**
|
582 |
+
* Recursively uploads all files in a given directory to a given bucket.
|
583 |
+
*
|
584 |
+
* @param string $directory Full path to a directory to upload
|
585 |
+
* @param string $bucket Name of the bucket
|
586 |
+
* @param string $keyPrefix Virtual directory key prefix to add to each upload
|
587 |
+
* @param array $options Options available in Aws\S3\Transfer::__construct
|
588 |
+
*
|
589 |
+
* @see Aws\S3\Transfer for more options and customization
|
590 |
+
*/
|
591 |
+
public function uploadDirectory(
|
592 |
+
$directory,
|
593 |
+
$bucket,
|
594 |
+
$keyPrefix = null,
|
595 |
+
array $options = []
|
596 |
+
) {
|
597 |
+
$d = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
|
598 |
+
(new Transfer($this, $directory, $d, $options))->transfer();
|
599 |
+
}
|
600 |
+
|
601 |
+
/**
|
602 |
+
* Downloads a bucket to the local filesystem
|
603 |
+
*
|
604 |
+
* @param string $directory Directory to download to
|
605 |
+
* @param string $bucket Bucket to download from
|
606 |
+
* @param string $keyPrefix Only download objects that use this key prefix
|
607 |
+
* @param array $options Options available in Aws\S3\Transfer::__construct
|
608 |
+
*/
|
609 |
+
public function downloadBucket(
|
610 |
+
$directory,
|
611 |
+
$bucket,
|
612 |
+
$keyPrefix = '',
|
613 |
+
array $options = []
|
614 |
+
) {
|
615 |
+
$s = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
|
616 |
+
(new Transfer($this, $s, $directory, $options))->transfer();
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* Determines if the body should be uploaded using PutObject or the
|
621 |
+
* Multipart Upload System. It also modifies the passed-in $body as needed
|
622 |
+
* to support the upload.
|
623 |
+
*
|
624 |
+
* @param StreamInterface $body Stream representing the body.
|
625 |
+
* @param integer $threshold Minimum bytes before using Multipart.
|
626 |
+
*
|
627 |
+
* @return bool
|
628 |
+
*/
|
629 |
+
private function requiresMultipart(StreamInterface &$body, $threshold)
|
630 |
+
{
|
631 |
+
// If body size known, compare to threshold to determine if Multipart.
|
632 |
+
if ($body->getSize() !== null) {
|
633 |
+
return $body->getSize() >= $threshold;
|
634 |
+
}
|
635 |
+
|
636 |
+
// Handle the situation where the body size is unknown.
|
637 |
+
// Read up to 5MB into a buffer to determine how to upload the body.
|
638 |
+
$buffer = Psr7\stream_for();
|
639 |
+
Psr7\copy_to_stream($body, $buffer, MultipartUploader::PART_MIN_SIZE);
|
640 |
+
|
641 |
+
// If body < 5MB, use PutObject with the buffer.
|
642 |
+
if ($buffer->getSize() < MultipartUploader::PART_MIN_SIZE) {
|
643 |
+
$buffer->seek(0);
|
644 |
+
$body = $buffer;
|
645 |
+
return false;
|
646 |
+
}
|
647 |
+
|
648 |
+
// If body >= 5 MB, then use multipart. [YES]
|
649 |
+
if ($body->isSeekable()) {
|
650 |
+
// If the body is seekable, just rewind the body.
|
651 |
+
$body->seek(0);
|
652 |
+
} else {
|
653 |
+
// If the body is non-seekable, stitch the rewind the buffer and
|
654 |
+
// the partially read body together into one stream. This avoids
|
655 |
+
// unnecessary disc usage and does not require seeking on the
|
656 |
+
// original stream.
|
657 |
+
$buffer->seek(0);
|
658 |
+
$body = new Psr7\AppendStream([$buffer, $body]);
|
659 |
+
}
|
660 |
+
|
661 |
+
return true;
|
662 |
+
}
|
663 |
+
|
664 |
+
/**
|
665 |
+
* Determines whether or not a resource exists using a command
|
666 |
+
*
|
667 |
+
* @param CommandInterface $command Command used to poll for the resource
|
668 |
+
*
|
669 |
+
* @return bool
|
670 |
+
* @throws S3Exception|\Exception if there is an unhandled exception
|
671 |
+
*/
|
672 |
+
private function checkExistenceWithCommand(CommandInterface $command)
|
673 |
+
{
|
674 |
+
try {
|
675 |
+
$this->execute($command);
|
676 |
+
return true;
|
677 |
+
} catch (S3Exception $e) {
|
678 |
+
if ($e->getAwsErrorCode() == 'AccessDenied') {
|
679 |
+
return true;
|
680 |
+
}
|
681 |
+
if ($e->getStatusCode() >= 500) {
|
682 |
+
throw $e;
|
683 |
+
}
|
684 |
+
return false;
|
685 |
+
}
|
686 |
+
}
|
687 |
+
|
688 |
+
/**
|
689 |
+
* Provides a middleware that removes the need to specify LocationConstraint on CreateBucket.
|
690 |
+
*
|
691 |
+
* @return \Closure
|
692 |
+
*/
|
693 |
+
private function getLocationConstraintMiddleware()
|
694 |
+
{
|
695 |
+
$region = $this->getRegion();
|
696 |
+
return static function (callable $handler) use ($region) {
|
697 |
+
return function (Command $command, $request = null) use ($handler, $region) {
|
698 |
+
if ($command->getName() === 'CreateBucket') {
|
699 |
+
$locationConstraint = isset($command['CreateBucketConfiguration']['LocationConstraint'])
|
700 |
+
? $command['CreateBucketConfiguration']['LocationConstraint']
|
701 |
+
: null;
|
702 |
+
|
703 |
+
if ($locationConstraint === 'us-east-1') {
|
704 |
+
unset($command['CreateBucketConfiguration']);
|
705 |
+
} elseif ('us-east-1' !== $region && empty($locationConstraint)) {
|
706 |
+
$command['CreateBucketConfiguration'] = ['LocationConstraint' => $region];
|
707 |
+
}
|
708 |
+
}
|
709 |
+
|
710 |
+
return $handler($command, $request);
|
711 |
+
};
|
712 |
+
};
|
713 |
+
}
|
714 |
+
|
715 |
+
/**
|
716 |
+
* Provides a middleware that supports the `SaveAs` parameter.
|
717 |
+
*
|
718 |
+
* @return \Closure
|
719 |
+
*/
|
720 |
+
private function getSaveAsParameter()
|
721 |
+
{
|
722 |
+
return static function (callable $handler) {
|
723 |
+
return function (Command $command, $request = null) use ($handler) {
|
724 |
+
if ($command->getName() === 'GetObject' && isset($command['SaveAs'])) {
|
725 |
+
$command['@http']['sink'] = $command['SaveAs'];
|
726 |
+
unset($command['SaveAs']);
|
727 |
+
}
|
728 |
+
|
729 |
+
return $handler($command, $request);
|
730 |
+
};
|
731 |
+
};
|
732 |
+
}
|
733 |
+
|
734 |
+
/** @internal */
|
735 |
+
public static function _applyRetryConfig($value, $_, HandlerList $list)
|
736 |
+
{
|
737 |
+
if (!$value) {
|
738 |
+
return;
|
739 |
+
}
|
740 |
+
|
741 |
+
$decider = RetryMiddleware::createDefaultDecider($value);
|
742 |
+
$decider = function ($retries, $command, $request, $result, $error) use ($decider, $value) {
|
743 |
+
$maxRetries = null !== $command['@retries']
|
744 |
+
? $command['@retries']
|
745 |
+
: $value;
|
746 |
+
|
747 |
+
if ($decider($retries, $command, $request, $result, $error)) {
|
748 |
+
return true;
|
749 |
+
} elseif ($error instanceof AwsException
|
750 |
+
&& $retries < $maxRetries
|
751 |
+
) {
|
752 |
+
if (
|
753 |
+
$error->getResponse()
|
754 |
+
&& $error->getResponse()->getStatusCode() >= 400
|
755 |
+
) {
|
756 |
+
return strpos(
|
757 |
+
$error->getResponse()->getBody(),
|
758 |
+
'Your socket connection to the server'
|
759 |
+
) !== false;
|
760 |
+
} elseif ($error->getPrevious() instanceof RequestException) {
|
761 |
+
// All commands except CompleteMultipartUpload are
|
762 |
+
// idempotent and may be retried without worry if a
|
763 |
+
// networking error has occurred.
|
764 |
+
return $command->getName() !== 'CompleteMultipartUpload';
|
765 |
+
}
|
766 |
+
}
|
767 |
+
return false;
|
768 |
+
};
|
769 |
+
|
770 |
+
$delay = [RetryMiddleware::class, 'exponentialDelay'];
|
771 |
+
$list->appendSign(Middleware::retry($decider, $delay), 'retry');
|
772 |
+
}
|
773 |
+
|
774 |
+
/** @internal */
|
775 |
+
public static function _applyApiProvider($value, array &$args, HandlerList $list)
|
776 |
+
{
|
777 |
+
ClientResolver::_apply_api_provider($value, $args, $list);
|
778 |
+
$args['parser'] = new GetBucketLocationParser(
|
779 |
+
new AmbiguousSuccessParser(
|
780 |
+
new RetryableMalformedResponseParser(
|
781 |
+
$args['parser'],
|
782 |
+
$args['exception_class']
|
783 |
+
),
|
784 |
+
$args['error_parser'],
|
785 |
+
$args['exception_class']
|
786 |
+
)
|
787 |
+
);
|
788 |
+
}
|
789 |
+
|
790 |
+
/**
|
791 |
+
* @internal
|
792 |
+
* @codeCoverageIgnore
|
793 |
+
*/
|
794 |
+
public static function applyDocFilters(array $api, array $docs)
|
795 |
+
{
|
796 |
+
$b64 = '<div class="alert alert-info">This value will be base64 encoded on your behalf.</div>';
|
797 |
+
$opt = '<div class="alert alert-info">This value will be computed for you it is not supplied.</div>';
|
798 |
+
|
799 |
+
// Add the SourceFile parameter.
|
800 |
+
$docs['shapes']['SourceFile']['base'] = 'The path to a file on disk to use instead of the Body parameter.';
|
801 |
+
$api['shapes']['SourceFile'] = ['type' => 'string'];
|
802 |
+
$api['shapes']['PutObjectRequest']['members']['SourceFile'] = ['shape' => 'SourceFile'];
|
803 |
+
$api['shapes']['UploadPartRequest']['members']['SourceFile'] = ['shape' => 'SourceFile'];
|
804 |
+
|
805 |
+
// Add the ContentSHA256 parameter.
|
806 |
+
$docs['shapes']['ContentSHA256']['base'] = 'A SHA256 hash of the body content of the request.';
|
807 |
+
$api['shapes']['ContentSHA256'] = ['type' => 'string'];
|
808 |
+
$api['shapes']['PutObjectRequest']['members']['ContentSHA256'] = ['shape' => 'ContentSHA256'];
|
809 |
+
$api['shapes']['UploadPartRequest']['members']['ContentSHA256'] = ['shape' => 'ContentSHA256'];
|
810 |
+
unset($api['shapes']['PutObjectRequest']['members']['ContentMD5']);
|
811 |
+
unset($api['shapes']['UploadPartRequest']['members']['ContentMD5']);
|
812 |
+
$docs['shapes']['ContentSHA256']['append'] = $opt;
|
813 |
+
|
814 |
+
// Add the SaveAs parameter.
|
815 |
+
$docs['shapes']['SaveAs']['base'] = 'The path to a file on disk to save the object data.';
|
816 |
+
$api['shapes']['SaveAs'] = ['type' => 'string'];
|
817 |
+
$api['shapes']['GetObjectRequest']['members']['SaveAs'] = ['shape' => 'SaveAs'];
|
818 |
+
|
819 |
+
// Several SSECustomerKey documentation updates.
|
820 |
+
$docs['shapes']['SSECustomerKey']['append'] = $b64;
|
821 |
+
$docs['shapes']['CopySourceSSECustomerKey']['append'] = $b64;
|
822 |
+
$docs['shapes']['SSECustomerKeyMd5']['append'] = $opt;
|
823 |
+
|
824 |
+
// Add the ObjectURL to various output shapes and documentation.
|
825 |
+
$docs['shapes']['ObjectURL']['base'] = 'The URI of the created object.';
|
826 |
+
$api['shapes']['ObjectURL'] = ['type' => 'string'];
|
827 |
+
$api['shapes']['PutObjectOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
|
828 |
+
$api['shapes']['CopyObjectOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
|
829 |
+
$api['shapes']['CompleteMultipartUploadOutput']['members']['ObjectURL'] = ['shape' => 'ObjectURL'];
|
830 |
+
|
831 |
+
// Fix references to Location Constraint.
|
832 |
+
unset($api['shapes']['CreateBucketRequest']['payload']);
|
833 |
+
$api['shapes']['BucketLocationConstraint']['enum'] = [
|
834 |
+
"ap-northeast-1",
|
835 |
+
"ap-southeast-2",
|
836 |
+
"ap-southeast-1",
|
837 |
+
"cn-north-1",
|
838 |
+
"eu-central-1",
|
839 |
+
"eu-west-1",
|
840 |
+
"us-east-1",
|
841 |
+
"us-west-1",
|
842 |
+
"us-west-2",
|
843 |
+
"sa-east-1",
|
844 |
+
];
|
845 |
+
|
846 |
+
// Add a note that the ContentMD5 is optional.
|
847 |
+
$docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on '
|
848 |
+
. 'your behalf.</div>';
|
849 |
+
|
850 |
+
return [
|
851 |
+
new Service($api, ApiProvider::defaultProvider()),
|
852 |
+
new DocModel($docs)
|
853 |
+
];
|
854 |
+
}
|
855 |
+
}
|
includes/aws/Aws/S3/S3UriParser.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use GuzzleHttp\Psr7;
|
5 |
+
use Psr\Http\Message\UriInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Extracts a region, bucket, key, and and if a URI is in path-style
|
9 |
+
*/
|
10 |
+
class S3UriParser
|
11 |
+
{
|
12 |
+
private $pattern = '/^(.+\\.)?s3[.-]([A-Za-z0-9-]+)\\./';
|
13 |
+
|
14 |
+
private static $defaultResult = [
|
15 |
+
'path_style' => true,
|
16 |
+
'bucket' => null,
|
17 |
+
'key' => null,
|
18 |
+
'region' => null
|
19 |
+
];
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Parses a URL into an associative array of Amazon S3 data including:
|
23 |
+
*
|
24 |
+
* - bucket: The Amazon S3 bucket (null if none)
|
25 |
+
* - key: The Amazon S3 key (null if none)
|
26 |
+
* - path_style: Set to true if using path style, or false if not
|
27 |
+
* - region: Set to a string if a non-class endpoint is used or null.
|
28 |
+
*
|
29 |
+
* @param string|UriInterface $uri
|
30 |
+
*
|
31 |
+
* @return array
|
32 |
+
* @throws \InvalidArgumentException
|
33 |
+
*/
|
34 |
+
public function parse($uri)
|
35 |
+
{
|
36 |
+
$url = Psr7\uri_for($uri);
|
37 |
+
if (!$url->getHost()) {
|
38 |
+
throw new \InvalidArgumentException('No hostname found in URI: '
|
39 |
+
. $uri);
|
40 |
+
}
|
41 |
+
|
42 |
+
if (!preg_match($this->pattern, $url->getHost(), $matches)) {
|
43 |
+
return $this->parseCustomEndpoint($url);
|
44 |
+
}
|
45 |
+
|
46 |
+
// Parse the URI based on the matched format (path / virtual)
|
47 |
+
$result = empty($matches[1])
|
48 |
+
? $this->parsePathStyle($url)
|
49 |
+
: $this->parseVirtualHosted($url, $matches);
|
50 |
+
|
51 |
+
// Add the region if one was found and not the classic endpoint
|
52 |
+
$result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
|
53 |
+
|
54 |
+
return $result;
|
55 |
+
}
|
56 |
+
|
57 |
+
private function parseCustomEndpoint(UriInterface $url)
|
58 |
+
{
|
59 |
+
$result = $result = self::$defaultResult;
|
60 |
+
$path = ltrim($url->getPath(), '/ ');
|
61 |
+
$segments = explode('/', $path, 2);
|
62 |
+
|
63 |
+
if (isset($segments[0])) {
|
64 |
+
$result['bucket'] = $segments[0];
|
65 |
+
if (isset($segments[1])) {
|
66 |
+
$result['key'] = $segments[1];
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
return $result;
|
71 |
+
}
|
72 |
+
|
73 |
+
private function parsePathStyle(UriInterface $url)
|
74 |
+
{
|
75 |
+
$result = self::$defaultResult;
|
76 |
+
|
77 |
+
if ($url->getPath() != '/') {
|
78 |
+
$path = ltrim($url->getPath(), '/');
|
79 |
+
if ($path) {
|
80 |
+
$pathPos = strpos($path, '/');
|
81 |
+
if ($pathPos === false) {
|
82 |
+
// https://s3.amazonaws.com/bucket
|
83 |
+
$result['bucket'] = $path;
|
84 |
+
} elseif ($pathPos == strlen($path) - 1) {
|
85 |
+
// https://s3.amazonaws.com/bucket/
|
86 |
+
$result['bucket'] = substr($path, 0, -1);
|
87 |
+
} else {
|
88 |
+
// https://s3.amazonaws.com/bucket/key
|
89 |
+
$result['bucket'] = substr($path, 0, $pathPos);
|
90 |
+
$result['key'] = substr($path, $pathPos + 1) ?: null;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
return $result;
|
96 |
+
}
|
97 |
+
|
98 |
+
private function parseVirtualHosted(UriInterface $url, array $matches)
|
99 |
+
{
|
100 |
+
$result = self::$defaultResult;
|
101 |
+
$result['path_style'] = false;
|
102 |
+
// Remove trailing "." from the prefix to get the bucket
|
103 |
+
$result['bucket'] = substr($matches[1], 0, -1);
|
104 |
+
$path = $url->getPath();
|
105 |
+
// Check if a key was present, and if so, removing the leading "/"
|
106 |
+
$result['key'] = !$path || $path == '/' ? null : substr($path, 1);
|
107 |
+
|
108 |
+
return $result;
|
109 |
+
}
|
110 |
+
}
|
includes/aws/Aws/S3/SSECMiddleware.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CommandInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Simplifies the SSE-C process by encoding and hashing the key.
|
9 |
+
* @internal
|
10 |
+
*/
|
11 |
+
class SSECMiddleware
|
12 |
+
{
|
13 |
+
private $endpointScheme;
|
14 |
+
private $nextHandler;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Provide the URI scheme of the client sending requests.
|
18 |
+
*
|
19 |
+
* @param string $endpointScheme URI scheme (http/https).
|
20 |
+
*
|
21 |
+
* @return callable
|
22 |
+
*/
|
23 |
+
public static function wrap($endpointScheme)
|
24 |
+
{
|
25 |
+
return function (callable $handler) use ($endpointScheme) {
|
26 |
+
return new self($endpointScheme, $handler);
|
27 |
+
};
|
28 |
+
}
|
29 |
+
|
30 |
+
public function __construct($endpointScheme, callable $nextHandler)
|
31 |
+
{
|
32 |
+
$this->nextHandler = $nextHandler;
|
33 |
+
$this->endpointScheme = $endpointScheme;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function __invoke(
|
37 |
+
CommandInterface $command,
|
38 |
+
RequestInterface $request = null
|
39 |
+
) {
|
40 |
+
// Allows only HTTPS connections when using SSE-C
|
41 |
+
if (($command['SSECustomerKey'] || $command['CopySourceSSECustomerKey'])
|
42 |
+
&& $this->endpointScheme !== 'https'
|
43 |
+
) {
|
44 |
+
throw new \RuntimeException('You must configure your S3 client to '
|
45 |
+
. 'use HTTPS in order to use the SSE-C features.');
|
46 |
+
}
|
47 |
+
|
48 |
+
// Prepare the normal SSE-CPK headers
|
49 |
+
if ($command['SSECustomerKey']) {
|
50 |
+
$this->prepareSseParams($command);
|
51 |
+
}
|
52 |
+
|
53 |
+
// If it's a copy operation, prepare the SSE-CPK headers for the source.
|
54 |
+
if ($command['CopySourceSSECustomerKey']) {
|
55 |
+
$this->prepareSseParams($command, 'CopySource');
|
56 |
+
}
|
57 |
+
|
58 |
+
$f = $this->nextHandler;
|
59 |
+
return $f($command, $request);
|
60 |
+
}
|
61 |
+
|
62 |
+
private function prepareSseParams(CommandInterface $command, $prefix = '')
|
63 |
+
{
|
64 |
+
// Base64 encode the provided key
|
65 |
+
$key = $command[$prefix . 'SSECustomerKey'];
|
66 |
+
$command[$prefix . 'SSECustomerKey'] = base64_encode($key);
|
67 |
+
|
68 |
+
// Base64 the provided MD5 or, generate an MD5 if not provided
|
69 |
+
if ($md5 = $command[$prefix . 'SSECustomerKeyMD5']) {
|
70 |
+
$command[$prefix . 'SSECustomerKeyMD5'] = base64_encode($md5);
|
71 |
+
} else {
|
72 |
+
$command[$prefix . 'SSECustomerKeyMD5'] = base64_encode(md5($key, true));
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
includes/aws/Aws/S3/StreamWrapper.php
ADDED
@@ -0,0 +1,949 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws\CacheInterface;
|
5 |
+
use Aws\LruArrayCache;
|
6 |
+
use Aws\Result;
|
7 |
+
use Aws\S3\Exception\S3Exception;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\Psr7\Stream;
|
10 |
+
use GuzzleHttp\Psr7\CachingStream;
|
11 |
+
use Psr\Http\Message\StreamInterface;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Amazon S3 stream wrapper to use "s3://<bucket>/<key>" files with PHP
|
15 |
+
* streams, supporting "r", "w", "a", "x".
|
16 |
+
*
|
17 |
+
* # Opening "r" (read only) streams:
|
18 |
+
*
|
19 |
+
* Read only streams are truly streaming by default and will not allow you to
|
20 |
+
* seek. This is because data read from the stream is not kept in memory or on
|
21 |
+
* the local filesystem. You can force a "r" stream to be seekable by setting
|
22 |
+
* the "seekable" stream context option true. This will allow true streaming of
|
23 |
+
* data from Amazon S3, but will maintain a buffer of previously read bytes in
|
24 |
+
* a 'php://temp' stream to allow seeking to previously read bytes from the
|
25 |
+
* stream.
|
26 |
+
*
|
27 |
+
* You may pass any GetObject parameters as 's3' stream context options. These
|
28 |
+
* options will affect how the data is downloaded from Amazon S3.
|
29 |
+
*
|
30 |
+
* # Opening "w" and "x" (write only) streams:
|
31 |
+
*
|
32 |
+
* Because Amazon S3 requires a Content-Length header, write only streams will
|
33 |
+
* maintain a 'php://temp' stream to buffer data written to the stream until
|
34 |
+
* the stream is flushed (usually by closing the stream with fclose).
|
35 |
+
*
|
36 |
+
* You may pass any PutObject parameters as 's3' stream context options. These
|
37 |
+
* options will affect how the data is uploaded to Amazon S3.
|
38 |
+
*
|
39 |
+
* When opening an "x" stream, the file must exist on Amazon S3 for the stream
|
40 |
+
* to open successfully.
|
41 |
+
*
|
42 |
+
* # Opening "a" (write only append) streams:
|
43 |
+
*
|
44 |
+
* Similar to "w" streams, opening append streams requires that the data be
|
45 |
+
* buffered in a "php://temp" stream. Append streams will attempt to download
|
46 |
+
* the contents of an object in Amazon S3, seek to the end of the object, then
|
47 |
+
* allow you to append to the contents of the object. The data will then be
|
48 |
+
* uploaded using a PutObject operation when the stream is flushed (usually
|
49 |
+
* with fclose).
|
50 |
+
*
|
51 |
+
* You may pass any GetObject and/or PutObject parameters as 's3' stream
|
52 |
+
* context options. These options will affect how the data is downloaded and
|
53 |
+
* uploaded from Amazon S3.
|
54 |
+
*
|
55 |
+
* Stream context options:
|
56 |
+
*
|
57 |
+
* - "seekable": Set to true to create a seekable "r" (read only) stream by
|
58 |
+
* using a php://temp stream buffer
|
59 |
+
* - For "unlink" only: Any option that can be passed to the DeleteObject
|
60 |
+
* operation
|
61 |
+
*/
|
62 |
+
class StreamWrapper
|
63 |
+
{
|
64 |
+
/** @var resource|null Stream context (this is set by PHP) */
|
65 |
+
public $context;
|
66 |
+
|
67 |
+
/** @var StreamInterface Underlying stream resource */
|
68 |
+
private $body;
|
69 |
+
|
70 |
+
/** @var int Size of the body that is opened */
|
71 |
+
private $size;
|
72 |
+
|
73 |
+
/** @var array Hash of opened stream parameters */
|
74 |
+
private $params = [];
|
75 |
+
|
76 |
+
/** @var string Mode in which the stream was opened */
|
77 |
+
private $mode;
|
78 |
+
|
79 |
+
/** @var \Iterator Iterator used with opendir() related calls */
|
80 |
+
private $objectIterator;
|
81 |
+
|
82 |
+
/** @var string The bucket that was opened when opendir() was called */
|
83 |
+
private $openedBucket;
|
84 |
+
|
85 |
+
/** @var string The prefix of the bucket that was opened with opendir() */
|
86 |
+
private $openedBucketPrefix;
|
87 |
+
|
88 |
+
/** @var string Opened bucket path */
|
89 |
+
private $openedPath;
|
90 |
+
|
91 |
+
/** @var CacheInterface Cache for object and dir lookups */
|
92 |
+
private $cache;
|
93 |
+
|
94 |
+
/** @var string The opened protocol (e.g., "s3") */
|
95 |
+
private $protocol = 's3';
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Register the 's3://' stream wrapper
|
99 |
+
*
|
100 |
+
* @param S3Client $client Client to use with the stream wrapper
|
101 |
+
* @param string $protocol Protocol to register as.
|
102 |
+
* @param CacheInterface $cache Default cache for the protocol.
|
103 |
+
*/
|
104 |
+
public static function register(
|
105 |
+
S3Client $client,
|
106 |
+
$protocol = 's3',
|
107 |
+
CacheInterface $cache = null
|
108 |
+
) {
|
109 |
+
if (in_array($protocol, stream_get_wrappers())) {
|
110 |
+
stream_wrapper_unregister($protocol);
|
111 |
+
}
|
112 |
+
|
113 |
+
// Set the client passed in as the default stream context client
|
114 |
+
stream_wrapper_register($protocol, get_called_class(), STREAM_IS_URL);
|
115 |
+
$default = stream_context_get_options(stream_context_get_default());
|
116 |
+
$default[$protocol]['client'] = $client;
|
117 |
+
|
118 |
+
if ($cache) {
|
119 |
+
$default[$protocol]['cache'] = $cache;
|
120 |
+
} elseif (!isset($default[$protocol]['cache'])) {
|
121 |
+
// Set a default cache adapter.
|
122 |
+
$default[$protocol]['cache'] = new LruArrayCache();
|
123 |
+
}
|
124 |
+
|
125 |
+
stream_context_set_default($default);
|
126 |
+
}
|
127 |
+
|
128 |
+
public function stream_close()
|
129 |
+
{
|
130 |
+
$this->body = $this->cache = null;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function stream_open($path, $mode, $options, &$opened_path)
|
134 |
+
{
|
135 |
+
$this->initProtocol($path);
|
136 |
+
$this->params = $this->getBucketKey($path);
|
137 |
+
$this->mode = rtrim($mode, 'bt');
|
138 |
+
|
139 |
+
if ($errors = $this->validate($path, $this->mode)) {
|
140 |
+
return $this->triggerError($errors);
|
141 |
+
}
|
142 |
+
|
143 |
+
return $this->boolCall(function() use ($path) {
|
144 |
+
switch ($this->mode) {
|
145 |
+
case 'r': return $this->openReadStream($path);
|
146 |
+
case 'a': return $this->openAppendStream($path);
|
147 |
+
default: return $this->openWriteStream($path);
|
148 |
+
}
|
149 |
+
});
|
150 |
+
}
|
151 |
+
|
152 |
+
public function stream_eof()
|
153 |
+
{
|
154 |
+
return $this->body->eof();
|
155 |
+
}
|
156 |
+
|
157 |
+
public function stream_flush()
|
158 |
+
{
|
159 |
+
if ($this->mode == 'r') {
|
160 |
+
return false;
|
161 |
+
}
|
162 |
+
|
163 |
+
if ($this->body->isSeekable()) {
|
164 |
+
$this->body->seek(0);
|
165 |
+
}
|
166 |
+
$params = $this->getOptions(true);
|
167 |
+
$params['Body'] = $this->body;
|
168 |
+
|
169 |
+
// Attempt to guess the ContentType of the upload based on the
|
170 |
+
// file extension of the key
|
171 |
+
if (!isset($params['ContentType']) &&
|
172 |
+
($type = Psr7\mimetype_from_filename($params['Key']))
|
173 |
+
) {
|
174 |
+
$params['ContentType'] = $type;
|
175 |
+
}
|
176 |
+
|
177 |
+
return $this->boolCall(function () use ($params) {
|
178 |
+
return (bool) $this->getClient()->putObject($params);
|
179 |
+
});
|
180 |
+
}
|
181 |
+
|
182 |
+
public function stream_read($count)
|
183 |
+
{
|
184 |
+
return $this->body->read($count);
|
185 |
+
}
|
186 |
+
|
187 |
+
public function stream_seek($offset, $whence = SEEK_SET)
|
188 |
+
{
|
189 |
+
return !$this->body->isSeekable()
|
190 |
+
? false
|
191 |
+
: $this->boolCall(function () use ($offset, $whence) {
|
192 |
+
$this->body->seek($offset, $whence);
|
193 |
+
return true;
|
194 |
+
});
|
195 |
+
}
|
196 |
+
|
197 |
+
public function stream_tell()
|
198 |
+
{
|
199 |
+
return $this->boolCall(function() { return $this->body->tell(); });
|
200 |
+
}
|
201 |
+
|
202 |
+
public function stream_write($data)
|
203 |
+
{
|
204 |
+
return $this->body->write($data);
|
205 |
+
}
|
206 |
+
|
207 |
+
public function unlink($path)
|
208 |
+
{
|
209 |
+
$this->initProtocol($path);
|
210 |
+
|
211 |
+
return $this->boolCall(function () use ($path) {
|
212 |
+
$this->clearCacheKey($path);
|
213 |
+
$this->getClient()->deleteObject($this->withPath($path));
|
214 |
+
return true;
|
215 |
+
});
|
216 |
+
}
|
217 |
+
|
218 |
+
public function stream_stat()
|
219 |
+
{
|
220 |
+
$stat = $this->getStatTemplate();
|
221 |
+
$stat[7] = $stat['size'] = $this->getSize();
|
222 |
+
$stat[2] = $stat['mode'] = $this->mode;
|
223 |
+
|
224 |
+
return $stat;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Provides information for is_dir, is_file, filesize, etc. Works on
|
229 |
+
* buckets, keys, and prefixes.
|
230 |
+
* @link http://www.php.net/manual/en/streamwrapper.url-stat.php
|
231 |
+
*/
|
232 |
+
public function url_stat($path, $flags)
|
233 |
+
{
|
234 |
+
$this->initProtocol($path);
|
235 |
+
|
236 |
+
// Some paths come through as S3:// for some reason.
|
237 |
+
$split = explode('://', $path);
|
238 |
+
$path = strtolower($split[0]) . '://' . $split[1];
|
239 |
+
|
240 |
+
// Check if this path is in the url_stat cache
|
241 |
+
if ($value = $this->getCacheStorage()->get($path)) {
|
242 |
+
return $value;
|
243 |
+
}
|
244 |
+
|
245 |
+
$stat = $this->createStat($path, $flags);
|
246 |
+
|
247 |
+
if (is_array($stat)) {
|
248 |
+
$this->getCacheStorage()->set($path, $stat);
|
249 |
+
}
|
250 |
+
|
251 |
+
return $stat;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Parse the protocol out of the given path.
|
256 |
+
*
|
257 |
+
* @param $path
|
258 |
+
*/
|
259 |
+
private function initProtocol($path)
|
260 |
+
{
|
261 |
+
$parts = explode('://', $path, 2);
|
262 |
+
$this->protocol = $parts[0] ?: 's3';
|
263 |
+
}
|
264 |
+
|
265 |
+
private function createStat($path, $flags)
|
266 |
+
{
|
267 |
+
$this->initProtocol($path);
|
268 |
+
$parts = $this->withPath($path);
|
269 |
+
|
270 |
+
if (!$parts['Key']) {
|
271 |
+
return $this->statDirectory($parts, $path, $flags);
|
272 |
+
}
|
273 |
+
|
274 |
+
return $this->boolCall(function () use ($parts, $path) {
|
275 |
+
try {
|
276 |
+
$result = $this->getClient()->headObject($parts);
|
277 |
+
if (substr($parts['Key'], -1, 1) == '/' &&
|
278 |
+
$result['ContentLength'] == 0
|
279 |
+
) {
|
280 |
+
// Return as if it is a bucket to account for console
|
281 |
+
// bucket objects (e.g., zero-byte object "foo/")
|
282 |
+
return $this->formatUrlStat($path);
|
283 |
+
} else {
|
284 |
+
// Attempt to stat and cache regular object
|
285 |
+
return $this->formatUrlStat($result->toArray());
|
286 |
+
}
|
287 |
+
} catch (S3Exception $e) {
|
288 |
+
// Maybe this isn't an actual key, but a prefix. Do a prefix
|
289 |
+
// listing of objects to determine.
|
290 |
+
$result = $this->getClient()->listObjects([
|
291 |
+
'Bucket' => $parts['Bucket'],
|
292 |
+
'Prefix' => rtrim($parts['Key'], '/') . '/',
|
293 |
+
'MaxKeys' => 1
|
294 |
+
]);
|
295 |
+
if (!$result['Contents'] && !$result['CommonPrefixes']) {
|
296 |
+
throw new \Exception("File or directory not found: $path");
|
297 |
+
}
|
298 |
+
return $this->formatUrlStat($path);
|
299 |
+
}
|
300 |
+
}, $flags);
|
301 |
+
}
|
302 |
+
|
303 |
+
private function statDirectory($parts, $path, $flags)
|
304 |
+
{
|
305 |
+
// Stat "directories": buckets, or "s3://"
|
306 |
+
if (!$parts['Bucket'] ||
|
307 |
+
$this->getClient()->doesBucketExist($parts['Bucket'])
|
308 |
+
) {
|
309 |
+
return $this->formatUrlStat($path);
|
310 |
+
}
|
311 |
+
|
312 |
+
return $this->triggerError("File or directory not found: $path", $flags);
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Support for mkdir().
|
317 |
+
*
|
318 |
+
* @param string $path Directory which should be created.
|
319 |
+
* @param int $mode Permissions. 700-range permissions map to
|
320 |
+
* ACL_PUBLIC. 600-range permissions map to
|
321 |
+
* ACL_AUTH_READ. All other permissions map to
|
322 |
+
* ACL_PRIVATE. Expects octal form.
|
323 |
+
* @param int $options A bitwise mask of values, such as
|
324 |
+
* STREAM_MKDIR_RECURSIVE.
|
325 |
+
*
|
326 |
+
* @return bool
|
327 |
+
* @link http://www.php.net/manual/en/streamwrapper.mkdir.php
|
328 |
+
*/
|
329 |
+
public function mkdir($path, $mode, $options)
|
330 |
+
{
|
331 |
+
$this->initProtocol($path);
|
332 |
+
$params = $this->withPath($path);
|
333 |
+
$this->clearCacheKey($path);
|
334 |
+
if (!$params['Bucket']) {
|
335 |
+
return false;
|
336 |
+
}
|
337 |
+
|
338 |
+
if (!isset($params['ACL'])) {
|
339 |
+
$params['ACL'] = $this->determineAcl($mode);
|
340 |
+
}
|
341 |
+
|
342 |
+
return empty($params['Key'])
|
343 |
+
? $this->createBucket($path, $params)
|
344 |
+
: $this->createSubfolder($path, $params);
|
345 |
+
}
|
346 |
+
|
347 |
+
public function rmdir($path, $options)
|
348 |
+
{
|
349 |
+
$this->initProtocol($path);
|
350 |
+
$this->clearCacheKey($path);
|
351 |
+
$params = $this->withPath($path);
|
352 |
+
$client = $this->getClient();
|
353 |
+
|
354 |
+
if (!$params['Bucket']) {
|
355 |
+
return $this->triggerError('You must specify a bucket');
|
356 |
+
}
|
357 |
+
|
358 |
+
return $this->boolCall(function () use ($params, $path, $client) {
|
359 |
+
if (!$params['Key']) {
|
360 |
+
$client->deleteBucket(['Bucket' => $params['Bucket']]);
|
361 |
+
return true;
|
362 |
+
}
|
363 |
+
return $this->deleteSubfolder($path, $params);
|
364 |
+
});
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Support for opendir().
|
369 |
+
*
|
370 |
+
* The opendir() method of the Amazon S3 stream wrapper supports a stream
|
371 |
+
* context option of "listFilter". listFilter must be a callable that
|
372 |
+
* accepts an associative array of object data and returns true if the
|
373 |
+
* object should be yielded when iterating the keys in a bucket.
|
374 |
+
*
|
375 |
+
* @param string $path The path to the directory
|
376 |
+
* (e.g. "s3://dir[</prefix>]")
|
377 |
+
* @param string $options Unused option variable
|
378 |
+
*
|
379 |
+
* @return bool true on success
|
380 |
+
* @see http://www.php.net/manual/en/function.opendir.php
|
381 |
+
*/
|
382 |
+
public function dir_opendir($path, $options)
|
383 |
+
{
|
384 |
+
$this->initProtocol($path);
|
385 |
+
$this->openedPath = $path;
|
386 |
+
$params = $this->withPath($path);
|
387 |
+
$delimiter = $this->getOption('delimiter');
|
388 |
+
/** @var callable $filterFn */
|
389 |
+
$filterFn = $this->getOption('listFilter');
|
390 |
+
$op = ['Bucket' => $params['Bucket']];
|
391 |
+
$this->openedBucket = $params['Bucket'];
|
392 |
+
|
393 |
+
if ($delimiter === null) {
|
394 |
+
$delimiter = '/';
|
395 |
+
}
|
396 |
+
|
397 |
+
if ($delimiter) {
|
398 |
+
$op['Delimiter'] = $delimiter;
|
399 |
+
}
|
400 |
+
|
401 |
+
if ($params['Key']) {
|
402 |
+
$params['Key'] = rtrim($params['Key'], $delimiter) . $delimiter;
|
403 |
+
$op['Prefix'] = $params['Key'];
|
404 |
+
}
|
405 |
+
|
406 |
+
$this->openedBucketPrefix = $params['Key'];
|
407 |
+
|
408 |
+
// Filter our "/" keys added by the console as directories, and ensure
|
409 |
+
// that if a filter function is provided that it passes the filter.
|
410 |
+
$this->objectIterator = \Aws\flatmap(
|
411 |
+
$this->getClient()->getPaginator('ListObjects', $op),
|
412 |
+
function (Result $result) use ($filterFn) {
|
413 |
+
$contentsAndPrefixes = $result->search('[Contents[], CommonPrefixes[]][]');
|
414 |
+
// Filter out dir place holder keys and use the filter fn.
|
415 |
+
return array_filter(
|
416 |
+
$contentsAndPrefixes,
|
417 |
+
function ($key) use ($filterFn) {
|
418 |
+
return (!$filterFn || call_user_func($filterFn, $key))
|
419 |
+
&& (!isset($key['Key']) || substr($key['Key'], -1, 1) !== '/');
|
420 |
+
}
|
421 |
+
);
|
422 |
+
}
|
423 |
+
);
|
424 |
+
|
425 |
+
return true;
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Close the directory listing handles
|
430 |
+
*
|
431 |
+
* @return bool true on success
|
432 |
+
*/
|
433 |
+
public function dir_closedir()
|
434 |
+
{
|
435 |
+
$this->objectIterator = null;
|
436 |
+
gc_collect_cycles();
|
437 |
+
|
438 |
+
return true;
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* This method is called in response to rewinddir()
|
443 |
+
*
|
444 |
+
* @return boolean true on success
|
445 |
+
*/
|
446 |
+
public function dir_rewinddir()
|
447 |
+
{
|
448 |
+
$this->boolCall(function() {
|
449 |
+
$this->objectIterator = null;
|
450 |
+
$this->dir_opendir($this->openedPath, null);
|
451 |
+
return true;
|
452 |
+
});
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* This method is called in response to readdir()
|
457 |
+
*
|
458 |
+
* @return string Should return a string representing the next filename, or
|
459 |
+
* false if there is no next file.
|
460 |
+
* @link http://www.php.net/manual/en/function.readdir.php
|
461 |
+
*/
|
462 |
+
public function dir_readdir()
|
463 |
+
{
|
464 |
+
// Skip empty result keys
|
465 |
+
if (!$this->objectIterator->valid()) {
|
466 |
+
return false;
|
467 |
+
}
|
468 |
+
|
469 |
+
// First we need to create a cache key. This key is the full path to
|
470 |
+
// then object in s3: protocol://bucket/key.
|
471 |
+
// Next we need to create a result value. The result value is the
|
472 |
+
// current value of the iterator without the opened bucket prefix to
|
473 |
+
// emulate how readdir() works on directories.
|
474 |
+
// The cache key and result value will depend on if this is a prefix
|
475 |
+
// or a key.
|
476 |
+
$cur = $this->objectIterator->current();
|
477 |
+
if (isset($cur['Prefix'])) {
|
478 |
+
// Include "directories". Be sure to strip a trailing "/"
|
479 |
+
// on prefixes.
|
480 |
+
$result = rtrim($cur['Prefix'], '/');
|
481 |
+
$key = $this->formatKey($result);
|
482 |
+
$stat = $this->formatUrlStat($key);
|
483 |
+
} else {
|
484 |
+
$result = $cur['Key'];
|
485 |
+
$key = $this->formatKey($cur['Key']);
|
486 |
+
$stat = $this->formatUrlStat($cur);
|
487 |
+
}
|
488 |
+
|
489 |
+
// Cache the object data for quick url_stat lookups used with
|
490 |
+
// RecursiveDirectoryIterator.
|
491 |
+
$this->getCacheStorage()->set($key, $stat);
|
492 |
+
$this->objectIterator->next();
|
493 |
+
|
494 |
+
// Remove the prefix from the result to emulate other stream wrappers.
|
495 |
+
return $this->openedBucketPrefix
|
496 |
+
? substr($result, strlen($this->openedBucketPrefix))
|
497 |
+
: $result;
|
498 |
+
}
|
499 |
+
|
500 |
+
private function formatKey($key)
|
501 |
+
{
|
502 |
+
$protocol = explode('://', $this->openedPath)[0];
|
503 |
+
return "{$protocol}://{$this->openedBucket}/{$key}";
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Called in response to rename() to rename a file or directory. Currently
|
508 |
+
* only supports renaming objects.
|
509 |
+
*
|
510 |
+
* @param string $path_from the path to the file to rename
|
511 |
+
* @param string $path_to the new path to the file
|
512 |
+
*
|
513 |
+
* @return bool true if file was successfully renamed
|
514 |
+
* @link http://www.php.net/manual/en/function.rename.php
|
515 |
+
*/
|
516 |
+
public function rename($path_from, $path_to)
|
517 |
+
{
|
518 |
+
// PHP will not allow rename across wrapper types, so we can safely
|
519 |
+
// assume $path_from and $path_to have the same protocol
|
520 |
+
$this->initProtocol($path_from);
|
521 |
+
$partsFrom = $this->withPath($path_from);
|
522 |
+
$partsTo = $this->withPath($path_to);
|
523 |
+
$this->clearCacheKey($path_from);
|
524 |
+
$this->clearCacheKey($path_to);
|
525 |
+
|
526 |
+
if (!$partsFrom['Key'] || !$partsTo['Key']) {
|
527 |
+
return $this->triggerError('The Amazon S3 stream wrapper only '
|
528 |
+
. 'supports copying objects');
|
529 |
+
}
|
530 |
+
|
531 |
+
return $this->boolCall(function () use ($partsFrom, $partsTo) {
|
532 |
+
$options = $this->getOptions(true);
|
533 |
+
// Copy the object and allow overriding default parameters if
|
534 |
+
// desired, but by default copy metadata
|
535 |
+
$this->getClient()->copy(
|
536 |
+
$partsFrom['Bucket'],
|
537 |
+
$partsFrom['Key'],
|
538 |
+
$partsTo['Bucket'],
|
539 |
+
$partsTo['Key'],
|
540 |
+
isset($options['acl']) ? $options['acl'] : 'private',
|
541 |
+
$options
|
542 |
+
);
|
543 |
+
// Delete the original object
|
544 |
+
$this->getClient()->deleteObject([
|
545 |
+
'Bucket' => $partsFrom['Bucket'],
|
546 |
+
'Key' => $partsFrom['Key']
|
547 |
+
] + $options);
|
548 |
+
return true;
|
549 |
+
});
|
550 |
+
}
|
551 |
+
|
552 |
+
public function stream_cast($cast_as)
|
553 |
+
{
|
554 |
+
return false;
|
555 |
+
}
|
556 |
+
|
557 |
+
/**
|
558 |
+
* Validates the provided stream arguments for fopen and returns an array
|
559 |
+
* of errors.
|
560 |
+
*/
|
561 |
+
private function validate($path, $mode)
|
562 |
+
{
|
563 |
+
$errors = [];
|
564 |
+
|
565 |
+
if (!$this->getOption('Key')) {
|
566 |
+
$errors[] = 'Cannot open a bucket. You must specify a path in the '
|
567 |
+
. 'form of s3://bucket/key';
|
568 |
+
}
|
569 |
+
|
570 |
+
if (!in_array($mode, ['r', 'w', 'a', 'x'])) {
|
571 |
+
$errors[] = "Mode not supported: {$mode}. "
|
572 |
+
. "Use one 'r', 'w', 'a', or 'x'.";
|
573 |
+
}
|
574 |
+
|
575 |
+
// When using mode "x" validate if the file exists before attempting
|
576 |
+
// to read
|
577 |
+
if ($mode == 'x' &&
|
578 |
+
$this->getClient()->doesObjectExist(
|
579 |
+
$this->getOption('Bucket'),
|
580 |
+
$this->getOption('Key'),
|
581 |
+
$this->getOptions(true)
|
582 |
+
)
|
583 |
+
) {
|
584 |
+
$errors[] = "{$path} already exists on Amazon S3";
|
585 |
+
}
|
586 |
+
|
587 |
+
return $errors;
|
588 |
+
}
|
589 |
+
|
590 |
+
/**
|
591 |
+
* Get the stream context options available to the current stream
|
592 |
+
*
|
593 |
+
* @param bool $removeContextData Set to true to remove contextual kvp's
|
594 |
+
* like 'client' from the result.
|
595 |
+
*
|
596 |
+
* @return array
|
597 |
+
*/
|
598 |
+
private function getOptions($removeContextData = false)
|
599 |
+
{
|
600 |
+
// Context is not set when doing things like stat
|
601 |
+
if ($this->context === null) {
|
602 |
+
$options = [];
|
603 |
+
} else {
|
604 |
+
$options = stream_context_get_options($this->context);
|
605 |
+
$options = isset($options[$this->protocol])
|
606 |
+
? $options[$this->protocol]
|
607 |
+
: [];
|
608 |
+
}
|
609 |
+
|
610 |
+
$default = stream_context_get_options(stream_context_get_default());
|
611 |
+
$default = isset($default[$this->protocol])
|
612 |
+
? $default[$this->protocol]
|
613 |
+
: [];
|
614 |
+
$result = $this->params + $options + $default;
|
615 |
+
|
616 |
+
if ($removeContextData) {
|
617 |
+
unset($result['client'], $result['seekable'], $result['cache']);
|
618 |
+
}
|
619 |
+
|
620 |
+
return $result;
|
621 |
+
}
|
622 |
+
|
623 |
+
/**
|
624 |
+
* Get a specific stream context option
|
625 |
+
*
|
626 |
+
* @param string $name Name of the option to retrieve
|
627 |
+
*
|
628 |
+
* @return mixed|null
|
629 |
+
*/
|
630 |
+
private function getOption($name)
|
631 |
+
{
|
632 |
+
$options = $this->getOptions();
|
633 |
+
|
634 |
+
return isset($options[$name]) ? $options[$name] : null;
|
635 |
+
}
|
636 |
+
|
637 |
+
/**
|
638 |
+
* Gets the client from the stream context
|
639 |
+
*
|
640 |
+
* @return S3Client
|
641 |
+
* @throws \RuntimeException if no client has been configured
|
642 |
+
*/
|
643 |
+
private function getClient()
|
644 |
+
{
|
645 |
+
if (!$client = $this->getOption('client')) {
|
646 |
+
throw new \RuntimeException('No client in stream context');
|
647 |
+
}
|
648 |
+
|
649 |
+
return $client;
|
650 |
+
}
|
651 |
+
|
652 |
+
private function getBucketKey($path)
|
653 |
+
{
|
654 |
+
// Remove the protocol
|
655 |
+
$parts = explode('://', $path);
|
656 |
+
// Get the bucket, key
|
657 |
+
$parts = explode('/', $parts[1], 2);
|
658 |
+
|
659 |
+
return [
|
660 |
+
'Bucket' => $parts[0],
|
661 |
+
'Key' => isset($parts[1]) ? $parts[1] : null
|
662 |
+
];
|
663 |
+
}
|
664 |
+
|
665 |
+
/**
|
666 |
+
* Get the bucket and key from the passed path (e.g. s3://bucket/key)
|
667 |
+
*
|
668 |
+
* @param string $path Path passed to the stream wrapper
|
669 |
+
*
|
670 |
+
* @return array Hash of 'Bucket', 'Key', and custom params from the context
|
671 |
+
*/
|
672 |
+
private function withPath($path)
|
673 |
+
{
|
674 |
+
$params = $this->getOptions(true);
|
675 |
+
|
676 |
+
return $this->getBucketKey($path) + $params;
|
677 |
+
}
|
678 |
+
|
679 |
+
private function openReadStream()
|
680 |
+
{
|
681 |
+
$client = $this->getClient();
|
682 |
+
$command = $client->getCommand('GetObject', $this->getOptions(true));
|
683 |
+
$command['@http']['stream'] = true;
|
684 |
+
$result = $client->execute($command);
|
685 |
+
$this->size = $result['ContentLength'];
|
686 |
+
$this->body = $result['Body'];
|
687 |
+
|
688 |
+
// Wrap the body in a caching entity body if seeking is allowed
|
689 |
+
if ($this->getOption('seekable') && !$this->body->isSeekable()) {
|
690 |
+
$this->body = new CachingStream($this->body);
|
691 |
+
}
|
692 |
+
|
693 |
+
return true;
|
694 |
+
}
|
695 |
+
|
696 |
+
private function openWriteStream()
|
697 |
+
{
|
698 |
+
$this->body = new Stream(fopen('php://temp', 'r+'));
|
699 |
+
return true;
|
700 |
+
}
|
701 |
+
|
702 |
+
private function openAppendStream()
|
703 |
+
{
|
704 |
+
try {
|
705 |
+
// Get the body of the object and seek to the end of the stream
|
706 |
+
$client = $this->getClient();
|
707 |
+
$this->body = $client->getObject($this->getOptions(true))['Body'];
|
708 |
+
$this->body->seek(0, SEEK_END);
|
709 |
+
return true;
|
710 |
+
} catch (S3Exception $e) {
|
711 |
+
// The object does not exist, so use a simple write stream
|
712 |
+
return $this->openWriteStream();
|
713 |
+
}
|
714 |
+
}
|
715 |
+
|
716 |
+
/**
|
717 |
+
* Trigger one or more errors
|
718 |
+
*
|
719 |
+
* @param string|array $errors Errors to trigger
|
720 |
+
* @param mixed $flags If set to STREAM_URL_STAT_QUIET, then no
|
721 |
+
* error or exception occurs
|
722 |
+
*
|
723 |
+
* @return bool Returns false
|
724 |
+
* @throws \RuntimeException if throw_errors is true
|
725 |
+
*/
|
726 |
+
private function triggerError($errors, $flags = null)
|
727 |
+
{
|
728 |
+
// This is triggered with things like file_exists()
|
729 |
+
if ($flags & STREAM_URL_STAT_QUIET) {
|
730 |
+
return $flags & STREAM_URL_STAT_LINK
|
731 |
+
// This is triggered for things like is_link()
|
732 |
+
? $this->formatUrlStat(false)
|
733 |
+
: false;
|
734 |
+
}
|
735 |
+
|
736 |
+
// This is triggered when doing things like lstat() or stat()
|
737 |
+
trigger_error(implode("\n", (array) $errors), E_USER_WARNING);
|
738 |
+
|
739 |
+
return false;
|
740 |
+
}
|
741 |
+
|
742 |
+
/**
|
743 |
+
* Prepare a url_stat result array
|
744 |
+
*
|
745 |
+
* @param string|array $result Data to add
|
746 |
+
*
|
747 |
+
* @return array Returns the modified url_stat result
|
748 |
+
*/
|
749 |
+
private function formatUrlStat($result = null)
|
750 |
+
{
|
751 |
+
$stat = $this->getStatTemplate();
|
752 |
+
switch (gettype($result)) {
|
753 |
+
case 'NULL':
|
754 |
+
case 'string':
|
755 |
+
// Directory with 0777 access - see "man 2 stat".
|
756 |
+
$stat['mode'] = $stat[2] = 0040777;
|
757 |
+
break;
|
758 |
+
case 'array':
|
759 |
+
// Regular file with 0777 access - see "man 2 stat".
|
760 |
+
$stat['mode'] = $stat[2] = 0100777;
|
761 |
+
// Pluck the content-length if available.
|
762 |
+
if (isset($result['ContentLength'])) {
|
763 |
+
$stat['size'] = $stat[7] = $result['ContentLength'];
|
764 |
+
} elseif (isset($result['Size'])) {
|
765 |
+
$stat['size'] = $stat[7] = $result['Size'];
|
766 |
+
}
|
767 |
+
if (isset($result['LastModified'])) {
|
768 |
+
// ListObjects or HeadObject result
|
769 |
+
$stat['mtime'] = $stat[9] = $stat['ctime'] = $stat[10]
|
770 |
+
= strtotime($result['LastModified']);
|
771 |
+
}
|
772 |
+
}
|
773 |
+
|
774 |
+
return $stat;
|
775 |
+
}
|
776 |
+
|
777 |
+
/**
|
778 |
+
* Creates a bucket for the given parameters.
|
779 |
+
*
|
780 |
+
* @param string $path Stream wrapper path
|
781 |
+
* @param array $params A result of StreamWrapper::withPath()
|
782 |
+
*
|
783 |
+
* @return bool Returns true on success or false on failure
|
784 |
+
*/
|
785 |
+
private function createBucket($path, array $params)
|
786 |
+
{
|
787 |
+
if ($this->getClient()->doesBucketExist($params['Bucket'])) {
|
788 |
+
return $this->triggerError("Bucket already exists: {$path}");
|
789 |
+
}
|
790 |
+
|
791 |
+
return $this->boolCall(function () use ($params, $path) {
|
792 |
+
$this->getClient()->createBucket($params);
|
793 |
+
$this->clearCacheKey($path);
|
794 |
+
return true;
|
795 |
+
});
|
796 |
+
}
|
797 |
+
|
798 |
+
/**
|
799 |
+
* Creates a pseudo-folder by creating an empty "/" suffixed key
|
800 |
+
*
|
801 |
+
* @param string $path Stream wrapper path
|
802 |
+
* @param array $params A result of StreamWrapper::withPath()
|
803 |
+
*
|
804 |
+
* @return bool
|
805 |
+
*/
|
806 |
+
private function createSubfolder($path, array $params)
|
807 |
+
{
|
808 |
+
// Ensure the path ends in "/" and the body is empty.
|
809 |
+
$params['Key'] = rtrim($params['Key'], '/') . '/';
|
810 |
+
$params['Body'] = '';
|
811 |
+
|
812 |
+
// Fail if this pseudo directory key already exists
|
813 |
+
if ($this->getClient()->doesObjectExist(
|
814 |
+
$params['Bucket'],
|
815 |
+
$params['Key'])
|
816 |
+
) {
|
817 |
+
return $this->triggerError("Subfolder already exists: {$path}");
|
818 |
+
}
|
819 |
+
|
820 |
+
return $this->boolCall(function () use ($params, $path) {
|
821 |
+
$this->getClient()->putObject($params);
|
822 |
+
$this->clearCacheKey($path);
|
823 |
+
return true;
|
824 |
+
});
|
825 |
+
}
|
826 |
+
|
827 |
+
/**
|
828 |
+
* Deletes a nested subfolder if it is empty.
|
829 |
+
*
|
830 |
+
* @param string $path Path that is being deleted (e.g., 's3://a/b/c')
|
831 |
+
* @param array $params A result of StreamWrapper::withPath()
|
832 |
+
*
|
833 |
+
* @return bool
|
834 |
+
*/
|
835 |
+
private function deleteSubfolder($path, $params)
|
836 |
+
{
|
837 |
+
// Use a key that adds a trailing slash if needed.
|
838 |
+
$prefix = rtrim($params['Key'], '/') . '/';
|
839 |
+
$result = $this->getClient()->listObjects([
|
840 |
+
'Bucket' => $params['Bucket'],
|
841 |
+
'Prefix' => $prefix,
|
842 |
+
'MaxKeys' => 1
|
843 |
+
]);
|
844 |
+
|
845 |
+
// Check if the bucket contains keys other than the placeholder
|
846 |
+
if ($contents = $result['Contents']) {
|
847 |
+
return (count($contents) > 1 || $contents[0]['Key'] != $prefix)
|
848 |
+
? $this->triggerError('Subfolder is not empty')
|
849 |
+
: $this->unlink(rtrim($path, '/') . '/');
|
850 |
+
}
|
851 |
+
|
852 |
+
return $result['CommonPrefixes']
|
853 |
+
? $this->triggerError('Subfolder contains nested folders')
|
854 |
+
: true;
|
855 |
+
}
|
856 |
+
|
857 |
+
/**
|
858 |
+
* Determine the most appropriate ACL based on a file mode.
|
859 |
+
*
|
860 |
+
* @param int $mode File mode
|
861 |
+
*
|
862 |
+
* @return string
|
863 |
+
*/
|
864 |
+
private function determineAcl($mode)
|
865 |
+
{
|
866 |
+
switch (substr(decoct($mode), 0, 1)) {
|
867 |
+
case '7': return 'public-read';
|
868 |
+
case '6': return 'authenticated-read';
|
869 |
+
default: return 'private';
|
870 |
+
}
|
871 |
+
}
|
872 |
+
|
873 |
+
/**
|
874 |
+
* Gets a URL stat template with default values
|
875 |
+
*
|
876 |
+
* @return array
|
877 |
+
*/
|
878 |
+
private function getStatTemplate()
|
879 |
+
{
|
880 |
+
return [
|
881 |
+
0 => 0, 'dev' => 0,
|
882 |
+
1 => 0, 'ino' => 0,
|
883 |
+
2 => 0, 'mode' => 0,
|
884 |
+
3 => 0, 'nlink' => 0,
|
885 |
+
4 => 0, 'uid' => 0,
|
886 |
+
5 => 0, 'gid' => 0,
|
887 |
+
6 => -1, 'rdev' => -1,
|
888 |
+
7 => 0, 'size' => 0,
|
889 |
+
8 => 0, 'atime' => 0,
|
890 |
+
9 => 0, 'mtime' => 0,
|
891 |
+
10 => 0, 'ctime' => 0,
|
892 |
+
11 => -1, 'blksize' => -1,
|
893 |
+
12 => -1, 'blocks' => -1,
|
894 |
+
];
|
895 |
+
}
|
896 |
+
|
897 |
+
/**
|
898 |
+
* Invokes a callable and triggers an error if an exception occurs while
|
899 |
+
* calling the function.
|
900 |
+
*
|
901 |
+
* @param callable $fn
|
902 |
+
* @param int $flags
|
903 |
+
*
|
904 |
+
* @return bool
|
905 |
+
*/
|
906 |
+
private function boolCall(callable $fn, $flags = null)
|
907 |
+
{
|
908 |
+
try {
|
909 |
+
return $fn();
|
910 |
+
} catch (\Exception $e) {
|
911 |
+
return $this->triggerError($e->getMessage(), $flags);
|
912 |
+
}
|
913 |
+
}
|
914 |
+
|
915 |
+
/**
|
916 |
+
* @return LruArrayCache
|
917 |
+
*/
|
918 |
+
private function getCacheStorage()
|
919 |
+
{
|
920 |
+
if (!$this->cache) {
|
921 |
+
$this->cache = $this->getOption('cache') ?: new LruArrayCache();
|
922 |
+
}
|
923 |
+
|
924 |
+
return $this->cache;
|
925 |
+
}
|
926 |
+
|
927 |
+
/**
|
928 |
+
* Clears a specific stat cache value from the stat cache and LRU cache.
|
929 |
+
*
|
930 |
+
* @param string $key S3 path (s3://bucket/key).
|
931 |
+
*/
|
932 |
+
private function clearCacheKey($key)
|
933 |
+
{
|
934 |
+
clearstatcache(true, $key);
|
935 |
+
$this->getCacheStorage()->remove($key);
|
936 |
+
}
|
937 |
+
|
938 |
+
/**
|
939 |
+
* Returns the size of the opened object body.
|
940 |
+
*
|
941 |
+
* @return int|null
|
942 |
+
*/
|
943 |
+
private function getSize()
|
944 |
+
{
|
945 |
+
$size = $this->body->getSize();
|
946 |
+
|
947 |
+
return $size !== null ? $size : $this->size;
|
948 |
+
}
|
949 |
+
}
|
includes/aws/Aws/S3/Transfer.php
ADDED
@@ -0,0 +1,379 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\S3;
|
3 |
+
|
4 |
+
use Aws;
|
5 |
+
use Aws\CommandInterface;
|
6 |
+
use Aws\ResultInterface;
|
7 |
+
use GuzzleHttp\Promise;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Transfers files from the local filesystem to S3 or from S3 to the local
|
13 |
+
* filesystem.
|
14 |
+
*
|
15 |
+
* This class does not support copying from the local filesystem to somewhere
|
16 |
+
* else on the local filesystem or from one S3 bucket to another.
|
17 |
+
*/
|
18 |
+
class Transfer implements PromisorInterface
|
19 |
+
{
|
20 |
+
private $client;
|
21 |
+
private $promise;
|
22 |
+
private $source;
|
23 |
+
private $destination;
|
24 |
+
private $concurrency;
|
25 |
+
private $mupThreshold;
|
26 |
+
private $before;
|
27 |
+
private $s3Args = [];
|
28 |
+
|
29 |
+
/**
|
30 |
+
* When providing the $source argument, you may provide a string referencing
|
31 |
+
* the path to a directory on disk to upload, an s3 scheme URI that contains
|
32 |
+
* the bucket and key (e.g., "s3://bucket/key"), or an \Iterator object
|
33 |
+
* that yields strings containing filenames that are the path to a file on
|
34 |
+
* disk or an s3 scheme URI. The "/key" portion of an s3 URI is optional.
|
35 |
+
*
|
36 |
+
* When providing an iterator for the $source argument, you must also
|
37 |
+
* provide a 'base_dir' key value pair in the $options argument.
|
38 |
+
*
|
39 |
+
* The $dest argument can be the path to a directory on disk or an s3
|
40 |
+
* scheme URI (e.g., "s3://bucket/key").
|
41 |
+
*
|
42 |
+
* The options array can contain the following key value pairs:
|
43 |
+
*
|
44 |
+
* - base_dir: (string) Base directory of the source, if $source is an
|
45 |
+
* iterator. If the $source option is not an array, then this option is
|
46 |
+
* ignored.
|
47 |
+
* - before: (callable) A callback to invoke before each transfer. The
|
48 |
+
* callback accepts the following positional arguments: string $source,
|
49 |
+
* string $dest, Aws\CommandInterface $command. The provided command will
|
50 |
+
* be either a GetObject, PutObject, InitiateMultipartUpload, or
|
51 |
+
* UploadPart command.
|
52 |
+
* - mup_threshold: (int) Size in bytes in which a multipart upload should
|
53 |
+
* be used instead of PutObject. Defaults to 20971520 (20 MB).
|
54 |
+
* - concurrency: (int, default=5) Number of files to upload concurrently.
|
55 |
+
* The ideal concurrency value will vary based on the number of files
|
56 |
+
* being uploaded and the average size of each file. Generally speaking,
|
57 |
+
* smaller files benefit from a higher concurrency while larger files
|
58 |
+
* will not.
|
59 |
+
* - debug: (bool) Set to true to print out debug information for
|
60 |
+
* transfers. Set to an fopen() resource to write to a specific stream
|
61 |
+
* rather than writing to STDOUT.
|
62 |
+
*
|
63 |
+
* @param S3Client $client Client used for transfers.
|
64 |
+
* @param string|\Iterator $source Where the files are transferred from.
|
65 |
+
* @param string $dest Where the files are transferred to.
|
66 |
+
* @param array $options Hash of options.
|
67 |
+
*/
|
68 |
+
public function __construct(
|
69 |
+
S3Client $client,
|
70 |
+
$source,
|
71 |
+
$dest,
|
72 |
+
array $options = []
|
73 |
+
) {
|
74 |
+
$this->client = $client;
|
75 |
+
|
76 |
+
// Prepare the destination.
|
77 |
+
$this->destination = $this->prepareTarget($dest);
|
78 |
+
if ($this->destination['scheme'] === 's3') {
|
79 |
+
$this->s3Args = $this->getS3Args($this->destination['path']);
|
80 |
+
}
|
81 |
+
|
82 |
+
// Prepare the source.
|
83 |
+
if (is_string($source)) {
|
84 |
+
$this->source = $this->prepareTarget($source);
|
85 |
+
} elseif ($source instanceof \Iterator) {
|
86 |
+
if (isset($options['base_dir'])) {
|
87 |
+
$this->source = $this->prepareTarget($options['base_dir']);
|
88 |
+
} else {
|
89 |
+
throw new \InvalidArgumentException('You must provide the source'
|
90 |
+
. ' argument as a string or provide the "base_dir" option.');
|
91 |
+
}
|
92 |
+
} else {
|
93 |
+
throw new \InvalidArgumentException('source must be the path to a '
|
94 |
+
. 'directory or an iterator that yields file names.');
|
95 |
+
}
|
96 |
+
|
97 |
+
// Validate schemes.
|
98 |
+
if ($this->source['scheme'] === $this->destination['scheme']) {
|
99 |
+
throw new \InvalidArgumentException("You cannot copy from "
|
100 |
+
. "{$this->source['scheme']} to {$this->destination['scheme']}."
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
// Handle multipart-related options.
|
105 |
+
$this->concurrency = isset($options['concurrency'])
|
106 |
+
? $options['concurrency']
|
107 |
+
: MultipartUploader::DEFAULT_CONCURRENCY;
|
108 |
+
$this->mupThreshold = isset($options['mup_threshold'])
|
109 |
+
? $options['mup_threshold']
|
110 |
+
: 16777216;
|
111 |
+
if ($this->mupThreshold < MultipartUploader::PART_MIN_SIZE) {
|
112 |
+
throw new \InvalidArgumentException('mup_threshold must be >= 5MB');
|
113 |
+
}
|
114 |
+
|
115 |
+
// Handle "before" callback option.
|
116 |
+
if (isset($options['before'])) {
|
117 |
+
$this->before = $options['before'];
|
118 |
+
if (!is_callable($this->before)) {
|
119 |
+
throw new \InvalidArgumentException('before must be a callable.');
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
// Handle "debug" option.
|
124 |
+
if (isset($options['debug'])) {
|
125 |
+
if ($options['debug'] === true) {
|
126 |
+
$options['debug'] = fopen('php://output', 'w');
|
127 |
+
}
|
128 |
+
$this->addDebugToBefore($options['debug']);
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Transfers the files.
|
134 |
+
*/
|
135 |
+
public function promise()
|
136 |
+
{
|
137 |
+
// If the promise has been created, just return it.
|
138 |
+
if (!$this->promise) {
|
139 |
+
// Create an upload/download promise for the transfer.
|
140 |
+
$this->promise = $this->source['scheme'] === 'file'
|
141 |
+
? $this->createUploadPromise()
|
142 |
+
: $this->createDownloadPromise();
|
143 |
+
}
|
144 |
+
|
145 |
+
return $this->promise;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Transfers the files synchronously.
|
150 |
+
*/
|
151 |
+
public function transfer()
|
152 |
+
{
|
153 |
+
$this->promise()->wait();
|
154 |
+
}
|
155 |
+
|
156 |
+
private function prepareTarget($targetPath)
|
157 |
+
{
|
158 |
+
$target = [
|
159 |
+
'path' => $this->normalizePath($targetPath),
|
160 |
+
'scheme' => $this->determineScheme($targetPath),
|
161 |
+
];
|
162 |
+
|
163 |
+
if ($target['scheme'] !== 's3' && $target['scheme'] !== 'file') {
|
164 |
+
throw new \InvalidArgumentException('Scheme must be "s3" or "file".');
|
165 |
+
}
|
166 |
+
|
167 |
+
return $target;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Creates an array that contains Bucket and Key by parsing the filename.
|
172 |
+
*
|
173 |
+
* @param string $path Path to parse.
|
174 |
+
*
|
175 |
+
* @return array
|
176 |
+
*/
|
177 |
+
private function getS3Args($path)
|
178 |
+
{
|
179 |
+
$parts = explode('/', str_replace('s3://', '', $path), 2);
|
180 |
+
$args = ['Bucket' => $parts[0]];
|
181 |
+
if (isset($parts[1])) {
|
182 |
+
$args['Key'] = $parts[1];
|
183 |
+
}
|
184 |
+
|
185 |
+
return $args;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Parses the scheme from a filename.
|
190 |
+
*
|
191 |
+
* @param string $path Path to parse.
|
192 |
+
*
|
193 |
+
* @return string
|
194 |
+
*/
|
195 |
+
private function determineScheme($path)
|
196 |
+
{
|
197 |
+
return !strpos($path, '://') ? 'file' : explode('://', $path)[0];
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Normalize a path so that it has UNIX-style directory separators and no trailing /
|
202 |
+
*
|
203 |
+
* @param string $path
|
204 |
+
*
|
205 |
+
* @return string
|
206 |
+
*/
|
207 |
+
private function normalizePath($path)
|
208 |
+
{
|
209 |
+
return rtrim(str_replace('\\', '/', $path), '/');
|
210 |
+
}
|
211 |
+
|
212 |
+
private function createDownloadPromise()
|
213 |
+
{
|
214 |
+
// Prepare args for ListObjects.
|
215 |
+
$listArgs = $this->getS3Args($this->source['path']);
|
216 |
+
if (isset($listArgs['Key'])) {
|
217 |
+
$listArgs['Prefix'] = $listArgs['Key'] . '/';
|
218 |
+
unset($listArgs['Key']);
|
219 |
+
}
|
220 |
+
|
221 |
+
// Get the Paginator for ListObjects
|
222 |
+
$objects = $this->client->getPaginator('ListObjects', $listArgs);
|
223 |
+
|
224 |
+
// Asynchronously execute the paginator, building command pools to
|
225 |
+
// download the objects.
|
226 |
+
return $objects->each(function (
|
227 |
+
ResultInterface $result
|
228 |
+
) use ($listArgs) {
|
229 |
+
$commands = [];
|
230 |
+
$prefix = isset($listArgs['Prefix']) ? $listArgs['Prefix'] : null;
|
231 |
+
foreach ($result->search('Contents[].Key') as $key) {
|
232 |
+
// Skip files on S3 that just mark the existence of a folder.
|
233 |
+
if (substr($key, -1, 1) === '/') {
|
234 |
+
continue;
|
235 |
+
}
|
236 |
+
|
237 |
+
// Prepare the sink.
|
238 |
+
$localKey = $key;
|
239 |
+
if ($prefix && strpos($localKey, $prefix) === 0) {
|
240 |
+
$localKey = substr($key, strlen($prefix));
|
241 |
+
}
|
242 |
+
$sink = $this->destination['path'] . '/' . $localKey;
|
243 |
+
|
244 |
+
// Create the directory if needed.
|
245 |
+
$dir = dirname($sink);
|
246 |
+
if (!is_dir($dir) && !mkdir($dir, 0777, true)) {
|
247 |
+
return Promise\rejection_for(
|
248 |
+
new \RuntimeException("Could not create dir: {$dir}")
|
249 |
+
);
|
250 |
+
}
|
251 |
+
|
252 |
+
// Create the command.
|
253 |
+
$commands[] = $this->client->getCommand('GetObject', [
|
254 |
+
'Bucket' => $listArgs['Bucket'],
|
255 |
+
'Key' => $key,
|
256 |
+
'@http' => ['sink' => $sink],
|
257 |
+
]);
|
258 |
+
}
|
259 |
+
|
260 |
+
// Create a GetObject command pool and return the promise.
|
261 |
+
return (new Aws\CommandPool($this->client, $commands, [
|
262 |
+
'concurrency' => $this->concurrency,
|
263 |
+
'before' => $this->before,
|
264 |
+
'rejected' => function ($reason, $idx, Promise\PromiseInterface $p) {
|
265 |
+
$p->reject($reason);
|
266 |
+
}
|
267 |
+
]))->promise();
|
268 |
+
});
|
269 |
+
}
|
270 |
+
|
271 |
+
private function createUploadPromise()
|
272 |
+
{
|
273 |
+
// Creates an iterator that yields promises for either upload or
|
274 |
+
// multipart upload operations for each file in the source directory.
|
275 |
+
$files = Aws\recursive_dir_iterator($this->source['path']);
|
276 |
+
// Filter out directories.
|
277 |
+
$files = \Aws\filter($files, function ($file) {
|
278 |
+
return !is_dir($file);
|
279 |
+
});
|
280 |
+
// Map each file into a promise that performs the actual transfer.
|
281 |
+
$files = \Aws\map($files, function ($file) {
|
282 |
+
return (filesize($file) >= $this->mupThreshold)
|
283 |
+
? $this->uploadMultipart($file)
|
284 |
+
: $this->upload($file);
|
285 |
+
});
|
286 |
+
|
287 |
+
// Create an EachPromise, that will concurrently handle the upload
|
288 |
+
// operations' yielded promises from the iterator.
|
289 |
+
return Promise\each_limit_all($files, $this->concurrency);
|
290 |
+
}
|
291 |
+
|
292 |
+
private function upload($filename)
|
293 |
+
{
|
294 |
+
$args = $this->s3Args;
|
295 |
+
$args['SourceFile'] = $filename;
|
296 |
+
$args['Key'] = $this->createS3Key($filename);
|
297 |
+
$command = $this->client->getCommand('PutObject', $args);
|
298 |
+
$this->before and call_user_func($this->before, $command);
|
299 |
+
|
300 |
+
return $this->client->executeAsync($command);
|
301 |
+
}
|
302 |
+
|
303 |
+
private function uploadMultipart($filename)
|
304 |
+
{
|
305 |
+
$args = $this->s3Args;
|
306 |
+
$args['Key'] = $this->createS3Key($filename);
|
307 |
+
|
308 |
+
return (new MultipartUploader($this->client, $filename, [
|
309 |
+
'bucket' => $args['Bucket'],
|
310 |
+
'key' => $args['Key'],
|
311 |
+
'before_initiate' => $this->before,
|
312 |
+
'before_upload' => $this->before,
|
313 |
+
'before_complete' => $this->before,
|
314 |
+
'concurrency' => $this->concurrency,
|
315 |
+
]))->promise();
|
316 |
+
}
|
317 |
+
|
318 |
+
private function createS3Key($filename)
|
319 |
+
{
|
320 |
+
$relative_file_path = ltrim(
|
321 |
+
preg_replace('#^' . preg_quote($this->source['path']) . '#', '', $filename),
|
322 |
+
'/\\'
|
323 |
+
);
|
324 |
+
|
325 |
+
if (isset($this->s3Args['Key'])) {
|
326 |
+
return rtrim($this->s3Args['Key'], '/').'/'.$relative_file_path;
|
327 |
+
}
|
328 |
+
|
329 |
+
return $relative_file_path;
|
330 |
+
}
|
331 |
+
|
332 |
+
private function addDebugToBefore($debug)
|
333 |
+
{
|
334 |
+
$before = $this->before;
|
335 |
+
$sourcePath = $this->source['path'];
|
336 |
+
$s3Args = $this->s3Args;
|
337 |
+
|
338 |
+
$this->before = static function (
|
339 |
+
CommandInterface $command
|
340 |
+
) use ($before, $debug, $sourcePath, $s3Args) {
|
341 |
+
// Call the composed before function.
|
342 |
+
$before and $before($command);
|
343 |
+
|
344 |
+
// Determine the source and dest values based on operation.
|
345 |
+
switch ($operation = $command->getName()) {
|
346 |
+
case 'GetObject':
|
347 |
+
$source = "s3://{$command['Bucket']}/{$command['Key']}";
|
348 |
+
$dest = $command['@http']['sink'];
|
349 |
+
break;
|
350 |
+
case 'PutObject':
|
351 |
+
$source = $command['SourceFile'];
|
352 |
+
$dest = "s3://{$command['Bucket']}/{$command['Key']}";
|
353 |
+
break;
|
354 |
+
case 'UploadPart':
|
355 |
+
$part = $command['PartNumber'];
|
356 |
+
case 'CreateMultipartUpload':
|
357 |
+
case 'CompleteMultipartUpload':
|
358 |
+
$sourceKey = $command['Key'];
|
359 |
+
if (isset($s3Args['Key']) && strpos($sourceKey, $s3Args['Key']) === 0) {
|
360 |
+
$sourceKey = substr($sourceKey, strlen($s3Args['Key']) + 1);
|
361 |
+
}
|
362 |
+
$source = "{$sourcePath}/{$sourceKey}";
|
363 |
+
$dest = "s3://{$command['Bucket']}/{$command['Key']}";
|
364 |
+
break;
|
365 |
+
default:
|
366 |
+
throw new \UnexpectedValueException(
|
367 |
+
"Transfer encountered an unexpected operation: {$operation}."
|
368 |
+
);
|
369 |
+
}
|
370 |
+
|
371 |
+
// Print the debugging message.
|
372 |
+
$context = sprintf('%s -> %s (%s)', $source, $dest, $operation);
|
373 |
+
if (isset($part)) {
|
374 |
+
$context .= " : Part={$part}";
|
375 |
+
}
|
376 |
+
fwrite($debug, "Transferring {$context}\n");
|
377 |
+
};
|
378 |
+
}
|
379 |
+
}
|
includes/aws/Aws/Sdk.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Builds AWS clients based on configuration settings.
|
6 |
+
*
|
7 |
+
* @method \Aws\ApiGateway\ApiGatewayClient createApiGateway(array $args = [])
|
8 |
+
* @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
|
9 |
+
* @method \Aws\CloudFormation\CloudFormationClient createCloudFormation(array $args = [])
|
10 |
+
* @method \Aws\CloudFront\CloudFrontClient createCloudFront(array $args = [])
|
11 |
+
* @method \Aws\CloudHsm\CloudHsmClient createCloudHsm(array $args = [])
|
12 |
+
* @method \Aws\CloudSearch\CloudSearchClient createCloudSearch(array $args = [])
|
13 |
+
* @method \Aws\CloudSearchDomain\CloudSearchDomainClient createCloudSearchDomain(array $args = [])
|
14 |
+
* @method \Aws\CloudTrail\CloudTrailClient createCloudTrail(array $args = [])
|
15 |
+
* @method \Aws\CloudWatch\CloudWatchClient createCloudWatch(array $args = [])
|
16 |
+
* @method \Aws\CloudWatchLogs\CloudWatchLogsClient createCloudWatchLogs(array $args = [])
|
17 |
+
* @method \Aws\CodeCommit\CodeCommitClient createCodeCommit(array $args = [])
|
18 |
+
* @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
|
19 |
+
* @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
|
20 |
+
* @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
|
21 |
+
* @method \Aws\CognitoSync\CognitoSyncClient createCognitoSync(array $args = [])
|
22 |
+
* @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
|
23 |
+
* @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
|
24 |
+
* @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
|
25 |
+
* @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
|
26 |
+
* @method \Aws\DirectoryService\DirectoryServiceClient createDirectoryService(array $args = [])
|
27 |
+
* @method \Aws\DynamoDb\DynamoDbClient createDynamoDb(array $args = [])
|
28 |
+
* @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
|
29 |
+
* @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
|
30 |
+
* @method \Aws\Ecr\EcrClient createEcr(array $args = [])
|
31 |
+
* @method \Aws\Ecs\EcsClient createEcs(array $args = [])
|
32 |
+
* @method \Aws\Efs\EfsClient createEfs(array $args = [])
|
33 |
+
* @method \Aws\ElastiCache\ElastiCacheClient createElastiCache(array $args = [])
|
34 |
+
* @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
|
35 |
+
* @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
|
36 |
+
* @method \Aws\ElasticTranscoder\ElasticTranscoderClient createElasticTranscoder(array $args = [])
|
37 |
+
* @method \Aws\ElasticsearchService\ElasticsearchServiceClient createElasticsearchService(array $args = [])
|
38 |
+
* @method \Aws\Emr\EmrClient createEmr(array $args = [])
|
39 |
+
* @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
|
40 |
+
* @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
|
41 |
+
* @method \Aws\Iam\IamClient createIam(array $args = [])
|
42 |
+
* @method \Aws\Inspector\InspectorClient createInspector(array $args = [])
|
43 |
+
* @method \Aws\Iot\IotClient createIot(array $args = [])
|
44 |
+
* @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
|
45 |
+
* @method \Aws\Kinesis\KinesisClient createKinesis(array $args = [])
|
46 |
+
* @method \Aws\Kms\KmsClient createKms(array $args = [])
|
47 |
+
* @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
|
48 |
+
* @method \Aws\MachineLearning\MachineLearningClient createMachineLearning(array $args = [])
|
49 |
+
* @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
|
50 |
+
* @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
|
51 |
+
* @method \Aws\Rds\RdsClient createRds(array $args = [])
|
52 |
+
* @method \Aws\Redshift\RedshiftClient createRedshift(array $args = [])
|
53 |
+
* @method \Aws\Route53\Route53Client createRoute53(array $args = [])
|
54 |
+
* @method \Aws\Route53Domains\Route53DomainsClient createRoute53Domains(array $args = [])
|
55 |
+
* @method \Aws\S3\S3Client createS3(array $args = [])
|
56 |
+
* @method \Aws\Ses\SesClient createSes(array $args = [])
|
57 |
+
* @method \Aws\Sns\SnsClient createSns(array $args = [])
|
58 |
+
* @method \Aws\Sqs\SqsClient createSqs(array $args = [])
|
59 |
+
* @method \Aws\Ssm\SsmClient createSsm(array $args = [])
|
60 |
+
* @method \Aws\StorageGateway\StorageGatewayClient createStorageGateway(array $args = [])
|
61 |
+
* @method \Aws\Sts\StsClient createSts(array $args = [])
|
62 |
+
* @method \Aws\Support\SupportClient createSupport(array $args = [])
|
63 |
+
* @method \Aws\Swf\SwfClient createSwf(array $args = [])
|
64 |
+
* @method \Aws\Waf\WafClient createWaf(array $args = [])
|
65 |
+
* @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
|
66 |
+
*/
|
67 |
+
class Sdk
|
68 |
+
{
|
69 |
+
const VERSION = '3.12.0';
|
70 |
+
|
71 |
+
/** @var array Arguments for creating clients */
|
72 |
+
private $args;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Constructs a new SDK object with an associative array of default
|
76 |
+
* client settings.
|
77 |
+
*
|
78 |
+
* @param array $args
|
79 |
+
*
|
80 |
+
* @throws \InvalidArgumentException
|
81 |
+
* @see Aws\Sdk::getClient for a list of available options.
|
82 |
+
*/
|
83 |
+
public function __construct(array $args = [])
|
84 |
+
{
|
85 |
+
$this->args = $args;
|
86 |
+
|
87 |
+
if (!isset($args['handler']) && !isset($args['http_handler'])) {
|
88 |
+
$this->args['http_handler'] = default_http_handler();
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
public function __call($name, array $args)
|
93 |
+
{
|
94 |
+
if (strpos($name, 'create') === 0) {
|
95 |
+
return $this->createClient(
|
96 |
+
substr($name, 6),
|
97 |
+
isset($args[0]) ? $args[0] : []
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
throw new \BadMethodCallException("Unknown method: {$name}.");
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get a client by name using an array of constructor options.
|
106 |
+
*
|
107 |
+
* @param string $name Service name or namespace (e.g., DynamoDb, s3).
|
108 |
+
* @param array $args Arguments to configure the client.
|
109 |
+
*
|
110 |
+
* @return AwsClientInterface
|
111 |
+
* @throws \InvalidArgumentException if any required options are missing or
|
112 |
+
* the service is not supported.
|
113 |
+
* @see Aws\AwsClient::__construct for a list of available options for args.
|
114 |
+
*/
|
115 |
+
public function createClient($name, array $args = [])
|
116 |
+
{
|
117 |
+
// Get information about the service from the manifest file.
|
118 |
+
$service = manifest($name);
|
119 |
+
$namespace = $service['namespace'];
|
120 |
+
|
121 |
+
// Merge provided args with stored, service-specific args.
|
122 |
+
if (isset($this->args[$namespace])) {
|
123 |
+
$args += $this->args[$namespace];
|
124 |
+
}
|
125 |
+
|
126 |
+
// Provide the endpoint prefix in the args.
|
127 |
+
if (!isset($args['service'])) {
|
128 |
+
$args['service'] = $service['endpoint'];
|
129 |
+
}
|
130 |
+
|
131 |
+
// Instantiate the client class.
|
132 |
+
$client = "Aws\\{$namespace}\\{$namespace}Client";
|
133 |
+
return new $client($args + $this->args);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Determine the endpoint prefix from a client namespace.
|
138 |
+
*
|
139 |
+
* @param string $name Namespace name
|
140 |
+
*
|
141 |
+
* @return string
|
142 |
+
* @internal
|
143 |
+
* @deprecated Use the `\Aws\manifest()` function instead.
|
144 |
+
*/
|
145 |
+
public static function getEndpointPrefix($name)
|
146 |
+
{
|
147 |
+
return manifest($name)['endpoint'];
|
148 |
+
}
|
149 |
+
}
|
includes/aws/Aws/Signature/AnonymousSignature.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Signature;
|
3 |
+
|
4 |
+
use Aws\Credentials\CredentialsInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Provides anonymous client access (does not sign requests).
|
9 |
+
*/
|
10 |
+
class AnonymousSignature implements SignatureInterface
|
11 |
+
{
|
12 |
+
public function signRequest(
|
13 |
+
RequestInterface $request,
|
14 |
+
CredentialsInterface $credentials
|
15 |
+
) {
|
16 |
+
return $request;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function presign(
|
20 |
+
RequestInterface $request,
|
21 |
+
CredentialsInterface $credentials,
|
22 |
+
$expires
|
23 |
+
) {
|
24 |
+
return $request;
|
25 |
+
}
|
26 |
+
}
|
includes/aws/Aws/Signature/S3SignatureV4.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Signature;
|
3 |
+
|
4 |
+
use Aws\Credentials\CredentialsInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Amazon S3 signature version 4 support.
|
9 |
+
*/
|
10 |
+
class S3SignatureV4 extends SignatureV4
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Always add a x-amz-content-sha-256 for data integrity.
|
14 |
+
*/
|
15 |
+
public function signRequest(
|
16 |
+
RequestInterface $request,
|
17 |
+
CredentialsInterface $credentials
|
18 |
+
) {
|
19 |
+
if (!$request->hasHeader('x-amz-content-sha256')) {
|
20 |
+
$request = $request->withHeader(
|
21 |
+
'X-Amz-Content-Sha256',
|
22 |
+
$this->getPayload($request)
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
return parent::signRequest($request, $credentials);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Override used to allow pre-signed URLs to be created for an
|
31 |
+
* in-determinate request payload.
|
32 |
+
*/
|
33 |
+
protected function getPresignedPayload(RequestInterface $request)
|
34 |
+
{
|
35 |
+
return 'UNSIGNED-PAYLOAD';
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Amazon S3 does not double-encode the path component in the canonical request
|
40 |
+
*/
|
41 |
+
protected function createCanonicalizedPath($path)
|
42 |
+
{
|
43 |
+
return '/' . ltrim($path, '/');
|
44 |
+
}
|
45 |
+
}
|
includes/aws/Aws/Signature/SignatureInterface.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Signature;
|
3 |
+
|
4 |
+
use Aws\Credentials\CredentialsInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Interface used to provide interchangeable strategies for signing requests
|
9 |
+
* using the various AWS signature protocols.
|
10 |
+
*/
|
11 |
+
interface SignatureInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Signs the specified request with an AWS signing protocol by using the
|
15 |
+
* provided AWS account credentials and adding the required headers to the
|
16 |
+
* request.
|
17 |
+
*
|
18 |
+
* @param RequestInterface $request Request to sign
|
19 |
+
* @param CredentialsInterface $credentials Signing credentials
|
20 |
+
*
|
21 |
+
* @return RequestInterface Returns the modified request.
|
22 |
+
*/
|
23 |
+
public function signRequest(
|
24 |
+
RequestInterface $request,
|
25 |
+
CredentialsInterface $credentials
|
26 |
+
);
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Create a pre-signed request.
|
30 |
+
*
|
31 |
+
* @param RequestInterface $request Request to sign
|
32 |
+
* @param CredentialsInterface $credentials Credentials used to sign
|
33 |
+
* @param int|string|\DateTime $expires The time at which the URL should
|
34 |
+
* expire. This can be a Unix timestamp, a PHP DateTime object, or a
|
35 |
+
* string that can be evaluated by strtotime.
|
36 |
+
*
|
37 |
+
* @return RequestInterface
|
38 |
+
*/
|
39 |
+
public function presign(
|
40 |
+
RequestInterface $request,
|
41 |
+
CredentialsInterface $credentials,
|
42 |
+
$expires
|
43 |
+
);
|
44 |
+
}
|
includes/aws/Aws/Signature/SignatureProvider.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Signature;
|
3 |
+
|
4 |
+
use Aws\Exception\UnresolvedSignatureException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Signature providers.
|
8 |
+
*
|
9 |
+
* A signature provider is a function that accepts a version, service, and
|
10 |
+
* region and returns a {@see SignatureInterface} object on success or NULL if
|
11 |
+
* no signature can be created from the provided arguments.
|
12 |
+
*
|
13 |
+
* You can wrap your calls to a signature provider with the
|
14 |
+
* {@see SignatureProvider::resolve} function to ensure that a signature object
|
15 |
+
* is created. If a signature object is not created, then the resolve()
|
16 |
+
* function will throw a {@see Aws\Exception\UnresolvedSignatureException}.
|
17 |
+
*
|
18 |
+
* use Aws\Signature\SignatureProvider;
|
19 |
+
* $provider = SignatureProvider::defaultProvider();
|
20 |
+
* // Returns a SignatureInterface or NULL.
|
21 |
+
* $signer = $provider('v4', 's3', 'us-west-2');
|
22 |
+
* // Returns a SignatureInterface or throws.
|
23 |
+
* $signer = SignatureProvider::resolve($provider, 'no', 's3', 'foo');
|
24 |
+
*
|
25 |
+
* You can compose multiple providers into a single provider using
|
26 |
+
* {@see Aws\or_chain}. This function accepts providers as arguments and
|
27 |
+
* returns a new function that will invoke each provider until a non-null value
|
28 |
+
* is returned.
|
29 |
+
*
|
30 |
+
* $a = SignatureProvider::defaultProvider();
|
31 |
+
* $b = function ($version, $service, $region) {
|
32 |
+
* if ($version === 'foo') {
|
33 |
+
* return new MyFooSignature();
|
34 |
+
* }
|
35 |
+
* };
|
36 |
+
* $c = \Aws\or_chain($a, $b);
|
37 |
+
* $signer = $c('v4', 'abc', '123'); // $a handles this.
|
38 |
+
* $signer = $c('foo', 'abc', '123'); // $b handles this.
|
39 |
+
* $nullValue = $c('???', 'abc', '123'); // Neither can handle this.
|
40 |
+
*/
|
41 |
+
class SignatureProvider
|
42 |
+
{
|
43 |
+
/**
|
44 |
+
* Resolves and signature provider and ensures a non-null return value.
|
45 |
+
*
|
46 |
+
* @param callable $provider Provider function to invoke.
|
47 |
+
* @param string $version Signature version.
|
48 |
+
* @param string $service Service name.
|
49 |
+
* @param string $region Region name.
|
50 |
+
*
|
51 |
+
* @return SignatureInterface
|
52 |
+
* @throws UnresolvedSignatureException
|
53 |
+
*/
|
54 |
+
public static function resolve(callable $provider, $version, $service, $region)
|
55 |
+
{
|
56 |
+
$result = $provider($version, $service, $region);
|
57 |
+
if ($result instanceof SignatureInterface) {
|
58 |
+
return $result;
|
59 |
+
}
|
60 |
+
|
61 |
+
throw new UnresolvedSignatureException(
|
62 |
+
"Unable to resolve a signature for $version/$service/$region.\n"
|
63 |
+
. "Valid signature versions include v4 and anonymous."
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Default SDK signature provider.
|
69 |
+
*
|
70 |
+
* @return callable
|
71 |
+
*/
|
72 |
+
public static function defaultProvider()
|
73 |
+
{
|
74 |
+
return self::memoize(self::version());
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Creates a signature provider that caches previously created signature
|
79 |
+
* objects. The computed cache key is the concatenation of the version,
|
80 |
+
* service, and region.
|
81 |
+
*
|
82 |
+
* @param callable $provider Signature provider to wrap.
|
83 |
+
*
|
84 |
+
* @return callable
|
85 |
+
*/
|
86 |
+
public static function memoize(callable $provider)
|
87 |
+
{
|
88 |
+
$cache = [];
|
89 |
+
return function ($version, $service, $region) use (&$cache, $provider) {
|
90 |
+
$key = "($version)($service)($region)";
|
91 |
+
if (!isset($cache[$key])) {
|
92 |
+
$cache[$key] = $provider($version, $service, $region);
|
93 |
+
}
|
94 |
+
return $cache[$key];
|
95 |
+
};
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Creates signature objects from known signature versions.
|
100 |
+
*
|
101 |
+
* This provider currently recognizes the following signature versions:
|
102 |
+
*
|
103 |
+
* - v4: Signature version 4.
|
104 |
+
* - anonymous: Does not sign requests.
|
105 |
+
*
|
106 |
+
* @return callable
|
107 |
+
*/
|
108 |
+
public static function version()
|
109 |
+
{
|
110 |
+
return function ($version, $service, $region) {
|
111 |
+
switch ($version) {
|
112 |
+
case 'v4':
|
113 |
+
return $service === 's3'
|
114 |
+
? new S3SignatureV4($service, $region)
|
115 |
+
: new SignatureV4($service, $region);
|
116 |
+
case 'anonymous':
|
117 |
+
return new AnonymousSignature();
|
118 |
+
default:
|
119 |
+
return null;
|
120 |
+
}
|
121 |
+
};
|
122 |
+
}
|
123 |
+
}
|
includes/aws/Aws/Signature/SignatureV4.php
ADDED
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Signature;
|
3 |
+
|
4 |
+
use Aws\Credentials\CredentialsInterface;
|
5 |
+
use Aws\Exception\CouldNotCreateChecksumException;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Signature Version 4
|
11 |
+
* @link http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
|
12 |
+
*/
|
13 |
+
class SignatureV4 implements SignatureInterface
|
14 |
+
{
|
15 |
+
const ISO8601_BASIC = 'Ymd\THis\Z';
|
16 |
+
|
17 |
+
/** @var string */
|
18 |
+
private $service;
|
19 |
+
|
20 |
+
/** @var string */
|
21 |
+
private $region;
|
22 |
+
|
23 |
+
/** @var array Cache of previously signed values */
|
24 |
+
private $cache = [];
|
25 |
+
|
26 |
+
/** @var int Size of the hash cache */
|
27 |
+
private $cacheSize = 0;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param string $service Service name to use when signing
|
31 |
+
* @param string $region Region name to use when signing
|
32 |
+
*/
|
33 |
+
public function __construct($service, $region)
|
34 |
+
{
|
35 |
+
$this->service = $service;
|
36 |
+
$this->region = $region;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function signRequest(
|
40 |
+
RequestInterface $request,
|
41 |
+
CredentialsInterface $credentials
|
42 |
+
) {
|
43 |
+
$ldt = gmdate(self::ISO8601_BASIC);
|
44 |
+
$sdt = substr($ldt, 0, 8);
|
45 |
+
$parsed = $this->parseRequest($request);
|
46 |
+
$parsed['headers']['X-Amz-Date'] = [$ldt];
|
47 |
+
|
48 |
+
if ($token = $credentials->getSecurityToken()) {
|
49 |
+
$parsed['headers']['X-Amz-Security-Token'] = [$token];
|
50 |
+
}
|
51 |
+
|
52 |
+
$cs = $this->createScope($sdt, $this->region, $this->service);
|
53 |
+
$payload = $this->getPayload($request);
|
54 |
+
$context = $this->createContext($parsed, $payload);
|
55 |
+
$toSign = $this->createStringToSign($ldt, $cs, $context['creq']);
|
56 |
+
$signingKey = $this->getSigningKey(
|
57 |
+
$sdt,
|
58 |
+
$this->region,
|
59 |
+
$this->service,
|
60 |
+
$credentials->getSecretKey()
|
61 |
+
);
|
62 |
+
$signature = hash_hmac('sha256', $toSign, $signingKey);
|
63 |
+
$parsed['headers']['Authorization'] = [
|
64 |
+
"AWS4-HMAC-SHA256 "
|
65 |
+
. "Credential={$credentials->getAccessKeyId()}/{$cs}, "
|
66 |
+
. "SignedHeaders={$context['headers']}, Signature={$signature}"
|
67 |
+
];
|
68 |
+
|
69 |
+
return $this->buildRequest($parsed);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function presign(
|
73 |
+
RequestInterface $request,
|
74 |
+
CredentialsInterface $credentials,
|
75 |
+
$expires
|
76 |
+
) {
|
77 |
+
$parsed = $this->createPresignedRequest($request, $credentials);
|
78 |
+
$payload = $this->getPresignedPayload($request);
|
79 |
+
$httpDate = gmdate(self::ISO8601_BASIC, time());
|
80 |
+
$shortDate = substr($httpDate, 0, 8);
|
81 |
+
$scope = $this->createScope($shortDate, $this->region, $this->service);
|
82 |
+
$credential = $credentials->getAccessKeyId() . '/' . $scope;
|
83 |
+
$parsed['query']['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256';
|
84 |
+
$parsed['query']['X-Amz-Credential'] = $credential;
|
85 |
+
$parsed['query']['X-Amz-Date'] = gmdate('Ymd\THis\Z', time());
|
86 |
+
$parsed['query']['X-Amz-SignedHeaders'] = 'Host';
|
87 |
+
$parsed['query']['X-Amz-Expires'] = $this->convertExpires($expires);
|
88 |
+
$context = $this->createContext($parsed, $payload);
|
89 |
+
$stringToSign = $this->createStringToSign($httpDate, $scope, $context['creq']);
|
90 |
+
$key = $this->getSigningKey(
|
91 |
+
$shortDate,
|
92 |
+
$this->region,
|
93 |
+
$this->service,
|
94 |
+
$credentials->getSecretKey()
|
95 |
+
);
|
96 |
+
$parsed['query']['X-Amz-Signature'] = hash_hmac('sha256', $stringToSign, $key);
|
97 |
+
|
98 |
+
return $this->buildRequest($parsed);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Converts a POST request to a GET request by moving POST fields into the
|
103 |
+
* query string.
|
104 |
+
*
|
105 |
+
* Useful for pre-signing query protocol requests.
|
106 |
+
*
|
107 |
+
* @param RequestInterface $request Request to clone
|
108 |
+
*
|
109 |
+
* @return RequestInterface
|
110 |
+
* @throws \InvalidArgumentException if the method is not POST
|
111 |
+
*/
|
112 |
+
public static function convertPostToGet(RequestInterface $request)
|
113 |
+
{
|
114 |
+
if ($request->getMethod() !== 'POST') {
|
115 |
+
throw new \InvalidArgumentException('Expected a POST request but '
|
116 |
+
. 'received a ' . $request->getMethod() . ' request.');
|
117 |
+
}
|
118 |
+
|
119 |
+
$sr = $request->withMethod('GET')
|
120 |
+
->withBody(Psr7\stream_for(''))
|
121 |
+
->withoutHeader('Content-Type')
|
122 |
+
->withoutHeader('Content-Length');
|
123 |
+
|
124 |
+
// Move POST fields to the query if they are present
|
125 |
+
if ($request->getHeaderLine('Content-Type') === 'application/x-www-form-urlencoded') {
|
126 |
+
$body = (string) $request->getBody();
|
127 |
+
$sr = $sr->withUri($sr->getUri()->withQuery($body));
|
128 |
+
}
|
129 |
+
|
130 |
+
return $sr;
|
131 |
+
}
|
132 |
+
|
133 |
+
protected function getPayload(RequestInterface $request)
|
134 |
+
{
|
135 |
+
// Calculate the request signature payload
|
136 |
+
if ($request->hasHeader('X-Amz-Content-Sha256')) {
|
137 |
+
// Handle streaming operations (e.g. Glacier.UploadArchive)
|
138 |
+
return $request->getHeaderLine('X-Amz-Content-Sha256');
|
139 |
+
}
|
140 |
+
|
141 |
+
if (!$request->getBody()->isSeekable()) {
|
142 |
+
throw new CouldNotCreateChecksumException('sha256');
|
143 |
+
}
|
144 |
+
|
145 |
+
try {
|
146 |
+
return Psr7\hash($request->getBody(), 'sha256');
|
147 |
+
} catch (\Exception $e) {
|
148 |
+
throw new CouldNotCreateChecksumException('sha256', $e);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
protected function getPresignedPayload(RequestInterface $request)
|
153 |
+
{
|
154 |
+
return $this->getPayload($request);
|
155 |
+
}
|
156 |
+
|
157 |
+
protected function createCanonicalizedPath($path)
|
158 |
+
{
|
159 |
+
$doubleEncoded = rawurlencode(ltrim($path, '/'));
|
160 |
+
|
161 |
+
return '/' . str_replace('%2F', '/', $doubleEncoded);
|
162 |
+
}
|
163 |
+
|
164 |
+
private function createStringToSign($longDate, $credentialScope, $creq)
|
165 |
+
{
|
166 |
+
$hash = hash('sha256', $creq);
|
167 |
+
|
168 |
+
return "AWS4-HMAC-SHA256\n{$longDate}\n{$credentialScope}\n{$hash}";
|
169 |
+
}
|
170 |
+
|
171 |
+
private function createPresignedRequest(
|
172 |
+
RequestInterface $request,
|
173 |
+
CredentialsInterface $credentials
|
174 |
+
) {
|
175 |
+
$parsedRequest = $this->parseRequest($request);
|
176 |
+
|
177 |
+
// Make sure to handle temporary credentials
|
178 |
+
if ($token = $credentials->getSecurityToken()) {
|
179 |
+
$parsedRequest['headers']['X-Amz-Security-Token'] = [$token];
|
180 |
+
}
|
181 |
+
|
182 |
+
return $this->moveHeadersToQuery($parsedRequest);
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* @param array $parsedRequest
|
187 |
+
* @param string $payload Hash of the request payload
|
188 |
+
* @return array Returns an array of context information
|
189 |
+
*/
|
190 |
+
private function createContext(array $parsedRequest, $payload)
|
191 |
+
{
|
192 |
+
// The following headers are not signed because signing these headers
|
193 |
+
// would potentially cause a signature mismatch when sending a request
|
194 |
+
// through a proxy or if modified at the HTTP client level.
|
195 |
+
static $blacklist = [
|
196 |
+
'cache-control' => true,
|
197 |
+
'content-type' => true,
|
198 |
+
'content-length' => true,
|
199 |
+
'expect' => true,
|
200 |
+
'max-forwards' => true,
|
201 |
+
'pragma' => true,
|
202 |
+
'range' => true,
|
203 |
+
'te' => true,
|
204 |
+
'if-match' => true,
|
205 |
+
'if-none-match' => true,
|
206 |
+
'if-modified-since' => true,
|
207 |
+
'if-unmodified-since' => true,
|
208 |
+
'if-range' => true,
|
209 |
+
'accept' => true,
|
210 |
+
'authorization' => true,
|
211 |
+
'proxy-authorization' => true,
|
212 |
+
'from' => true,
|
213 |
+
'referer' => true,
|
214 |
+
'user-agent' => true
|
215 |
+
];
|
216 |
+
|
217 |
+
// Normalize the path as required by SigV4
|
218 |
+
$canon = $parsedRequest['method'] . "\n"
|
219 |
+
. $this->createCanonicalizedPath($parsedRequest['path']) . "\n"
|
220 |
+
. $this->getCanonicalizedQuery($parsedRequest['query']) . "\n";
|
221 |
+
|
222 |
+
// Case-insensitively aggregate all of the headers.
|
223 |
+
$aggregate = [];
|
224 |
+
foreach ($parsedRequest['headers'] as $key => $values) {
|
225 |
+
$key = strtolower($key);
|
226 |
+
if (!isset($blacklist[$key])) {
|
227 |
+
foreach ($values as $v) {
|
228 |
+
$aggregate[$key][] = $v;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
ksort($aggregate);
|
234 |
+
$canonHeaders = [];
|
235 |
+
foreach ($aggregate as $k => $v) {
|
236 |
+
if (count($v) > 0) {
|
237 |
+
sort($v);
|
238 |
+
}
|
239 |
+
$canonHeaders[] = $k . ':' . preg_replace('/\s+/', ' ', implode(',', $v));
|
240 |
+
}
|
241 |
+
|
242 |
+
$signedHeadersString = implode(';', array_keys($aggregate));
|
243 |
+
$canon .= implode("\n", $canonHeaders) . "\n\n"
|
244 |
+
. $signedHeadersString . "\n"
|
245 |
+
. $payload;
|
246 |
+
|
247 |
+
return ['creq' => $canon, 'headers' => $signedHeadersString];
|
248 |
+
}
|
249 |
+
|
250 |
+
private function getSigningKey($shortDate, $region, $service, $secretKey)
|
251 |
+
{
|
252 |
+
$k = $shortDate . '_' . $region . '_' . $service . '_' . $secretKey;
|
253 |
+
|
254 |
+
if (!isset($this->cache[$k])) {
|
255 |
+
// Clear the cache when it reaches 50 entries
|
256 |
+
if (++$this->cacheSize > 50) {
|
257 |
+
$this->cache = [];
|
258 |
+
$this->cacheSize = 0;
|
259 |
+
}
|
260 |
+
$dateKey = hash_hmac('sha256', $shortDate, "AWS4{$secretKey}", true);
|
261 |
+
$regionKey = hash_hmac('sha256', $region, $dateKey, true);
|
262 |
+
$serviceKey = hash_hmac('sha256', $service, $regionKey, true);
|
263 |
+
$this->cache[$k] = hash_hmac('sha256', 'aws4_request', $serviceKey, true);
|
264 |
+
}
|
265 |
+
|
266 |
+
return $this->cache[$k];
|
267 |
+
}
|
268 |
+
|
269 |
+
private function getCanonicalizedQuery(array $query)
|
270 |
+
{
|
271 |
+
unset($query['X-Amz-Signature']);
|
272 |
+
|
273 |
+
if (!$query) {
|
274 |
+
return '';
|
275 |
+
}
|
276 |
+
|
277 |
+
$qs = '';
|
278 |
+
ksort($query);
|
279 |
+
foreach ($query as $k => $v) {
|
280 |
+
if (!is_array($v)) {
|
281 |
+
$qs .= rawurlencode($k) . '=' . rawurlencode($v) . '&';
|
282 |
+
} else {
|
283 |
+
sort($v);
|
284 |
+
foreach ($v as $value) {
|
285 |
+
$qs .= rawurlencode($k) . '=' . rawurlencode($value) . '&';
|
286 |
+
}
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
return substr($qs, 0, -1);
|
291 |
+
}
|
292 |
+
|
293 |
+
private function convertExpires($expires)
|
294 |
+
{
|
295 |
+
if ($expires instanceof \DateTime) {
|
296 |
+
$expires = $expires->getTimestamp();
|
297 |
+
} elseif (!is_numeric($expires)) {
|
298 |
+
$expires = strtotime($expires);
|
299 |
+
}
|
300 |
+
|
301 |
+
$duration = $expires - time();
|
302 |
+
|
303 |
+
// Ensure that the duration of the signature is not longer than a week
|
304 |
+
if ($duration > 604800) {
|
305 |
+
throw new \InvalidArgumentException('The expiration date of a '
|
306 |
+
. 'signature version 4 presigned URL must be less than one '
|
307 |
+
. 'week');
|
308 |
+
}
|
309 |
+
|
310 |
+
return $duration;
|
311 |
+
}
|
312 |
+
|
313 |
+
private function createScope($shortDate, $region, $service)
|
314 |
+
{
|
315 |
+
return "$shortDate/$region/$service/aws4_request";
|
316 |
+
}
|
317 |
+
|
318 |
+
private function moveHeadersToQuery(array $parsedRequest)
|
319 |
+
{
|
320 |
+
foreach ($parsedRequest['headers'] as $name => $header) {
|
321 |
+
$lname = strtolower($name);
|
322 |
+
if (substr($lname, 0, 5) == 'x-amz') {
|
323 |
+
$parsedRequest['query'][$name] = $header;
|
324 |
+
}
|
325 |
+
if ($lname !== 'host') {
|
326 |
+
unset($parsedRequest['headers'][$name]);
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
return $parsedRequest;
|
331 |
+
}
|
332 |
+
|
333 |
+
private function parseRequest(RequestInterface $request)
|
334 |
+
{
|
335 |
+
// Clean up any previously set headers.
|
336 |
+
/** @var RequestInterface $request */
|
337 |
+
$request = $request
|
338 |
+
->withoutHeader('X-Amz-Date')
|
339 |
+
->withoutHeader('Date')
|
340 |
+
->withoutHeader('Authorization');
|
341 |
+
$uri = $request->getUri();
|
342 |
+
|
343 |
+
return [
|
344 |
+
'method' => $request->getMethod(),
|
345 |
+
'path' => $uri->getPath(),
|
346 |
+
'query' => Psr7\parse_query($uri->getQuery()),
|
347 |
+
'uri' => $uri,
|
348 |
+
'headers' => $request->getHeaders(),
|
349 |
+
'body' => $request->getBody(),
|
350 |
+
'version' => $request->getProtocolVersion()
|
351 |
+
];
|
352 |
+
}
|
353 |
+
|
354 |
+
private function buildRequest(array $req)
|
355 |
+
{
|
356 |
+
if ($req['query']) {
|
357 |
+
$req['uri'] = $req['uri']->withQuery(Psr7\build_query($req['query']));
|
358 |
+
}
|
359 |
+
|
360 |
+
return new Psr7\Request(
|
361 |
+
$req['method'],
|
362 |
+
$req['uri'],
|
363 |
+
$req['headers'],
|
364 |
+
$req['body'],
|
365 |
+
$req['version']
|
366 |
+
);
|
367 |
+
}
|
368 |
+
}
|
includes/aws/Aws/StorageGateway/Exception/StorageGatewayException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\StorageGateway\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the AWS Storage Gateway service.
|
8 |
+
*/
|
9 |
+
class StorageGatewayException extends AwsException {}
|
includes/aws/Aws/StorageGateway/StorageGatewayClient.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\StorageGateway;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS Storage Gateway client.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result activateGateway(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise activateGatewayAsync(array $args = [])
|
11 |
+
* @method \Aws\Result addCache(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise addCacheAsync(array $args = [])
|
13 |
+
* @method \Aws\Result addTagsToResource(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise addTagsToResourceAsync(array $args = [])
|
15 |
+
* @method \Aws\Result addUploadBuffer(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise addUploadBufferAsync(array $args = [])
|
17 |
+
* @method \Aws\Result addWorkingStorage(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise addWorkingStorageAsync(array $args = [])
|
19 |
+
* @method \Aws\Result cancelArchival(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise cancelArchivalAsync(array $args = [])
|
21 |
+
* @method \Aws\Result cancelRetrieval(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise cancelRetrievalAsync(array $args = [])
|
23 |
+
* @method \Aws\Result createCachediSCSIVolume(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise createCachediSCSIVolumeAsync(array $args = [])
|
25 |
+
* @method \Aws\Result createSnapshot(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise createSnapshotAsync(array $args = [])
|
27 |
+
* @method \Aws\Result createSnapshotFromVolumeRecoveryPoint(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise createSnapshotFromVolumeRecoveryPointAsync(array $args = [])
|
29 |
+
* @method \Aws\Result createStorediSCSIVolume(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise createStorediSCSIVolumeAsync(array $args = [])
|
31 |
+
* @method \Aws\Result createTapes(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise createTapesAsync(array $args = [])
|
33 |
+
* @method \Aws\Result deleteBandwidthRateLimit(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise deleteBandwidthRateLimitAsync(array $args = [])
|
35 |
+
* @method \Aws\Result deleteChapCredentials(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise deleteChapCredentialsAsync(array $args = [])
|
37 |
+
* @method \Aws\Result deleteGateway(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise deleteGatewayAsync(array $args = [])
|
39 |
+
* @method \Aws\Result deleteSnapshotSchedule(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise deleteSnapshotScheduleAsync(array $args = [])
|
41 |
+
* @method \Aws\Result deleteTape(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise deleteTapeAsync(array $args = [])
|
43 |
+
* @method \Aws\Result deleteTapeArchive(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise deleteTapeArchiveAsync(array $args = [])
|
45 |
+
* @method \Aws\Result deleteVolume(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise deleteVolumeAsync(array $args = [])
|
47 |
+
* @method \Aws\Result describeBandwidthRateLimit(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise describeBandwidthRateLimitAsync(array $args = [])
|
49 |
+
* @method \Aws\Result describeCache(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise describeCacheAsync(array $args = [])
|
51 |
+
* @method \Aws\Result describeCachediSCSIVolumes(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise describeCachediSCSIVolumesAsync(array $args = [])
|
53 |
+
* @method \Aws\Result describeChapCredentials(array $args = [])
|
54 |
+
* @method \GuzzleHttp\Promise\Promise describeChapCredentialsAsync(array $args = [])
|
55 |
+
* @method \Aws\Result describeGatewayInformation(array $args = [])
|
56 |
+
* @method \GuzzleHttp\Promise\Promise describeGatewayInformationAsync(array $args = [])
|
57 |
+
* @method \Aws\Result describeMaintenanceStartTime(array $args = [])
|
58 |
+
* @method \GuzzleHttp\Promise\Promise describeMaintenanceStartTimeAsync(array $args = [])
|
59 |
+
* @method \Aws\Result describeSnapshotSchedule(array $args = [])
|
60 |
+
* @method \GuzzleHttp\Promise\Promise describeSnapshotScheduleAsync(array $args = [])
|
61 |
+
* @method \Aws\Result describeStorediSCSIVolumes(array $args = [])
|
62 |
+
* @method \GuzzleHttp\Promise\Promise describeStorediSCSIVolumesAsync(array $args = [])
|
63 |
+
* @method \Aws\Result describeTapeArchives(array $args = [])
|
64 |
+
* @method \GuzzleHttp\Promise\Promise describeTapeArchivesAsync(array $args = [])
|
65 |
+
* @method \Aws\Result describeTapeRecoveryPoints(array $args = [])
|
66 |
+
* @method \GuzzleHttp\Promise\Promise describeTapeRecoveryPointsAsync(array $args = [])
|
67 |
+
* @method \Aws\Result describeTapes(array $args = [])
|
68 |
+
* @method \GuzzleHttp\Promise\Promise describeTapesAsync(array $args = [])
|
69 |
+
* @method \Aws\Result describeUploadBuffer(array $args = [])
|
70 |
+
* @method \GuzzleHttp\Promise\Promise describeUploadBufferAsync(array $args = [])
|
71 |
+
* @method \Aws\Result describeVTLDevices(array $args = [])
|
72 |
+
* @method \GuzzleHttp\Promise\Promise describeVTLDevicesAsync(array $args = [])
|
73 |
+
* @method \Aws\Result describeWorkingStorage(array $args = [])
|
74 |
+
* @method \GuzzleHttp\Promise\Promise describeWorkingStorageAsync(array $args = [])
|
75 |
+
* @method \Aws\Result disableGateway(array $args = [])
|
76 |
+
* @method \GuzzleHttp\Promise\Promise disableGatewayAsync(array $args = [])
|
77 |
+
* @method \Aws\Result listGateways(array $args = [])
|
78 |
+
* @method \GuzzleHttp\Promise\Promise listGatewaysAsync(array $args = [])
|
79 |
+
* @method \Aws\Result listLocalDisks(array $args = [])
|
80 |
+
* @method \GuzzleHttp\Promise\Promise listLocalDisksAsync(array $args = [])
|
81 |
+
* @method \Aws\Result listTagsForResource(array $args = [])
|
82 |
+
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = [])
|
83 |
+
* @method \Aws\Result listVolumeInitiators(array $args = [])
|
84 |
+
* @method \GuzzleHttp\Promise\Promise listVolumeInitiatorsAsync(array $args = [])
|
85 |
+
* @method \Aws\Result listVolumeRecoveryPoints(array $args = [])
|
86 |
+
* @method \GuzzleHttp\Promise\Promise listVolumeRecoveryPointsAsync(array $args = [])
|
87 |
+
* @method \Aws\Result listVolumes(array $args = [])
|
88 |
+
* @method \GuzzleHttp\Promise\Promise listVolumesAsync(array $args = [])
|
89 |
+
* @method \Aws\Result removeTagsFromResource(array $args = [])
|
90 |
+
* @method \GuzzleHttp\Promise\Promise removeTagsFromResourceAsync(array $args = [])
|
91 |
+
* @method \Aws\Result resetCache(array $args = [])
|
92 |
+
* @method \GuzzleHttp\Promise\Promise resetCacheAsync(array $args = [])
|
93 |
+
* @method \Aws\Result retrieveTapeArchive(array $args = [])
|
94 |
+
* @method \GuzzleHttp\Promise\Promise retrieveTapeArchiveAsync(array $args = [])
|
95 |
+
* @method \Aws\Result retrieveTapeRecoveryPoint(array $args = [])
|
96 |
+
* @method \GuzzleHttp\Promise\Promise retrieveTapeRecoveryPointAsync(array $args = [])
|
97 |
+
* @method \Aws\Result shutdownGateway(array $args = [])
|
98 |
+
* @method \GuzzleHttp\Promise\Promise shutdownGatewayAsync(array $args = [])
|
99 |
+
* @method \Aws\Result startGateway(array $args = [])
|
100 |
+
* @method \GuzzleHttp\Promise\Promise startGatewayAsync(array $args = [])
|
101 |
+
* @method \Aws\Result updateBandwidthRateLimit(array $args = [])
|
102 |
+
* @method \GuzzleHttp\Promise\Promise updateBandwidthRateLimitAsync(array $args = [])
|
103 |
+
* @method \Aws\Result updateChapCredentials(array $args = [])
|
104 |
+
* @method \GuzzleHttp\Promise\Promise updateChapCredentialsAsync(array $args = [])
|
105 |
+
* @method \Aws\Result updateGatewayInformation(array $args = [])
|
106 |
+
* @method \GuzzleHttp\Promise\Promise updateGatewayInformationAsync(array $args = [])
|
107 |
+
* @method \Aws\Result updateGatewaySoftwareNow(array $args = [])
|
108 |
+
* @method \GuzzleHttp\Promise\Promise updateGatewaySoftwareNowAsync(array $args = [])
|
109 |
+
* @method \Aws\Result updateMaintenanceStartTime(array $args = [])
|
110 |
+
* @method \GuzzleHttp\Promise\Promise updateMaintenanceStartTimeAsync(array $args = [])
|
111 |
+
* @method \Aws\Result updateSnapshotSchedule(array $args = [])
|
112 |
+
* @method \GuzzleHttp\Promise\Promise updateSnapshotScheduleAsync(array $args = [])
|
113 |
+
* @method \Aws\Result updateVTLDeviceType(array $args = [])
|
114 |
+
* @method \GuzzleHttp\Promise\Promise updateVTLDeviceTypeAsync(array $args = [])
|
115 |
+
*/
|
116 |
+
class StorageGatewayClient extends AwsClient {}
|
includes/aws/Aws/Support/Exception/SupportException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Support\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS Support service exception.
|
8 |
+
*/
|
9 |
+
class SupportException extends AwsException {}
|
includes/aws/Aws/Support/SupportClient.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\Support;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AWS Support client.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result addAttachmentsToSet(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise addAttachmentsToSetAsync(array $args = [])
|
11 |
+
* @method \Aws\Result addCommunicationToCase(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise addCommunicationToCaseAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createCase(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createCaseAsync(array $args = [])
|
15 |
+
* @method \Aws\Result describeAttachment(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise describeAttachmentAsync(array $args = [])
|
17 |
+
* @method \Aws\Result describeCases(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise describeCasesAsync(array $args = [])
|
19 |
+
* @method \Aws\Result describeCommunications(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise describeCommunicationsAsync(array $args = [])
|
21 |
+
* @method \Aws\Result describeServices(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise describeServicesAsync(array $args = [])
|
23 |
+
* @method \Aws\Result describeSeverityLevels(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise describeSeverityLevelsAsync(array $args = [])
|
25 |
+
* @method \Aws\Result describeTrustedAdvisorCheckRefreshStatuses(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckRefreshStatusesAsync(array $args = [])
|
27 |
+
* @method \Aws\Result describeTrustedAdvisorCheckResult(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckResultAsync(array $args = [])
|
29 |
+
* @method \Aws\Result describeTrustedAdvisorCheckSummaries(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorCheckSummariesAsync(array $args = [])
|
31 |
+
* @method \Aws\Result describeTrustedAdvisorChecks(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise describeTrustedAdvisorChecksAsync(array $args = [])
|
33 |
+
* @method \Aws\Result refreshTrustedAdvisorCheck(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise refreshTrustedAdvisorCheckAsync(array $args = [])
|
35 |
+
* @method \Aws\Result resolveCase(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise resolveCaseAsync(array $args = [])
|
37 |
+
*/
|
38 |
+
class SupportClient extends AwsClient {}
|
includes/aws/Aws/TraceMiddleware.php
ADDED
@@ -0,0 +1,302 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
use Psr\Http\Message\StreamInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Traces state changes between middlewares.
|
12 |
+
*/
|
13 |
+
class TraceMiddleware
|
14 |
+
{
|
15 |
+
private $prevOutput;
|
16 |
+
private $prevInput;
|
17 |
+
private $config;
|
18 |
+
|
19 |
+
private static $authHeaders = [
|
20 |
+
'X-Amz-Security-Token' => '[TOKEN]',
|
21 |
+
];
|
22 |
+
|
23 |
+
private static $authStrings = [
|
24 |
+
// S3Signature
|
25 |
+
'/AWSAccessKeyId=[A-Z0-9]{20}&/i' => 'AWSAccessKeyId=[KEY]&',
|
26 |
+
// SignatureV4 Signature and S3Signature
|
27 |
+
'/Signature=.+/i' => 'Signature=[SIGNATURE]',
|
28 |
+
// SignatureV4 access key ID
|
29 |
+
'/Credential=[A-Z0-9]{20}\//i' => 'Credential=[KEY]/',
|
30 |
+
// S3 signatures
|
31 |
+
'/AWS [A-Z0-9]{20}:.+/' => 'AWS AKI[KEY]:[SIGNATURE]',
|
32 |
+
// STS Presigned URLs
|
33 |
+
'/X-Amz-Security-Token=[^&]+/i' => 'X-Amz-Security-Token=[TOKEN]',
|
34 |
+
];
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Configuration array can contain the following key value pairs.
|
38 |
+
*
|
39 |
+
* - logfn: (callable) Function that is invoked with log messages. By
|
40 |
+
* default, PHP's "echo" function will be utilized.
|
41 |
+
* - stream_size: (int) When the size of a stream is greater than this
|
42 |
+
* number, the stream data will not be logged. Set to "0" to not log any
|
43 |
+
* stream data.
|
44 |
+
* - scrub_auth: (bool) Set to false to disable the scrubbing of auth data
|
45 |
+
* from the logged messages.
|
46 |
+
* - http: (bool) Set to false to disable the "debug" feature of lower
|
47 |
+
* level HTTP adapters (e.g., verbose curl output).
|
48 |
+
* - auth_strings: (array) A mapping of authentication string regular
|
49 |
+
* expressions to scrubbed strings. These mappings are passed directly to
|
50 |
+
* preg_replace (e.g., preg_replace($key, $value, $debugOutput) if
|
51 |
+
* "scrub_auth" is set to true.
|
52 |
+
* - auth_headers: (array) A mapping of header names known to contain
|
53 |
+
* sensitive data to what the scrubbed value should be. The value of any
|
54 |
+
* headers contained in this array will be replaced with the if
|
55 |
+
* "scrub_auth" is set to true.
|
56 |
+
*/
|
57 |
+
public function __construct(array $config = [])
|
58 |
+
{
|
59 |
+
$this->config = $config + [
|
60 |
+
'logfn' => function ($value) { echo $value; },
|
61 |
+
'stream_size' => 524288,
|
62 |
+
'scrub_auth' => true,
|
63 |
+
'http' => true,
|
64 |
+
'auth_strings' => [],
|
65 |
+
'auth_headers' => [],
|
66 |
+
];
|
67 |
+
|
68 |
+
$this->config['auth_strings'] += self::$authStrings;
|
69 |
+
$this->config['auth_headers'] += self::$authHeaders;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function __invoke($step, $name)
|
73 |
+
{
|
74 |
+
$this->prevOutput = $this->prevInput = [];
|
75 |
+
|
76 |
+
return function (callable $next) use ($step, $name) {
|
77 |
+
return function (
|
78 |
+
CommandInterface $command,
|
79 |
+
RequestInterface $request = null
|
80 |
+
) use ($next, $step, $name) {
|
81 |
+
$this->createHttpDebug($command);
|
82 |
+
$start = microtime(true);
|
83 |
+
$this->stepInput([
|
84 |
+
'step' => $step,
|
85 |
+
'name' => $name,
|
86 |
+
'request' => $this->requestArray($request),
|
87 |
+
'command' => $this->commandArray($command)
|
88 |
+
]);
|
89 |
+
|
90 |
+
return $next($command, $request)->then(
|
91 |
+
function ($value) use ($step, $name, $command, $start) {
|
92 |
+
$this->flushHttpDebug($command);
|
93 |
+
$this->stepOutput($start, [
|
94 |
+
'step' => $step,
|
95 |
+
'name' => $name,
|
96 |
+
'result' => $this->resultArray($value),
|
97 |
+
'error' => null
|
98 |
+
]);
|
99 |
+
return $value;
|
100 |
+
},
|
101 |
+
function ($reason) use ($step, $name, $start, $command) {
|
102 |
+
$this->flushHttpDebug($command);
|
103 |
+
$this->stepOutput($start, [
|
104 |
+
'step' => $step,
|
105 |
+
'name' => $name,
|
106 |
+
'result' => null,
|
107 |
+
'error' => $this->exceptionArray($reason)
|
108 |
+
]);
|
109 |
+
return new RejectedPromise($reason);
|
110 |
+
}
|
111 |
+
);
|
112 |
+
};
|
113 |
+
};
|
114 |
+
}
|
115 |
+
|
116 |
+
private function stepInput($entry)
|
117 |
+
{
|
118 |
+
static $keys = ['command', 'request'];
|
119 |
+
$this->compareStep($this->prevInput, $entry, '-> Entering', $keys);
|
120 |
+
$this->write("\n");
|
121 |
+
$this->prevInput = $entry;
|
122 |
+
}
|
123 |
+
|
124 |
+
private function stepOutput($start, $entry)
|
125 |
+
{
|
126 |
+
static $keys = ['result', 'error'];
|
127 |
+
$this->compareStep($this->prevOutput, $entry, '<- Leaving', $keys);
|
128 |
+
$totalTime = microtime(true) - $start;
|
129 |
+
$this->write(" Inclusive step time: " . $totalTime . "\n\n");
|
130 |
+
$this->prevOutput = $entry;
|
131 |
+
}
|
132 |
+
|
133 |
+
private function compareStep(array $a, array $b, $title, array $keys)
|
134 |
+
{
|
135 |
+
$changes = [];
|
136 |
+
foreach ($keys as $key) {
|
137 |
+
$av = isset($a[$key]) ? $a[$key] : null;
|
138 |
+
$bv = isset($b[$key]) ? $b[$key] : null;
|
139 |
+
$this->compareArray($av, $bv, $key, $changes);
|
140 |
+
}
|
141 |
+
$str = "\n{$title} step {$b['step']}, name '{$b['name']}'";
|
142 |
+
$str .= "\n" . str_repeat('-', strlen($str) - 1) . "\n\n ";
|
143 |
+
$str .= $changes
|
144 |
+
? implode("\n ", str_replace("\n", "\n ", $changes))
|
145 |
+
: 'no changes';
|
146 |
+
$this->write($str . "\n");
|
147 |
+
}
|
148 |
+
|
149 |
+
private function commandArray(CommandInterface $cmd)
|
150 |
+
{
|
151 |
+
return [
|
152 |
+
'instance' => spl_object_hash($cmd),
|
153 |
+
'name' => $cmd->getName(),
|
154 |
+
'params' => $cmd->toArray()
|
155 |
+
];
|
156 |
+
}
|
157 |
+
|
158 |
+
private function requestArray(RequestInterface $request = null)
|
159 |
+
{
|
160 |
+
return !$request ? [] : array_filter([
|
161 |
+
'instance' => spl_object_hash($request),
|
162 |
+
'method' => $request->getMethod(),
|
163 |
+
'headers' => $this->redactHeaders($request->getHeaders()),
|
164 |
+
'body' => $this->streamStr($request->getBody()),
|
165 |
+
'scheme' => $request->getUri()->getScheme(),
|
166 |
+
'port' => $request->getUri()->getPort(),
|
167 |
+
'path' => $request->getUri()->getPath(),
|
168 |
+
'query' => $request->getUri()->getQuery(),
|
169 |
+
]);
|
170 |
+
}
|
171 |
+
|
172 |
+
private function responseArray(ResponseInterface $response = null)
|
173 |
+
{
|
174 |
+
return !$response ? [] : [
|
175 |
+
'instance' => spl_object_hash($response),
|
176 |
+
'statusCode' => $response->getStatusCode(),
|
177 |
+
'headers' => $this->redactHeaders($response->getHeaders()),
|
178 |
+
'body' => $this->streamStr($response->getBody())
|
179 |
+
];
|
180 |
+
}
|
181 |
+
|
182 |
+
private function resultArray($value)
|
183 |
+
{
|
184 |
+
return $value instanceof ResultInterface
|
185 |
+
? [
|
186 |
+
'instance' => spl_object_hash($value),
|
187 |
+
'data' => $value->toArray()
|
188 |
+
] : $value;
|
189 |
+
}
|
190 |
+
|
191 |
+
private function exceptionArray($e)
|
192 |
+
{
|
193 |
+
if (!($e instanceof \Exception)) {
|
194 |
+
return $e;
|
195 |
+
}
|
196 |
+
|
197 |
+
$result = [
|
198 |
+
'instance' => spl_object_hash($e),
|
199 |
+
'class' => get_class($e),
|
200 |
+
'message' => $e->getMessage(),
|
201 |
+
'file' => $e->getFile(),
|
202 |
+
'line' => $e->getLine(),
|
203 |
+
'trace' => $e->getTraceAsString(),
|
204 |
+
];
|
205 |
+
|
206 |
+
if ($e instanceof AwsException) {
|
207 |
+
$result += [
|
208 |
+
'type' => $e->getAwsErrorType(),
|
209 |
+
'code' => $e->getAwsErrorCode(),
|
210 |
+
'requestId' => $e->getAwsRequestId(),
|
211 |
+
'statusCode' => $e->getStatusCode(),
|
212 |
+
'result' => $this->resultArray($e->getResult()),
|
213 |
+
'request' => $this->requestArray($e->getRequest()),
|
214 |
+
'response' => $this->responseArray($e->getResponse()),
|
215 |
+
];
|
216 |
+
}
|
217 |
+
|
218 |
+
return $result;
|
219 |
+
}
|
220 |
+
|
221 |
+
private function compareArray($a, $b, $path, array &$diff)
|
222 |
+
{
|
223 |
+
if ($a === $b) {
|
224 |
+
return;
|
225 |
+
} elseif (is_array($a)) {
|
226 |
+
$b = (array) $b;
|
227 |
+
$keys = array_unique(array_merge(array_keys($a), array_keys($b)));
|
228 |
+
foreach ($keys as $k) {
|
229 |
+
if (!array_key_exists($k, $a)) {
|
230 |
+
$this->compareArray(null, $b[$k], "{$path}.{$k}", $diff);
|
231 |
+
} elseif (!array_key_exists($k, $b)) {
|
232 |
+
$this->compareArray($a[$k], null, "{$path}.{$k}", $diff);
|
233 |
+
} else {
|
234 |
+
$this->compareArray($a[$k], $b[$k], "{$path}.{$k}", $diff);
|
235 |
+
}
|
236 |
+
}
|
237 |
+
} elseif ($a !== null && $b === null) {
|
238 |
+
$diff[] = "{$path} was unset";
|
239 |
+
} elseif ($a === null && $b !== null) {
|
240 |
+
$diff[] = sprintf("%s was set to %s", $path, $this->str($b));
|
241 |
+
} else {
|
242 |
+
$diff[] = sprintf("%s changed from %s to %s", $path, $this->str($a), $this->str($b));
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
private function str($value)
|
247 |
+
{
|
248 |
+
if (is_scalar($value)) {
|
249 |
+
return (string) $value;
|
250 |
+
} elseif ($value instanceof \Exception) {
|
251 |
+
$value = $this->exceptionArray($value);
|
252 |
+
}
|
253 |
+
|
254 |
+
ob_start();
|
255 |
+
var_dump($value);
|
256 |
+
return ob_get_clean();
|
257 |
+
}
|
258 |
+
|
259 |
+
private function streamStr(StreamInterface $body)
|
260 |
+
{
|
261 |
+
return $body->getSize() < $this->config['stream_size']
|
262 |
+
? (string) $body
|
263 |
+
: 'stream(size=' . $body->getSize() . ')';
|
264 |
+
}
|
265 |
+
|
266 |
+
private function createHttpDebug(CommandInterface $command)
|
267 |
+
{
|
268 |
+
if ($this->config['http'] && !isset($command['@http']['debug'])) {
|
269 |
+
$command['@http']['debug'] = fopen('php://temp', 'w+');
|
270 |
+
}
|
271 |
+
}
|
272 |
+
|
273 |
+
private function flushHttpDebug(CommandInterface $command)
|
274 |
+
{
|
275 |
+
if ($res = $command['@http']['debug']) {
|
276 |
+
rewind($res);
|
277 |
+
$this->write(stream_get_contents($res));
|
278 |
+
fclose($res);
|
279 |
+
$command['@http']['debug'] = null;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
private function write($value)
|
284 |
+
{
|
285 |
+
if ($this->config['scrub_auth']) {
|
286 |
+
foreach ($this->config['auth_strings'] as $pattern => $replacement) {
|
287 |
+
$value = preg_replace($pattern, $replacement, $value);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
call_user_func($this->config['logfn'], $value);
|
292 |
+
}
|
293 |
+
|
294 |
+
private function redactHeaders(array $headers)
|
295 |
+
{
|
296 |
+
if ($this->config['scrub_auth']) {
|
297 |
+
$headers = $this->config['auth_headers'] + $headers;
|
298 |
+
}
|
299 |
+
|
300 |
+
return $headers;
|
301 |
+
}
|
302 |
+
}
|
includes/aws/Aws/Waiter.php
ADDED
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
7 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* "Waiters" are associated with an AWS resource (e.g., EC2 instance), and poll
|
11 |
+
* that resource and until it is in a particular state.
|
12 |
+
|
13 |
+
* The Waiter object produces a promise that is either a.) resolved once the
|
14 |
+
* waiting conditions are met, or b.) rejected if the waiting conditions cannot
|
15 |
+
* be met or has exceeded the number of allowed attempts at meeting the
|
16 |
+
* conditions. You can use waiters in a blocking or non-blocking way, depending
|
17 |
+
* on whether you call wait() on the promise.
|
18 |
+
|
19 |
+
* The configuration for the waiter must include information about the operation
|
20 |
+
* and the conditions for wait completion.
|
21 |
+
*/
|
22 |
+
class Waiter implements PromisorInterface
|
23 |
+
{
|
24 |
+
/** @var AwsClientInterface Client used to execute each attempt. */
|
25 |
+
private $client;
|
26 |
+
|
27 |
+
/** @var string Name of the waiter. */
|
28 |
+
private $name;
|
29 |
+
|
30 |
+
/** @var array Params to use with each attempt operation. */
|
31 |
+
private $args;
|
32 |
+
|
33 |
+
/** @var array Waiter configuration. */
|
34 |
+
private $config;
|
35 |
+
|
36 |
+
/** @var array Default configuration options. */
|
37 |
+
private static $defaults = ['initDelay' => 0, 'before' => null];
|
38 |
+
|
39 |
+
/** @var array Required configuration options. */
|
40 |
+
private static $required = [
|
41 |
+
'acceptors',
|
42 |
+
'delay',
|
43 |
+
'maxAttempts',
|
44 |
+
'operation',
|
45 |
+
];
|
46 |
+
|
47 |
+
/**
|
48 |
+
* The array of configuration options include:
|
49 |
+
*
|
50 |
+
* - acceptors: (array) Array of acceptor options
|
51 |
+
* - delay: (int) Number of seconds to delay between attempts
|
52 |
+
* - maxAttempts: (int) Maximum number of attempts before failing
|
53 |
+
* - operation: (string) Name of the API operation to use for polling
|
54 |
+
* - before: (callable) Invoked before attempts. Accepts command and tries.
|
55 |
+
*
|
56 |
+
* @param AwsClientInterface $client Client used to execute commands.
|
57 |
+
* @param string $name Waiter name.
|
58 |
+
* @param array $args Command arguments.
|
59 |
+
* @param array $config Waiter config that overrides defaults.
|
60 |
+
*
|
61 |
+
* @throws \InvalidArgumentException if the configuration is incomplete.
|
62 |
+
*/
|
63 |
+
public function __construct(
|
64 |
+
AwsClientInterface $client,
|
65 |
+
$name,
|
66 |
+
array $args = [],
|
67 |
+
array $config = []
|
68 |
+
) {
|
69 |
+
$this->client = $client;
|
70 |
+
$this->name = $name;
|
71 |
+
$this->args = $args;
|
72 |
+
|
73 |
+
// Prepare and validate config.
|
74 |
+
$this->config = $config + self::$defaults;
|
75 |
+
foreach (self::$required as $key) {
|
76 |
+
if (!isset($this->config[$key])) {
|
77 |
+
throw new \InvalidArgumentException(
|
78 |
+
'The provided waiter configuration was incomplete.'
|
79 |
+
);
|
80 |
+
}
|
81 |
+
}
|
82 |
+
if ($this->config['before'] && !is_callable($this->config['before'])) {
|
83 |
+
throw new \InvalidArgumentException(
|
84 |
+
'The provided "before" callback is not callable.'
|
85 |
+
);
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
public function promise()
|
90 |
+
{
|
91 |
+
return Promise\coroutine(function () {
|
92 |
+
$name = $this->config['operation'];
|
93 |
+
for ($state = 'retry', $attempt = 1; $state === 'retry'; $attempt++) {
|
94 |
+
// Execute the operation.
|
95 |
+
$args = $this->getArgsForAttempt($attempt);
|
96 |
+
$command = $this->client->getCommand($name, $args);
|
97 |
+
try {
|
98 |
+
if ($this->config['before']) {
|
99 |
+
$this->config['before']($command, $attempt);
|
100 |
+
}
|
101 |
+
$result = (yield $this->client->executeAsync($command));
|
102 |
+
} catch (AwsException $e) {
|
103 |
+
$result = $e;
|
104 |
+
}
|
105 |
+
|
106 |
+
// Determine the waiter's state and what to do next.
|
107 |
+
$state = $this->determineState($result);
|
108 |
+
if ($state === 'success') {
|
109 |
+
yield $command;
|
110 |
+
} elseif ($state === 'failed') {
|
111 |
+
$msg = "The {$this->name} waiter entered a failure state.";
|
112 |
+
if ($result instanceof \Exception) {
|
113 |
+
$msg .= ' Reason: ' . $result->getMessage();
|
114 |
+
}
|
115 |
+
yield new RejectedPromise(new \RuntimeException($msg));
|
116 |
+
} elseif ($state === 'retry'
|
117 |
+
&& $attempt >= $this->config['maxAttempts']
|
118 |
+
) {
|
119 |
+
$state = 'failed';
|
120 |
+
yield new RejectedPromise(new \RuntimeException(
|
121 |
+
"The {$this->name} waiter failed after attempt #{$attempt}."
|
122 |
+
));
|
123 |
+
}
|
124 |
+
}
|
125 |
+
});
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Gets the operation arguments for the attempt, including the delay.
|
130 |
+
*
|
131 |
+
* @param $attempt Number of the current attempt.
|
132 |
+
*
|
133 |
+
* @return mixed integer
|
134 |
+
*/
|
135 |
+
private function getArgsForAttempt($attempt)
|
136 |
+
{
|
137 |
+
$args = $this->args;
|
138 |
+
|
139 |
+
// Determine the delay.
|
140 |
+
$delay = ($attempt === 1)
|
141 |
+
? $this->config['initDelay']
|
142 |
+
: $this->config['delay'];
|
143 |
+
if (is_callable($delay)) {
|
144 |
+
$delay = $delay($attempt);
|
145 |
+
}
|
146 |
+
|
147 |
+
// Set the delay. (Note: handlers except delay in milliseconds.)
|
148 |
+
if (!isset($args['@http'])) {
|
149 |
+
$args['@http'] = [];
|
150 |
+
}
|
151 |
+
$args['@http']['delay'] = $delay * 1000;
|
152 |
+
|
153 |
+
return $args;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Determines the state of the waiter attempt, based on the result of
|
158 |
+
* polling the resource. A waiter can have the state of "success", "failed",
|
159 |
+
* or "retry".
|
160 |
+
*
|
161 |
+
* @param mixed $result
|
162 |
+
*
|
163 |
+
* @return string Will be "success", "failed", or "retry"
|
164 |
+
*/
|
165 |
+
private function determineState($result)
|
166 |
+
{
|
167 |
+
foreach ($this->config['acceptors'] as $acceptor) {
|
168 |
+
$matcher = 'matches' . ucfirst($acceptor['matcher']);
|
169 |
+
if ($this->{$matcher}($result, $acceptor)) {
|
170 |
+
return $acceptor['state'];
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
return $result instanceof \Exception ? 'failed' : 'retry';
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @param result $result Result or exception.
|
179 |
+
* @param array $acceptor Acceptor configuration being checked.
|
180 |
+
*
|
181 |
+
* @return bool
|
182 |
+
*/
|
183 |
+
private function matchesPath($result, array $acceptor)
|
184 |
+
{
|
185 |
+
return !($result instanceof ResultInterface)
|
186 |
+
? false
|
187 |
+
: $acceptor['expected'] == $result->search($acceptor['argument']);
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* @param result $result Result or exception.
|
192 |
+
* @param array $acceptor Acceptor configuration being checked.
|
193 |
+
*
|
194 |
+
* @return bool
|
195 |
+
*/
|
196 |
+
private function matchesPathAll($result, array $acceptor)
|
197 |
+
{
|
198 |
+
if (!($result instanceof ResultInterface)) {
|
199 |
+
return false;
|
200 |
+
}
|
201 |
+
|
202 |
+
$actuals = $result->search($acceptor['argument']) ?: [];
|
203 |
+
foreach ($actuals as $actual) {
|
204 |
+
if ($actual != $acceptor['expected']) {
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
return true;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @param result $result Result or exception.
|
214 |
+
* @param array $acceptor Acceptor configuration being checked.
|
215 |
+
*
|
216 |
+
* @return bool
|
217 |
+
*/
|
218 |
+
private function matchesPathAny($result, array $acceptor)
|
219 |
+
{
|
220 |
+
if (!($result instanceof ResultInterface)) {
|
221 |
+
return false;
|
222 |
+
}
|
223 |
+
|
224 |
+
$actuals = $result->search($acceptor['argument']) ?: [];
|
225 |
+
foreach ($actuals as $actual) {
|
226 |
+
if ($actual == $acceptor['expected']) {
|
227 |
+
return true;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
return false;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @param result $result Result or exception.
|
236 |
+
* @param array $acceptor Acceptor configuration being checked.
|
237 |
+
*
|
238 |
+
* @return bool
|
239 |
+
*/
|
240 |
+
private function matchesStatus($result, array $acceptor)
|
241 |
+
{
|
242 |
+
if ($result instanceof ResultInterface) {
|
243 |
+
return $acceptor['expected'] == $result['@metadata']['statusCode'];
|
244 |
+
} elseif ($result instanceof AwsException && $response = $result->getResponse()) {
|
245 |
+
return $acceptor['expected'] == $response->getStatusCode();
|
246 |
+
} else {
|
247 |
+
return false;
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* @param result $result Result or exception.
|
253 |
+
* @param array $acceptor Acceptor configuration being checked.
|
254 |
+
*
|
255 |
+
* @return bool
|
256 |
+
*/
|
257 |
+
private function matchesError($result, array $acceptor)
|
258 |
+
{
|
259 |
+
if ($result instanceof AwsException) {
|
260 |
+
return $result->isConnectionError()
|
261 |
+
|| $result->getAwsErrorCode() == $acceptor['expected'];
|
262 |
+
}
|
263 |
+
|
264 |
+
return false;
|
265 |
+
}
|
266 |
+
}
|
includes/aws/Aws/WorkSpaces/Exception/WorkSpacesException.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\WorkSpaces\Exception;
|
3 |
+
|
4 |
+
use Aws\Exception\AwsException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Represents an error while interacting with Amazon WorkSpaces.
|
8 |
+
*/
|
9 |
+
class WorkSpacesException extends AwsException {}
|
includes/aws/Aws/WorkSpaces/WorkSpacesClient.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws\WorkSpaces;
|
3 |
+
|
4 |
+
use Aws\AwsClient;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Amazon WorkSpaces client.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result createWorkspaces(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise createWorkspacesAsync(array $args = [])
|
11 |
+
* @method \Aws\Result describeWorkspaceBundles(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise describeWorkspaceBundlesAsync(array $args = [])
|
13 |
+
* @method \Aws\Result describeWorkspaceDirectories(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise describeWorkspaceDirectoriesAsync(array $args = [])
|
15 |
+
* @method \Aws\Result describeWorkspaces(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise describeWorkspacesAsync(array $args = [])
|
17 |
+
* @method \Aws\Result rebootWorkspaces(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise rebootWorkspacesAsync(array $args = [])
|
19 |
+
* @method \Aws\Result rebuildWorkspaces(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise rebuildWorkspacesAsync(array $args = [])
|
21 |
+
* @method \Aws\Result terminateWorkspaces(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise terminateWorkspacesAsync(array $args = [])
|
23 |
+
*/
|
24 |
+
class WorkSpacesClient extends AwsClient {}
|
includes/aws/Aws/WrappedHttpHandler.php
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Aws\Api\Parser\Exception\ParserException;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Converts an HTTP handler into a Command HTTP handler.
|
11 |
+
*
|
12 |
+
* HTTP handlers have the following signature:
|
13 |
+
* function(RequestInterface $request, array $options) : PromiseInterface
|
14 |
+
*
|
15 |
+
* The promise returned form an HTTP handler must resolve to a PSR-7 response
|
16 |
+
* object when fulfilled or an error array when rejected. The error array
|
17 |
+
* can contain the following data:
|
18 |
+
*
|
19 |
+
* - exception: (required, Exception) Exception that was encountered.
|
20 |
+
* - response: (ResponseInterface) PSR-7 response that was received (if a
|
21 |
+
* response) was received.
|
22 |
+
* - connection_error: (bool) True if the error is the result of failing to
|
23 |
+
* connect.
|
24 |
+
*/
|
25 |
+
class WrappedHttpHandler
|
26 |
+
{
|
27 |
+
private $httpHandler;
|
28 |
+
private $parser;
|
29 |
+
private $errorParser;
|
30 |
+
private $exceptionClass;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param callable $httpHandler Function that accepts a request and array
|
34 |
+
* of request options and returns a promise
|
35 |
+
* that fulfills with a response or rejects
|
36 |
+
* with an error array.
|
37 |
+
* @param callable $parser Function that accepts a response object
|
38 |
+
* and returns an AWS result object.
|
39 |
+
* @param callable $errorParser Function that parses a response object
|
40 |
+
* into AWS error data.
|
41 |
+
* @param string $exceptionClass Exception class to throw.
|
42 |
+
*/
|
43 |
+
public function __construct(
|
44 |
+
callable $httpHandler,
|
45 |
+
callable $parser,
|
46 |
+
callable $errorParser,
|
47 |
+
$exceptionClass = 'Aws\Exception\AwsException'
|
48 |
+
) {
|
49 |
+
$this->httpHandler = $httpHandler;
|
50 |
+
$this->parser = $parser;
|
51 |
+
$this->errorParser = $errorParser;
|
52 |
+
$this->exceptionClass = $exceptionClass;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Calls the simpler HTTP specific handler and wraps the returned promise
|
57 |
+
* with AWS specific values (e.g., a result object or AWS exception).
|
58 |
+
*
|
59 |
+
* @param CommandInterface $command Command being executed.
|
60 |
+
* @param RequestInterface $request Request to send.
|
61 |
+
*
|
62 |
+
* @return Promise\PromiseInterface
|
63 |
+
*/
|
64 |
+
public function __invoke(
|
65 |
+
CommandInterface $command,
|
66 |
+
RequestInterface $request
|
67 |
+
) {
|
68 |
+
$fn = $this->httpHandler;
|
69 |
+
|
70 |
+
return Promise\promise_for($fn($request, $command['@http'] ?: []))
|
71 |
+
->then(
|
72 |
+
function (ResponseInterface $res) use ($command, $request) {
|
73 |
+
return $this->parseResponse($command, $request, $res);
|
74 |
+
},
|
75 |
+
function ($err) use ($request, $command) {
|
76 |
+
if (is_array($err)) {
|
77 |
+
$exception = $this->parseError($err, $request, $command);
|
78 |
+
return new Promise\RejectedPromise($exception);
|
79 |
+
}
|
80 |
+
return new Promise\RejectedPromise($err);
|
81 |
+
}
|
82 |
+
);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @param CommandInterface $command
|
87 |
+
* @param RequestInterface $request
|
88 |
+
* @param ResponseInterface $response
|
89 |
+
*
|
90 |
+
* @return ResultInterface
|
91 |
+
*/
|
92 |
+
private function parseResponse(
|
93 |
+
CommandInterface $command,
|
94 |
+
RequestInterface $request,
|
95 |
+
ResponseInterface $response
|
96 |
+
) {
|
97 |
+
$parser = $this->parser;
|
98 |
+
$status = $response->getStatusCode();
|
99 |
+
$result = $status < 300
|
100 |
+
? $parser($command, $response)
|
101 |
+
: new Result();
|
102 |
+
|
103 |
+
$metadata = [
|
104 |
+
'statusCode' => $status,
|
105 |
+
'effectiveUri' => (string) $request->getUri(),
|
106 |
+
'headers' => []
|
107 |
+
];
|
108 |
+
|
109 |
+
// Bring headers into the metadata array.
|
110 |
+
foreach ($response->getHeaders() as $name => $values) {
|
111 |
+
$metadata['headers'][strtolower($name)] = $values[0];
|
112 |
+
}
|
113 |
+
|
114 |
+
$result['@metadata'] = $metadata;
|
115 |
+
|
116 |
+
return $result;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Parses a rejection into an AWS error.
|
121 |
+
*
|
122 |
+
* @param array $err Rejection error array.
|
123 |
+
* @param RequestInterface $request Request that was sent.
|
124 |
+
* @param CommandInterface $command Command being sent.
|
125 |
+
*
|
126 |
+
* @return \Exception
|
127 |
+
*/
|
128 |
+
private function parseError(
|
129 |
+
array $err,
|
130 |
+
RequestInterface $request,
|
131 |
+
CommandInterface $command
|
132 |
+
) {
|
133 |
+
if (!isset($err['exception'])) {
|
134 |
+
throw new \RuntimeException('The HTTP handler was rejected without an "exception" key value pair.');
|
135 |
+
}
|
136 |
+
|
137 |
+
$serviceError = "AWS HTTP error: " . $err['exception']->getMessage();
|
138 |
+
|
139 |
+
if (!isset($err['response'])) {
|
140 |
+
$parts = ['response' => null];
|
141 |
+
} else {
|
142 |
+
try {
|
143 |
+
$parts = call_user_func($this->errorParser, $err['response']);
|
144 |
+
$serviceError .= " {$parts['code']} ({$parts['type']}): "
|
145 |
+
. "{$parts['message']} - " . $err['response']->getBody();
|
146 |
+
} catch (ParserException $e) {
|
147 |
+
$parts = [];
|
148 |
+
$serviceError .= ' Unable to parse error information from '
|
149 |
+
. "response - {$e->getMessage()}";
|
150 |
+
}
|
151 |
+
|
152 |
+
$parts['response'] = $err['response'];
|
153 |
+
}
|
154 |
+
|
155 |
+
$parts['exception'] = $err['exception'];
|
156 |
+
$parts['request'] = $request;
|
157 |
+
$parts['connection_error'] = !empty($err['connection_error']);
|
158 |
+
|
159 |
+
return new $this->exceptionClass(
|
160 |
+
sprintf(
|
161 |
+
'Error executing "%s" on "%s"; %s',
|
162 |
+
$command->getName(),
|
163 |
+
$request->getUri(),
|
164 |
+
$serviceError
|
165 |
+
),
|
166 |
+
$command,
|
167 |
+
$parts,
|
168 |
+
$err['exception']
|
169 |
+
);
|
170 |
+
}
|
171 |
+
}
|
includes/aws/Aws/data/cloudfront/2015-09-17/api-2.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/api-2.json
|
3 |
+
return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2015-09-17', 'endpointPrefix' => 'cloudfront', 'globalEndpoint' => 'cloudfront.amazonaws.com', 'protocol' => 'rest-xml', 'serviceAbbreviation' => 'CloudFront', 'serviceFullName' => 'Amazon CloudFront', 'signatureVersion' => 'v4', ], 'operations' => [ 'CreateCloudFrontOriginAccessIdentity' => [ 'name' => 'CreateCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'CreateCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'CloudFrontOriginAccessIdentityAlreadyExists', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyCloudFrontOriginAccessIdentities', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'CreateDistribution' => [ 'name' => 'CreateDistribution2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/distribution', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateDistributionRequest', ], 'output' => [ 'shape' => 'CreateDistributionResult', ], 'errors' => [ [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'DistributionAlreadyExists', ], [ 'shape' => 'InvalidOrigin', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InvalidViewerCertificate', ], [ 'shape' => 'InvalidMinimumProtocolVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyDistributionCNAMEs', ], [ 'shape' => 'TooManyDistributions', ], [ 'shape' => 'InvalidDefaultRootObject', ], [ 'shape' => 'InvalidRelativePath', ], [ 'shape' => 'InvalidErrorCode', ], [ 'shape' => 'InvalidResponseCode', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidRequiredProtocol', ], [ 'shape' => 'NoSuchOrigin', ], [ 'shape' => 'TooManyOrigins', ], [ 'shape' => 'TooManyCacheBehaviors', ], [ 'shape' => 'TooManyCookieNamesInWhiteList', ], [ 'shape' => 'InvalidForwardCookies', ], [ 'shape' => 'TooManyHeadersInForwardedValues', ], [ 'shape' => 'InvalidHeadersForS3Origin', ], [ 'shape' => 'InconsistentQuantities', ], [ 'shape' => 'TooManyCertificates', ], [ 'shape' => 'InvalidLocationCode', ], [ 'shape' => 'InvalidGeoRestrictionParameter', ], [ 'shape' => 'InvalidProtocolSettings', ], [ 'shape' => 'InvalidTTLOrder', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'CreateInvalidation' => [ 'name' => 'CreateInvalidation2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateInvalidationRequest', ], 'output' => [ 'shape' => 'CreateInvalidationResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'BatchTooLarge', ], [ 'shape' => 'TooManyInvalidationsInProgress', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'CreateStreamingDistribution' => [ 'name' => 'CreateStreamingDistribution2015_09_17', 'http' => [ 'method' => 'POST', 'requestUri' => '/2015-09-17/streaming-distribution', 'responseCode' => 201, ], 'input' => [ 'shape' => 'CreateStreamingDistributionRequest', ], 'output' => [ 'shape' => 'CreateStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'StreamingDistributionAlreadyExists', ], [ 'shape' => 'InvalidOrigin', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'TooManyStreamingDistributionCNAMEs', ], [ 'shape' => 'TooManyStreamingDistributions', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'DeleteCloudFrontOriginAccessIdentity' => [ 'name' => 'DeleteCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteCloudFrontOriginAccessIdentityRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'CloudFrontOriginAccessIdentityInUse', ], ], ], 'DeleteDistribution' => [ 'name' => 'DeleteDistribution2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/distribution/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteDistributionRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'DistributionNotDisabled', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'PreconditionFailed', ], ], ], 'DeleteStreamingDistribution' => [ 'name' => 'DeleteStreamingDistribution2015_09_17', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}', 'responseCode' => 204, ], 'input' => [ 'shape' => 'DeleteStreamingDistributionRequest', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'StreamingDistributionNotDisabled', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'PreconditionFailed', ], ], ], 'GetCloudFrontOriginAccessIdentity' => [ 'name' => 'GetCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}', ], 'input' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetCloudFrontOriginAccessIdentityConfig' => [ 'name' => 'GetCloudFrontOriginAccessIdentityConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}/config', ], 'input' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityConfigRequest', ], 'output' => [ 'shape' => 'GetCloudFrontOriginAccessIdentityConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetDistribution' => [ 'name' => 'GetDistribution2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{Id}', ], 'input' => [ 'shape' => 'GetDistributionRequest', ], 'output' => [ 'shape' => 'GetDistributionResult', ], 'errors' => [ [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetDistributionConfig' => [ 'name' => 'GetDistributionConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{Id}/config', ], 'input' => [ 'shape' => 'GetDistributionConfigRequest', ], 'output' => [ 'shape' => 'GetDistributionConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetInvalidation' => [ 'name' => 'GetInvalidation2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation/{Id}', ], 'input' => [ 'shape' => 'GetInvalidationRequest', ], 'output' => [ 'shape' => 'GetInvalidationResult', ], 'errors' => [ [ 'shape' => 'NoSuchInvalidation', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetStreamingDistribution' => [ 'name' => 'GetStreamingDistribution2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}', ], 'input' => [ 'shape' => 'GetStreamingDistributionRequest', ], 'output' => [ 'shape' => 'GetStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'GetStreamingDistributionConfig' => [ 'name' => 'GetStreamingDistributionConfig2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}/config', ], 'input' => [ 'shape' => 'GetStreamingDistributionConfigRequest', ], 'output' => [ 'shape' => 'GetStreamingDistributionConfigResult', ], 'errors' => [ [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'ListCloudFrontOriginAccessIdentities' => [ 'name' => 'ListCloudFrontOriginAccessIdentities2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront', ], 'input' => [ 'shape' => 'ListCloudFrontOriginAccessIdentitiesRequest', ], 'output' => [ 'shape' => 'ListCloudFrontOriginAccessIdentitiesResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'ListDistributions' => [ 'name' => 'ListDistributions2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution', ], 'input' => [ 'shape' => 'ListDistributionsRequest', ], 'output' => [ 'shape' => 'ListDistributionsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'ListDistributionsByWebACLId' => [ 'name' => 'ListDistributionsByWebACLId2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distributionsByWebACLId/{WebACLId}', ], 'input' => [ 'shape' => 'ListDistributionsByWebACLIdRequest', ], 'output' => [ 'shape' => 'ListDistributionsByWebACLIdResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'ListInvalidations' => [ 'name' => 'ListInvalidations2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/distribution/{DistributionId}/invalidation', ], 'input' => [ 'shape' => 'ListInvalidationsRequest', ], 'output' => [ 'shape' => 'ListInvalidationsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'AccessDenied', ], ], ], 'ListStreamingDistributions' => [ 'name' => 'ListStreamingDistributions2015_09_17', 'http' => [ 'method' => 'GET', 'requestUri' => '/2015-09-17/streaming-distribution', ], 'input' => [ 'shape' => 'ListStreamingDistributionsRequest', ], 'output' => [ 'shape' => 'ListStreamingDistributionsResult', ], 'errors' => [ [ 'shape' => 'InvalidArgument', ], ], ], 'UpdateCloudFrontOriginAccessIdentity' => [ 'name' => 'UpdateCloudFrontOriginAccessIdentity2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/origin-access-identity/cloudfront/{Id}/config', ], 'input' => [ 'shape' => 'UpdateCloudFrontOriginAccessIdentityRequest', ], 'output' => [ 'shape' => 'UpdateCloudFrontOriginAccessIdentityResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchCloudFrontOriginAccessIdentity', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InconsistentQuantities', ], ], ], 'UpdateDistribution' => [ 'name' => 'UpdateDistribution2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/distribution/{Id}/config', ], 'input' => [ 'shape' => 'UpdateDistributionRequest', ], 'output' => [ 'shape' => 'UpdateDistributionResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchDistribution', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'TooManyDistributionCNAMEs', ], [ 'shape' => 'InvalidDefaultRootObject', ], [ 'shape' => 'InvalidRelativePath', ], [ 'shape' => 'InvalidErrorCode', ], [ 'shape' => 'InvalidResponseCode', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InvalidViewerCertificate', ], [ 'shape' => 'InvalidMinimumProtocolVersion', ], [ 'shape' => 'InvalidRequiredProtocol', ], [ 'shape' => 'NoSuchOrigin', ], [ 'shape' => 'TooManyOrigins', ], [ 'shape' => 'TooManyCacheBehaviors', ], [ 'shape' => 'TooManyCookieNamesInWhiteList', ], [ 'shape' => 'InvalidForwardCookies', ], [ 'shape' => 'TooManyHeadersInForwardedValues', ], [ 'shape' => 'InvalidHeadersForS3Origin', ], [ 'shape' => 'InconsistentQuantities', ], [ 'shape' => 'TooManyCertificates', ], [ 'shape' => 'InvalidLocationCode', ], [ 'shape' => 'InvalidGeoRestrictionParameter', ], [ 'shape' => 'InvalidTTLOrder', ], [ 'shape' => 'InvalidWebACLId', ], ], ], 'UpdateStreamingDistribution' => [ 'name' => 'UpdateStreamingDistribution2015_09_17', 'http' => [ 'method' => 'PUT', 'requestUri' => '/2015-09-17/streaming-distribution/{Id}/config', ], 'input' => [ 'shape' => 'UpdateStreamingDistributionRequest', ], 'output' => [ 'shape' => 'UpdateStreamingDistributionResult', ], 'errors' => [ [ 'shape' => 'AccessDenied', ], [ 'shape' => 'CNAMEAlreadyExists', ], [ 'shape' => 'IllegalUpdate', ], [ 'shape' => 'InvalidIfMatchVersion', ], [ 'shape' => 'MissingBody', ], [ 'shape' => 'NoSuchStreamingDistribution', ], [ 'shape' => 'PreconditionFailed', ], [ 'shape' => 'TooManyStreamingDistributionCNAMEs', ], [ 'shape' => 'InvalidArgument', ], [ 'shape' => 'InvalidOriginAccessIdentity', ], [ 'shape' => 'TooManyTrustedSigners', ], [ 'shape' => 'TrustedSignerDoesNotExist', ], [ 'shape' => 'InconsistentQuantities', ], ], ], ], 'shapes' => [ 'AccessDenied' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 403, ], 'exception' => true, ], 'ActiveTrustedSigners' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Quantity', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'SignerList', ], ], ], 'AliasList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'CNAME', ], ], 'Aliases' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'AliasList', ], ], ], 'AllowedMethods' => [ 'type' => 'structure', 'required' => [ 'Quantity', 'Items', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'MethodsList', ], 'CachedMethods' => [ 'shape' => 'CachedMethods', ], ], ], 'AwsAccountNumberList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'AwsAccountNumber', ], ], 'BatchTooLarge' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 413, ], 'exception' => true, ], 'CNAMEAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CacheBehavior' => [ 'type' => 'structure', 'required' => [ 'PathPattern', 'TargetOriginId', 'ForwardedValues', 'TrustedSigners', 'ViewerProtocolPolicy', 'MinTTL', ], 'members' => [ 'PathPattern' => [ 'shape' => 'string', ], 'TargetOriginId' => [ 'shape' => 'string', ], 'ForwardedValues' => [ 'shape' => 'ForwardedValues', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'ViewerProtocolPolicy' => [ 'shape' => 'ViewerProtocolPolicy', ], 'MinTTL' => [ 'shape' => 'long', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', ], 'SmoothStreaming' => [ 'shape' => 'boolean', ], 'DefaultTTL' => [ 'shape' => 'long', ], 'MaxTTL' => [ 'shape' => 'long', ], 'Compress' => [ 'shape' => 'boolean', ], ], ], 'CacheBehaviorList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CacheBehavior', 'locationName' => 'CacheBehavior', ], ], 'CacheBehaviors' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CacheBehaviorList', ], ], ], 'CachedMethods' => [ 'type' => 'structure', 'required' => [ 'Quantity', 'Items', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'MethodsList', ], ], ], 'CertificateSource' => [ 'type' => 'string', 'enum' => [ 'cloudfront', 'iam', ], ], 'CloudFrontOriginAccessIdentity' => [ 'type' => 'structure', 'required' => [ 'Id', 'S3CanonicalUserId', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'S3CanonicalUserId' => [ 'shape' => 'string', ], 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', ], ], ], 'CloudFrontOriginAccessIdentityAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CloudFrontOriginAccessIdentityConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'Comment', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'Comment' => [ 'shape' => 'string', ], ], ], 'CloudFrontOriginAccessIdentityInUse' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'CloudFrontOriginAccessIdentityList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CloudFrontOriginAccessIdentitySummaryList', ], ], ], 'CloudFrontOriginAccessIdentitySummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'S3CanonicalUserId', 'Comment', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'S3CanonicalUserId' => [ 'shape' => 'string', ], 'Comment' => [ 'shape' => 'string', ], ], ], 'CloudFrontOriginAccessIdentitySummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CloudFrontOriginAccessIdentitySummary', 'locationName' => 'CloudFrontOriginAccessIdentitySummary', ], ], 'CookieNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Name', ], ], 'CookieNames' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CookieNameList', ], ], ], 'CookiePreference' => [ 'type' => 'structure', 'required' => [ 'Forward', ], 'members' => [ 'Forward' => [ 'shape' => 'ItemSelection', ], 'WhitelistedNames' => [ 'shape' => 'CookieNames', ], ], ], 'CreateCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'CloudFrontOriginAccessIdentityConfig', ], 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', 'locationName' => 'CloudFrontOriginAccessIdentityConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'CreateCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'CreateDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionConfig', ], 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', 'locationName' => 'DistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'DistributionConfig', ], 'CreateDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'CreateInvalidationRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', 'InvalidationBatch', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'InvalidationBatch' => [ 'shape' => 'InvalidationBatch', 'locationName' => 'InvalidationBatch', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'InvalidationBatch', ], 'CreateInvalidationResult' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'Invalidation' => [ 'shape' => 'Invalidation', ], ], 'payload' => 'Invalidation', ], 'CreateStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'StreamingDistributionConfig', ], 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', 'locationName' => 'StreamingDistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], ], 'payload' => 'StreamingDistributionConfig', ], 'CreateStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'Location' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'Location', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'CustomErrorResponse' => [ 'type' => 'structure', 'required' => [ 'ErrorCode', ], 'members' => [ 'ErrorCode' => [ 'shape' => 'integer', ], 'ResponsePagePath' => [ 'shape' => 'string', ], 'ResponseCode' => [ 'shape' => 'string', ], 'ErrorCachingMinTTL' => [ 'shape' => 'long', ], ], ], 'CustomErrorResponseList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CustomErrorResponse', 'locationName' => 'CustomErrorResponse', ], ], 'CustomErrorResponses' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'CustomErrorResponseList', ], ], ], 'CustomOriginConfig' => [ 'type' => 'structure', 'required' => [ 'HTTPPort', 'HTTPSPort', 'OriginProtocolPolicy', ], 'members' => [ 'HTTPPort' => [ 'shape' => 'integer', ], 'HTTPSPort' => [ 'shape' => 'integer', ], 'OriginProtocolPolicy' => [ 'shape' => 'OriginProtocolPolicy', ], ], ], 'DefaultCacheBehavior' => [ 'type' => 'structure', 'required' => [ 'TargetOriginId', 'ForwardedValues', 'TrustedSigners', 'ViewerProtocolPolicy', 'MinTTL', ], 'members' => [ 'TargetOriginId' => [ 'shape' => 'string', ], 'ForwardedValues' => [ 'shape' => 'ForwardedValues', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'ViewerProtocolPolicy' => [ 'shape' => 'ViewerProtocolPolicy', ], 'MinTTL' => [ 'shape' => 'long', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', ], 'SmoothStreaming' => [ 'shape' => 'boolean', ], 'DefaultTTL' => [ 'shape' => 'long', ], 'MaxTTL' => [ 'shape' => 'long', ], 'Compress' => [ 'shape' => 'boolean', ], ], ], 'DeleteCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'DeleteDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'DeleteStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], ], 'Distribution' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'InProgressInvalidationBatches', 'DomainName', 'ActiveTrustedSigners', 'DistributionConfig', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'InProgressInvalidationBatches' => [ 'shape' => 'integer', ], 'DomainName' => [ 'shape' => 'string', ], 'ActiveTrustedSigners' => [ 'shape' => 'ActiveTrustedSigners', ], 'DistributionConfig' => [ 'shape' => 'DistributionConfig', ], ], ], 'DistributionAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'DistributionConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'Origins', 'DefaultCacheBehavior', 'Comment', 'Enabled', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'DefaultRootObject' => [ 'shape' => 'string', ], 'Origins' => [ 'shape' => 'Origins', ], 'DefaultCacheBehavior' => [ 'shape' => 'DefaultCacheBehavior', ], 'CacheBehaviors' => [ 'shape' => 'CacheBehaviors', ], 'CustomErrorResponses' => [ 'shape' => 'CustomErrorResponses', ], 'Comment' => [ 'shape' => 'string', ], 'Logging' => [ 'shape' => 'LoggingConfig', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], 'ViewerCertificate' => [ 'shape' => 'ViewerCertificate', ], 'Restrictions' => [ 'shape' => 'Restrictions', ], 'WebACLId' => [ 'shape' => 'string', ], ], ], 'DistributionList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'DistributionSummaryList', ], ], ], 'DistributionNotDisabled' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'DistributionSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'DomainName', 'Aliases', 'Origins', 'DefaultCacheBehavior', 'CacheBehaviors', 'CustomErrorResponses', 'Comment', 'PriceClass', 'Enabled', 'ViewerCertificate', 'Restrictions', 'WebACLId', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'Origins' => [ 'shape' => 'Origins', ], 'DefaultCacheBehavior' => [ 'shape' => 'DefaultCacheBehavior', ], 'CacheBehaviors' => [ 'shape' => 'CacheBehaviors', ], 'CustomErrorResponses' => [ 'shape' => 'CustomErrorResponses', ], 'Comment' => [ 'shape' => 'string', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], 'ViewerCertificate' => [ 'shape' => 'ViewerCertificate', ], 'Restrictions' => [ 'shape' => 'Restrictions', ], 'WebACLId' => [ 'shape' => 'string', ], ], ], 'DistributionSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DistributionSummary', 'locationName' => 'DistributionSummary', ], ], 'ForwardedValues' => [ 'type' => 'structure', 'required' => [ 'QueryString', 'Cookies', ], 'members' => [ 'QueryString' => [ 'shape' => 'boolean', ], 'Cookies' => [ 'shape' => 'CookiePreference', ], 'Headers' => [ 'shape' => 'Headers', ], ], ], 'GeoRestriction' => [ 'type' => 'structure', 'required' => [ 'RestrictionType', 'Quantity', ], 'members' => [ 'RestrictionType' => [ 'shape' => 'GeoRestrictionType', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'LocationList', ], ], ], 'GeoRestrictionType' => [ 'type' => 'string', 'enum' => [ 'blacklist', 'whitelist', 'none', ], ], 'GetCloudFrontOriginAccessIdentityConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetCloudFrontOriginAccessIdentityConfigResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'GetCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'GetDistributionConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetDistributionConfigResult' => [ 'type' => 'structure', 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'DistributionConfig', ], 'GetDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'GetInvalidationRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', 'Id', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetInvalidationResult' => [ 'type' => 'structure', 'members' => [ 'Invalidation' => [ 'shape' => 'Invalidation', ], ], 'payload' => 'Invalidation', ], 'GetStreamingDistributionConfigRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetStreamingDistributionConfigResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistributionConfig', ], 'GetStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'Id', ], 'members' => [ 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], ], ], 'GetStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'HeaderList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Name', ], ], 'Headers' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'HeaderList', ], ], ], 'IllegalUpdate' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InconsistentQuantities' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidArgument' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidDefaultRootObject' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidErrorCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidForwardCookies' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidGeoRestrictionParameter' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidHeadersForS3Origin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidIfMatchVersion' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidLocationCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidMinimumProtocolVersion' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidOrigin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidOriginAccessIdentity' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidProtocolSettings' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidRelativePath' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidRequiredProtocol' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidResponseCode' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidTTLOrder' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidViewerCertificate' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'InvalidWebACLId' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'Invalidation' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'CreateTime', 'InvalidationBatch', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'CreateTime' => [ 'shape' => 'timestamp', ], 'InvalidationBatch' => [ 'shape' => 'InvalidationBatch', ], ], ], 'InvalidationBatch' => [ 'type' => 'structure', 'required' => [ 'Paths', 'CallerReference', ], 'members' => [ 'Paths' => [ 'shape' => 'Paths', ], 'CallerReference' => [ 'shape' => 'string', ], ], ], 'InvalidationList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'InvalidationSummaryList', ], ], ], 'InvalidationSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'CreateTime', 'Status', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'CreateTime' => [ 'shape' => 'timestamp', ], 'Status' => [ 'shape' => 'string', ], ], ], 'InvalidationSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'InvalidationSummary', 'locationName' => 'InvalidationSummary', ], ], 'ItemSelection' => [ 'type' => 'string', 'enum' => [ 'none', 'whitelist', 'all', ], ], 'KeyPairIdList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'KeyPairId', ], ], 'KeyPairIds' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'KeyPairIdList', ], ], ], 'ListCloudFrontOriginAccessIdentitiesRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListCloudFrontOriginAccessIdentitiesResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentityList' => [ 'shape' => 'CloudFrontOriginAccessIdentityList', ], ], 'payload' => 'CloudFrontOriginAccessIdentityList', ], 'ListDistributionsByWebACLIdRequest' => [ 'type' => 'structure', 'required' => [ 'WebACLId', ], 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], 'WebACLId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'WebACLId', ], ], ], 'ListDistributionsByWebACLIdResult' => [ 'type' => 'structure', 'members' => [ 'DistributionList' => [ 'shape' => 'DistributionList', ], ], 'payload' => 'DistributionList', ], 'ListDistributionsRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListDistributionsResult' => [ 'type' => 'structure', 'members' => [ 'DistributionList' => [ 'shape' => 'DistributionList', ], ], 'payload' => 'DistributionList', ], 'ListInvalidationsRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionId', ], 'members' => [ 'DistributionId' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'DistributionId', ], 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListInvalidationsResult' => [ 'type' => 'structure', 'members' => [ 'InvalidationList' => [ 'shape' => 'InvalidationList', ], ], 'payload' => 'InvalidationList', ], 'ListStreamingDistributionsRequest' => [ 'type' => 'structure', 'members' => [ 'Marker' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'Marker', ], 'MaxItems' => [ 'shape' => 'string', 'location' => 'querystring', 'locationName' => 'MaxItems', ], ], ], 'ListStreamingDistributionsResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistributionList' => [ 'shape' => 'StreamingDistributionList', ], ], 'payload' => 'StreamingDistributionList', ], 'LocationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Location', ], ], 'LoggingConfig' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'IncludeCookies', 'Bucket', 'Prefix', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'IncludeCookies' => [ 'shape' => 'boolean', ], 'Bucket' => [ 'shape' => 'string', ], 'Prefix' => [ 'shape' => 'string', ], ], ], 'Method' => [ 'type' => 'string', 'enum' => [ 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE', ], ], 'MethodsList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Method', 'locationName' => 'Method', ], ], 'MinimumProtocolVersion' => [ 'type' => 'string', 'enum' => [ 'SSLv3', 'TLSv1', ], ], 'MissingBody' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'NoSuchCloudFrontOriginAccessIdentity' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchDistribution' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchInvalidation' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchOrigin' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'NoSuchStreamingDistribution' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 404, ], 'exception' => true, ], 'Origin' => [ 'type' => 'structure', 'required' => [ 'Id', 'DomainName', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'DomainName' => [ 'shape' => 'string', ], 'OriginPath' => [ 'shape' => 'string', ], 'S3OriginConfig' => [ 'shape' => 'S3OriginConfig', ], 'CustomOriginConfig' => [ 'shape' => 'CustomOriginConfig', ], ], ], 'OriginList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Origin', 'locationName' => 'Origin', ], 'min' => 1, ], 'OriginProtocolPolicy' => [ 'type' => 'string', 'enum' => [ 'http-only', 'match-viewer', ], ], 'Origins' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'OriginList', ], ], ], 'PathList' => [ 'type' => 'list', 'member' => [ 'shape' => 'string', 'locationName' => 'Path', ], ], 'Paths' => [ 'type' => 'structure', 'required' => [ 'Quantity', ], 'members' => [ 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'PathList', ], ], ], 'PreconditionFailed' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 412, ], 'exception' => true, ], 'PriceClass' => [ 'type' => 'string', 'enum' => [ 'PriceClass_100', 'PriceClass_200', 'PriceClass_All', ], ], 'Restrictions' => [ 'type' => 'structure', 'required' => [ 'GeoRestriction', ], 'members' => [ 'GeoRestriction' => [ 'shape' => 'GeoRestriction', ], ], ], 'S3Origin' => [ 'type' => 'structure', 'required' => [ 'DomainName', 'OriginAccessIdentity', ], 'members' => [ 'DomainName' => [ 'shape' => 'string', ], 'OriginAccessIdentity' => [ 'shape' => 'string', ], ], ], 'S3OriginConfig' => [ 'type' => 'structure', 'required' => [ 'OriginAccessIdentity', ], 'members' => [ 'OriginAccessIdentity' => [ 'shape' => 'string', ], ], ], 'SSLSupportMethod' => [ 'type' => 'string', 'enum' => [ 'sni-only', 'vip', ], ], 'Signer' => [ 'type' => 'structure', 'members' => [ 'AwsAccountNumber' => [ 'shape' => 'string', ], 'KeyPairIds' => [ 'shape' => 'KeyPairIds', ], ], ], 'SignerList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Signer', 'locationName' => 'Signer', ], ], 'StreamingDistribution' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'DomainName', 'ActiveTrustedSigners', 'StreamingDistributionConfig', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'ActiveTrustedSigners' => [ 'shape' => 'ActiveTrustedSigners', ], 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', ], ], ], 'StreamingDistributionAlreadyExists' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'StreamingDistributionConfig' => [ 'type' => 'structure', 'required' => [ 'CallerReference', 'S3Origin', 'Comment', 'TrustedSigners', 'Enabled', ], 'members' => [ 'CallerReference' => [ 'shape' => 'string', ], 'S3Origin' => [ 'shape' => 'S3Origin', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'Comment' => [ 'shape' => 'string', ], 'Logging' => [ 'shape' => 'StreamingLoggingConfig', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], ], ], 'StreamingDistributionList' => [ 'type' => 'structure', 'required' => [ 'Marker', 'MaxItems', 'IsTruncated', 'Quantity', ], 'members' => [ 'Marker' => [ 'shape' => 'string', ], 'NextMarker' => [ 'shape' => 'string', ], 'MaxItems' => [ 'shape' => 'integer', ], 'IsTruncated' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'StreamingDistributionSummaryList', ], ], ], 'StreamingDistributionNotDisabled' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 409, ], 'exception' => true, ], 'StreamingDistributionSummary' => [ 'type' => 'structure', 'required' => [ 'Id', 'Status', 'LastModifiedTime', 'DomainName', 'S3Origin', 'Aliases', 'TrustedSigners', 'Comment', 'PriceClass', 'Enabled', ], 'members' => [ 'Id' => [ 'shape' => 'string', ], 'Status' => [ 'shape' => 'string', ], 'LastModifiedTime' => [ 'shape' => 'timestamp', ], 'DomainName' => [ 'shape' => 'string', ], 'S3Origin' => [ 'shape' => 'S3Origin', ], 'Aliases' => [ 'shape' => 'Aliases', ], 'TrustedSigners' => [ 'shape' => 'TrustedSigners', ], 'Comment' => [ 'shape' => 'string', ], 'PriceClass' => [ 'shape' => 'PriceClass', ], 'Enabled' => [ 'shape' => 'boolean', ], ], ], 'StreamingDistributionSummaryList' => [ 'type' => 'list', 'member' => [ 'shape' => 'StreamingDistributionSummary', 'locationName' => 'StreamingDistributionSummary', ], ], 'StreamingLoggingConfig' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Bucket', 'Prefix', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Bucket' => [ 'shape' => 'string', ], 'Prefix' => [ 'shape' => 'string', ], ], ], 'TooManyCacheBehaviors' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCertificates' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCloudFrontOriginAccessIdentities' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyCookieNamesInWhiteList' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyDistributionCNAMEs' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyDistributions' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyHeadersInForwardedValues' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyInvalidationsInProgress' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyOrigins' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyStreamingDistributionCNAMEs' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyStreamingDistributions' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TooManyTrustedSigners' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TrustedSignerDoesNotExist' => [ 'type' => 'structure', 'members' => [ 'Message' => [ 'shape' => 'string', ], ], 'error' => [ 'httpStatusCode' => 400, ], 'exception' => true, ], 'TrustedSigners' => [ 'type' => 'structure', 'required' => [ 'Enabled', 'Quantity', ], 'members' => [ 'Enabled' => [ 'shape' => 'boolean', ], 'Quantity' => [ 'shape' => 'integer', ], 'Items' => [ 'shape' => 'AwsAccountNumberList', ], ], ], 'UpdateCloudFrontOriginAccessIdentityRequest' => [ 'type' => 'structure', 'required' => [ 'CloudFrontOriginAccessIdentityConfig', 'Id', ], 'members' => [ 'CloudFrontOriginAccessIdentityConfig' => [ 'shape' => 'CloudFrontOriginAccessIdentityConfig', 'locationName' => 'CloudFrontOriginAccessIdentityConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'CloudFrontOriginAccessIdentityConfig', ], 'UpdateCloudFrontOriginAccessIdentityResult' => [ 'type' => 'structure', 'members' => [ 'CloudFrontOriginAccessIdentity' => [ 'shape' => 'CloudFrontOriginAccessIdentity', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'CloudFrontOriginAccessIdentity', ], 'UpdateDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'DistributionConfig', 'Id', ], 'members' => [ 'DistributionConfig' => [ 'shape' => 'DistributionConfig', 'locationName' => 'DistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'DistributionConfig', ], 'UpdateDistributionResult' => [ 'type' => 'structure', 'members' => [ 'Distribution' => [ 'shape' => 'Distribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'Distribution', ], 'UpdateStreamingDistributionRequest' => [ 'type' => 'structure', 'required' => [ 'StreamingDistributionConfig', 'Id', ], 'members' => [ 'StreamingDistributionConfig' => [ 'shape' => 'StreamingDistributionConfig', 'locationName' => 'StreamingDistributionConfig', 'xmlNamespace' => [ 'uri' => 'http://cloudfront.amazonaws.com/doc/2015-09-17/', ], ], 'Id' => [ 'shape' => 'string', 'location' => 'uri', 'locationName' => 'Id', ], 'IfMatch' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'If-Match', ], ], 'payload' => 'StreamingDistributionConfig', ], 'UpdateStreamingDistributionResult' => [ 'type' => 'structure', 'members' => [ 'StreamingDistribution' => [ 'shape' => 'StreamingDistribution', ], 'ETag' => [ 'shape' => 'string', 'location' => 'header', 'locationName' => 'ETag', ], ], 'payload' => 'StreamingDistribution', ], 'ViewerCertificate' => [ 'type' => 'structure', 'members' => [ 'Certificate' => [ 'shape' => 'string', ], 'CertificateSource' => [ 'shape' => 'CertificateSource', ], 'SSLSupportMethod' => [ 'shape' => 'SSLSupportMethod', ], 'MinimumProtocolVersion' => [ 'shape' => 'MinimumProtocolVersion', ], 'IAMCertificateId' => [ 'shape' => 'string', 'deprecated' => true, ], 'CloudFrontDefaultCertificate' => [ 'shape' => 'boolean', 'deprecated' => true, ], ], ], 'ViewerProtocolPolicy' => [ 'type' => 'string', 'enum' => [ 'allow-all', 'https-only', 'redirect-to-https', ], ], 'boolean' => [ 'type' => 'boolean', ], 'integer' => [ 'type' => 'integer', ], 'long' => [ 'type' => 'long', ], 'string' => [ 'type' => 'string', ], 'timestamp' => [ 'type' => 'timestamp', ], ],];
|
includes/aws/Aws/data/cloudfront/2015-09-17/examples-1.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/examples-1.json
|
3 |
+
return [ 'version' => '1.0', 'examples' => [],];
|
includes/aws/Aws/data/cloudfront/2015-09-17/paginators-1.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/paginators-1.json
|
3 |
+
return [ 'pagination' => [ 'ListCloudFrontOriginAccessIdentities' => [ 'input_token' => 'Marker', 'output_token' => 'CloudFrontOriginAccessIdentityList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'CloudFrontOriginAccessIdentityList.IsTruncated', 'result_key' => 'CloudFrontOriginAccessIdentityList.Items', ], 'ListDistributions' => [ 'input_token' => 'Marker', 'output_token' => 'DistributionList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'DistributionList.IsTruncated', 'result_key' => 'DistributionList.Items', ], 'ListInvalidations' => [ 'input_token' => 'Marker', 'output_token' => 'InvalidationList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'InvalidationList.IsTruncated', 'result_key' => 'InvalidationList.Items', ], 'ListStreamingDistributions' => [ 'input_token' => 'Marker', 'output_token' => 'StreamingDistributionList.NextMarker', 'limit_key' => 'MaxItems', 'more_results' => 'StreamingDistributionList.IsTruncated', 'result_key' => 'StreamingDistributionList.Items', ], ],];
|
includes/aws/Aws/data/cloudfront/2015-09-17/waiters-2.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/cloudfront/2015-09-17/waiters-2.json
|
3 |
+
return [ 'version' => 2, 'waiters' => [ 'DistributionDeployed' => [ 'delay' => 60, 'operation' => 'GetDistribution', 'maxAttempts' => 25, 'description' => 'Wait until a distribution is deployed.', 'acceptors' => [ [ 'expected' => 'Deployed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], 'InvalidationCompleted' => [ 'delay' => 20, 'operation' => 'GetInvalidation', 'maxAttempts' => 30, 'description' => 'Wait until an invalidation has completed.', 'acceptors' => [ [ 'expected' => 'Completed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], 'StreamingDistributionDeployed' => [ 'delay' => 60, 'operation' => 'GetStreamingDistribution', 'maxAttempts' => 25, 'description' => 'Wait until a streaming distribution is deployed.', 'acceptors' => [ [ 'expected' => 'Deployed', 'matcher' => 'path', 'state' => 'success', 'argument' => 'Status', ], ], ], ],];
|
includes/aws/Aws/data/config/2014-11-12/api-2.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/config/2014-11-12/api-2.json
|
3 |
+
return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2014-11-12', 'endpointPrefix' => 'config', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'Config Service', 'serviceFullName' => 'AWS Config', 'signatureVersion' => 'v4', 'targetPrefix' => 'StarlingDoveService', ], 'operations' => [ 'DeleteConfigRule' => [ 'name' => 'DeleteConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeleteConfigRuleRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], [ 'shape' => 'ResourceInUseException', ], ], ], 'DeleteDeliveryChannel' => [ 'name' => 'DeleteDeliveryChannel', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeleteDeliveryChannelRequest', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], [ 'shape' => 'LastDeliveryChannelDeleteFailedException', ], ], ], 'DeliverConfigSnapshot' => [ 'name' => 'DeliverConfigSnapshot', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DeliverConfigSnapshotRequest', ], 'output' => [ 'shape' => 'DeliverConfigSnapshotResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'NoRunningConfigurationRecorderException', ], ], ], 'DescribeComplianceByConfigRule' => [ 'name' => 'DescribeComplianceByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeComplianceByConfigRuleRequest', ], 'output' => [ 'shape' => 'DescribeComplianceByConfigRuleResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeComplianceByResource' => [ 'name' => 'DescribeComplianceByResource', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeComplianceByResourceRequest', ], 'output' => [ 'shape' => 'DescribeComplianceByResourceResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidNextTokenException', ], ], ], 'DescribeConfigRuleEvaluationStatus' => [ 'name' => 'DescribeConfigRuleEvaluationStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigRuleEvaluationStatusRequest', ], 'output' => [ 'shape' => 'DescribeConfigRuleEvaluationStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeConfigRules' => [ 'name' => 'DescribeConfigRules', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigRulesRequest', ], 'output' => [ 'shape' => 'DescribeConfigRulesResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'DescribeConfigurationRecorderStatus' => [ 'name' => 'DescribeConfigurationRecorderStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigurationRecorderStatusRequest', ], 'output' => [ 'shape' => 'DescribeConfigurationRecorderStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], 'DescribeConfigurationRecorders' => [ 'name' => 'DescribeConfigurationRecorders', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeConfigurationRecordersRequest', ], 'output' => [ 'shape' => 'DescribeConfigurationRecordersResponse', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], 'DescribeDeliveryChannelStatus' => [ 'name' => 'DescribeDeliveryChannelStatus', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeDeliveryChannelStatusRequest', ], 'output' => [ 'shape' => 'DescribeDeliveryChannelStatusResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], ], ], 'DescribeDeliveryChannels' => [ 'name' => 'DescribeDeliveryChannels', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'DescribeDeliveryChannelsRequest', ], 'output' => [ 'shape' => 'DescribeDeliveryChannelsResponse', ], 'errors' => [ [ 'shape' => 'NoSuchDeliveryChannelException', ], ], ], 'GetComplianceDetailsByConfigRule' => [ 'name' => 'GetComplianceDetailsByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceDetailsByConfigRuleRequest', ], 'output' => [ 'shape' => 'GetComplianceDetailsByConfigRuleResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'GetComplianceDetailsByResource' => [ 'name' => 'GetComplianceDetailsByResource', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceDetailsByResourceRequest', ], 'output' => [ 'shape' => 'GetComplianceDetailsByResourceResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], ], ], 'GetComplianceSummaryByConfigRule' => [ 'name' => 'GetComplianceSummaryByConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'output' => [ 'shape' => 'GetComplianceSummaryByConfigRuleResponse', ], ], 'GetComplianceSummaryByResourceType' => [ 'name' => 'GetComplianceSummaryByResourceType', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetComplianceSummaryByResourceTypeRequest', ], 'output' => [ 'shape' => 'GetComplianceSummaryByResourceTypeResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], ], ], 'GetResourceConfigHistory' => [ 'name' => 'GetResourceConfigHistory', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'GetResourceConfigHistoryRequest', ], 'output' => [ 'shape' => 'GetResourceConfigHistoryResponse', ], 'errors' => [ [ 'shape' => 'ValidationException', ], [ 'shape' => 'InvalidTimeRangeException', ], [ 'shape' => 'InvalidLimitException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'ResourceNotDiscoveredException', ], ], ], 'ListDiscoveredResources' => [ 'name' => 'ListDiscoveredResources', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'ListDiscoveredResourcesRequest', ], 'output' => [ 'shape' => 'ListDiscoveredResourcesResponse', ], 'errors' => [ [ 'shape' => 'ValidationException', ], [ 'shape' => 'InvalidLimitException', ], [ 'shape' => 'InvalidNextTokenException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], ], ], 'PutConfigRule' => [ 'name' => 'PutConfigRule', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutConfigRuleRequest', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'MaxNumberOfConfigRulesExceededException', ], [ 'shape' => 'ResourceInUseException', ], [ 'shape' => 'InsufficientPermissionsException', ], ], ], 'PutConfigurationRecorder' => [ 'name' => 'PutConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'MaxNumberOfConfigurationRecordersExceededException', ], [ 'shape' => 'InvalidConfigurationRecorderNameException', ], [ 'shape' => 'InvalidRoleException', ], [ 'shape' => 'InvalidRecordingGroupException', ], ], ], 'PutDeliveryChannel' => [ 'name' => 'PutDeliveryChannel', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutDeliveryChannelRequest', ], 'errors' => [ [ 'shape' => 'MaxNumberOfDeliveryChannelsExceededException', ], [ 'shape' => 'NoAvailableConfigurationRecorderException', ], [ 'shape' => 'InvalidDeliveryChannelNameException', ], [ 'shape' => 'NoSuchBucketException', ], [ 'shape' => 'InvalidS3KeyPrefixException', ], [ 'shape' => 'InvalidSNSTopicARNException', ], [ 'shape' => 'InsufficientDeliveryPolicyException', ], ], ], 'PutEvaluations' => [ 'name' => 'PutEvaluations', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'PutEvaluationsRequest', ], 'output' => [ 'shape' => 'PutEvaluationsResponse', ], 'errors' => [ [ 'shape' => 'InvalidParameterValueException', ], [ 'shape' => 'InvalidResultTokenException', ], [ 'shape' => 'NoSuchConfigRuleException', ], ], ], 'StartConfigurationRecorder' => [ 'name' => 'StartConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'StartConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], [ 'shape' => 'NoAvailableDeliveryChannelException', ], ], ], 'StopConfigurationRecorder' => [ 'name' => 'StopConfigurationRecorder', 'http' => [ 'method' => 'POST', 'requestUri' => '/', ], 'input' => [ 'shape' => 'StopConfigurationRecorderRequest', ], 'errors' => [ [ 'shape' => 'NoSuchConfigurationRecorderException', ], ], ], ], 'shapes' => [ 'ARN' => [ 'type' => 'string', ], 'AccountId' => [ 'type' => 'string', ], 'AllSupported' => [ 'type' => 'boolean', ], 'AvailabilityZone' => [ 'type' => 'string', ], 'AwsRegion' => [ 'type' => 'string', ], 'Boolean' => [ 'type' => 'boolean', ], 'ChannelName' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'ChronologicalOrder' => [ 'type' => 'string', 'enum' => [ 'Reverse', 'Forward', ], ], 'Compliance' => [ 'type' => 'structure', 'members' => [ 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'ComplianceContributorCount' => [ 'shape' => 'ComplianceContributorCount', ], ], ], 'ComplianceByConfigRule' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'Compliance' => [ 'shape' => 'Compliance', ], ], ], 'ComplianceByConfigRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceByConfigRule', ], ], 'ComplianceByResource' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'Compliance' => [ 'shape' => 'Compliance', ], ], ], 'ComplianceByResources' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceByResource', ], ], 'ComplianceContributorCount' => [ 'type' => 'structure', 'members' => [ 'CappedCount' => [ 'shape' => 'Integer', ], 'CapExceeded' => [ 'shape' => 'Boolean', ], ], ], 'ComplianceResourceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit256', ], 'max' => 100, 'min' => 0, ], 'ComplianceSummariesByResourceType' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceSummaryByResourceType', ], ], 'ComplianceSummary' => [ 'type' => 'structure', 'members' => [ 'CompliantResourceCount' => [ 'shape' => 'ComplianceContributorCount', ], 'NonCompliantResourceCount' => [ 'shape' => 'ComplianceContributorCount', ], 'ComplianceSummaryTimestamp' => [ 'shape' => 'Date', ], ], ], 'ComplianceSummaryByResourceType' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceSummary' => [ 'shape' => 'ComplianceSummary', ], ], ], 'ComplianceType' => [ 'type' => 'string', 'enum' => [ 'COMPLIANT', 'NON_COMPLIANT', 'NOT_APPLICABLE', 'INSUFFICIENT_DATA', ], ], 'ComplianceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'ComplianceType', ], 'max' => 3, 'min' => 0, ], 'ConfigExportDeliveryInfo' => [ 'type' => 'structure', 'members' => [ 'lastStatus' => [ 'shape' => 'DeliveryStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastAttemptTime' => [ 'shape' => 'Date', ], 'lastSuccessfulTime' => [ 'shape' => 'Date', ], 'nextDeliveryTime' => [ 'shape' => 'Date', ], ], ], 'ConfigRule' => [ 'type' => 'structure', 'required' => [ 'Source', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ConfigRuleArn' => [ 'shape' => 'String', ], 'ConfigRuleId' => [ 'shape' => 'String', ], 'Description' => [ 'shape' => 'EmptiableStringWithCharLimit256', ], 'Scope' => [ 'shape' => 'Scope', ], 'Source' => [ 'shape' => 'Source', ], 'InputParameters' => [ 'shape' => 'StringWithCharLimit256', ], 'MaximumExecutionFrequency' => [ 'shape' => 'MaximumExecutionFrequency', ], 'ConfigRuleState' => [ 'shape' => 'ConfigRuleState', ], ], ], 'ConfigRuleEvaluationStatus' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ConfigRuleArn' => [ 'shape' => 'String', ], 'ConfigRuleId' => [ 'shape' => 'String', ], 'LastSuccessfulInvocationTime' => [ 'shape' => 'Date', ], 'LastFailedInvocationTime' => [ 'shape' => 'Date', ], 'LastSuccessfulEvaluationTime' => [ 'shape' => 'Date', ], 'LastFailedEvaluationTime' => [ 'shape' => 'Date', ], 'FirstActivatedTime' => [ 'shape' => 'Date', ], 'LastErrorCode' => [ 'shape' => 'String', ], 'LastErrorMessage' => [ 'shape' => 'String', ], 'FirstEvaluationStarted' => [ 'shape' => 'Boolean', ], ], ], 'ConfigRuleEvaluationStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigRuleEvaluationStatus', ], ], 'ConfigRuleNames' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit64', ], 'max' => 25, 'min' => 0, ], 'ConfigRuleState' => [ 'type' => 'string', 'enum' => [ 'ACTIVE', 'DELETING', ], ], 'ConfigRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigRule', ], ], 'ConfigSnapshotDeliveryProperties' => [ 'type' => 'structure', 'members' => [ 'deliveryFrequency' => [ 'shape' => 'MaximumExecutionFrequency', ], ], ], 'ConfigStreamDeliveryInfo' => [ 'type' => 'structure', 'members' => [ 'lastStatus' => [ 'shape' => 'DeliveryStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastStatusChangeTime' => [ 'shape' => 'Date', ], ], ], 'Configuration' => [ 'type' => 'string', ], 'ConfigurationItem' => [ 'type' => 'structure', 'members' => [ 'version' => [ 'shape' => 'Version', ], 'accountId' => [ 'shape' => 'AccountId', ], 'configurationItemCaptureTime' => [ 'shape' => 'ConfigurationItemCaptureTime', ], 'configurationItemStatus' => [ 'shape' => 'ConfigurationItemStatus', ], 'configurationStateId' => [ 'shape' => 'ConfigurationStateId', ], 'configurationItemMD5Hash' => [ 'shape' => 'ConfigurationItemMD5Hash', ], 'arn' => [ 'shape' => 'ARN', ], 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'awsRegion' => [ 'shape' => 'AwsRegion', ], 'availabilityZone' => [ 'shape' => 'AvailabilityZone', ], 'resourceCreationTime' => [ 'shape' => 'ResourceCreationTime', ], 'tags' => [ 'shape' => 'Tags', ], 'relatedEvents' => [ 'shape' => 'RelatedEventList', ], 'relationships' => [ 'shape' => 'RelationshipList', ], 'configuration' => [ 'shape' => 'Configuration', ], ], ], 'ConfigurationItemCaptureTime' => [ 'type' => 'timestamp', ], 'ConfigurationItemList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationItem', ], ], 'ConfigurationItemMD5Hash' => [ 'type' => 'string', ], 'ConfigurationItemStatus' => [ 'type' => 'string', 'enum' => [ 'Ok', 'Failed', 'Discovered', 'Deleted', ], ], 'ConfigurationRecorder' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'RecorderName', ], 'roleARN' => [ 'shape' => 'String', ], 'recordingGroup' => [ 'shape' => 'RecordingGroup', ], ], ], 'ConfigurationRecorderList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationRecorder', ], ], 'ConfigurationRecorderNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'RecorderName', ], ], 'ConfigurationRecorderStatus' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'String', ], 'lastStartTime' => [ 'shape' => 'Date', ], 'lastStopTime' => [ 'shape' => 'Date', ], 'recording' => [ 'shape' => 'Boolean', ], 'lastStatus' => [ 'shape' => 'RecorderStatus', ], 'lastErrorCode' => [ 'shape' => 'String', ], 'lastErrorMessage' => [ 'shape' => 'String', ], 'lastStatusChangeTime' => [ 'shape' => 'Date', ], ], ], 'ConfigurationRecorderStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ConfigurationRecorderStatus', ], ], 'ConfigurationStateId' => [ 'type' => 'string', ], 'Date' => [ 'type' => 'timestamp', ], 'DeleteConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRuleName', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], ], ], 'DeleteDeliveryChannelRequest' => [ 'type' => 'structure', 'required' => [ 'DeliveryChannelName', ], 'members' => [ 'DeliveryChannelName' => [ 'shape' => 'ChannelName', ], ], ], 'DeliverConfigSnapshotRequest' => [ 'type' => 'structure', 'required' => [ 'deliveryChannelName', ], 'members' => [ 'deliveryChannelName' => [ 'shape' => 'ChannelName', ], ], ], 'DeliverConfigSnapshotResponse' => [ 'type' => 'structure', 'members' => [ 'configSnapshotId' => [ 'shape' => 'String', ], ], ], 'DeliveryChannel' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'ChannelName', ], 's3BucketName' => [ 'shape' => 'String', ], 's3KeyPrefix' => [ 'shape' => 'String', ], 'snsTopicARN' => [ 'shape' => 'String', ], 'configSnapshotDeliveryProperties' => [ 'shape' => 'ConfigSnapshotDeliveryProperties', ], ], ], 'DeliveryChannelList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeliveryChannel', ], ], 'DeliveryChannelNameList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ChannelName', ], ], 'DeliveryChannelStatus' => [ 'type' => 'structure', 'members' => [ 'name' => [ 'shape' => 'String', ], 'configSnapshotDeliveryInfo' => [ 'shape' => 'ConfigExportDeliveryInfo', ], 'configHistoryDeliveryInfo' => [ 'shape' => 'ConfigExportDeliveryInfo', ], 'configStreamDeliveryInfo' => [ 'shape' => 'ConfigStreamDeliveryInfo', ], ], ], 'DeliveryChannelStatusList' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeliveryChannelStatus', ], ], 'DeliveryStatus' => [ 'type' => 'string', 'enum' => [ 'Success', 'Failure', 'Not_Applicable', ], ], 'DescribeComplianceByConfigRuleRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeComplianceByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceByConfigRules' => [ 'shape' => 'ComplianceByConfigRules', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeComplianceByResourceRequest' => [ 'type' => 'structure', 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'Limit' => [ 'shape' => 'Limit', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'DescribeComplianceByResourceResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceByResources' => [ 'shape' => 'ComplianceByResources', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'DescribeConfigRuleEvaluationStatusRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], ], ], 'DescribeConfigRuleEvaluationStatusResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigRulesEvaluationStatus' => [ 'shape' => 'ConfigRuleEvaluationStatusList', ], ], ], 'DescribeConfigRulesRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleNames' => [ 'shape' => 'ConfigRuleNames', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeConfigRulesResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigRules' => [ 'shape' => 'ConfigRules', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'DescribeConfigurationRecorderStatusRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorderNames' => [ 'shape' => 'ConfigurationRecorderNameList', ], ], ], 'DescribeConfigurationRecorderStatusResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecordersStatus' => [ 'shape' => 'ConfigurationRecorderStatusList', ], ], ], 'DescribeConfigurationRecordersRequest' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorderNames' => [ 'shape' => 'ConfigurationRecorderNameList', ], ], ], 'DescribeConfigurationRecordersResponse' => [ 'type' => 'structure', 'members' => [ 'ConfigurationRecorders' => [ 'shape' => 'ConfigurationRecorderList', ], ], ], 'DescribeDeliveryChannelStatusRequest' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelNames' => [ 'shape' => 'DeliveryChannelNameList', ], ], ], 'DescribeDeliveryChannelStatusResponse' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelsStatus' => [ 'shape' => 'DeliveryChannelStatusList', ], ], ], 'DescribeDeliveryChannelsRequest' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannelNames' => [ 'shape' => 'DeliveryChannelNameList', ], ], ], 'DescribeDeliveryChannelsResponse' => [ 'type' => 'structure', 'members' => [ 'DeliveryChannels' => [ 'shape' => 'DeliveryChannelList', ], ], ], 'EarlierTime' => [ 'type' => 'timestamp', ], 'EmptiableStringWithCharLimit256' => [ 'type' => 'string', 'max' => 256, 'min' => 0, ], 'Evaluation' => [ 'type' => 'structure', 'required' => [ 'ComplianceResourceType', 'ComplianceResourceId', 'ComplianceType', 'OrderingTimestamp', ], 'members' => [ 'ComplianceResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'Annotation' => [ 'shape' => 'StringWithCharLimit256', ], 'OrderingTimestamp' => [ 'shape' => 'OrderingTimestamp', ], ], ], 'EvaluationResult' => [ 'type' => 'structure', 'members' => [ 'EvaluationResultIdentifier' => [ 'shape' => 'EvaluationResultIdentifier', ], 'ComplianceType' => [ 'shape' => 'ComplianceType', ], 'ResultRecordedTime' => [ 'shape' => 'Date', ], 'ConfigRuleInvokedTime' => [ 'shape' => 'Date', ], 'Annotation' => [ 'shape' => 'StringWithCharLimit256', ], 'ResultToken' => [ 'shape' => 'String', ], ], ], 'EvaluationResultIdentifier' => [ 'type' => 'structure', 'members' => [ 'EvaluationResultQualifier' => [ 'shape' => 'EvaluationResultQualifier', ], 'OrderingTimestamp' => [ 'shape' => 'Date', ], ], ], 'EvaluationResultQualifier' => [ 'type' => 'structure', 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], ], ], 'EvaluationResults' => [ 'type' => 'list', 'member' => [ 'shape' => 'EvaluationResult', ], ], 'Evaluations' => [ 'type' => 'list', 'member' => [ 'shape' => 'Evaluation', ], 'max' => 100, 'min' => 0, ], 'EventSource' => [ 'type' => 'string', 'enum' => [ 'aws.config', ], ], 'GetComplianceDetailsByConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRuleName', ], 'members' => [ 'ConfigRuleName' => [ 'shape' => 'StringWithCharLimit64', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'Limit' => [ 'shape' => 'Limit', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetComplianceDetailsByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'EvaluationResults' => [ 'shape' => 'EvaluationResults', ], 'NextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetComplianceDetailsByResourceRequest' => [ 'type' => 'structure', 'required' => [ 'ResourceType', 'ResourceId', ], 'members' => [ 'ResourceType' => [ 'shape' => 'StringWithCharLimit256', ], 'ResourceId' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceTypes' => [ 'shape' => 'ComplianceTypes', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'GetComplianceDetailsByResourceResponse' => [ 'type' => 'structure', 'members' => [ 'EvaluationResults' => [ 'shape' => 'EvaluationResults', ], 'NextToken' => [ 'shape' => 'String', ], ], ], 'GetComplianceSummaryByConfigRuleResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceSummary' => [ 'shape' => 'ComplianceSummary', ], ], ], 'GetComplianceSummaryByResourceTypeRequest' => [ 'type' => 'structure', 'members' => [ 'ResourceTypes' => [ 'shape' => 'ResourceTypes', ], ], ], 'GetComplianceSummaryByResourceTypeResponse' => [ 'type' => 'structure', 'members' => [ 'ComplianceSummariesByResourceType' => [ 'shape' => 'ComplianceSummariesByResourceType', ], ], ], 'GetResourceConfigHistoryRequest' => [ 'type' => 'structure', 'required' => [ 'resourceType', 'resourceId', ], 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'laterTime' => [ 'shape' => 'LaterTime', ], 'earlierTime' => [ 'shape' => 'EarlierTime', ], 'chronologicalOrder' => [ 'shape' => 'ChronologicalOrder', ], 'limit' => [ 'shape' => 'Limit', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'GetResourceConfigHistoryResponse' => [ 'type' => 'structure', 'members' => [ 'configurationItems' => [ 'shape' => 'ConfigurationItemList', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'IncludeGlobalResourceTypes' => [ 'type' => 'boolean', ], 'InsufficientDeliveryPolicyException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InsufficientPermissionsException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'Integer' => [ 'type' => 'integer', ], 'InvalidConfigurationRecorderNameException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidDeliveryChannelNameException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidLimitException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidNextTokenException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidParameterValueException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidRecordingGroupException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidResultTokenException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidRoleException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidS3KeyPrefixException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidSNSTopicARNException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'InvalidTimeRangeException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'LastDeliveryChannelDeleteFailedException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'LaterTime' => [ 'type' => 'timestamp', ], 'Limit' => [ 'type' => 'integer', 'max' => 100, 'min' => 0, ], 'ListDiscoveredResourcesRequest' => [ 'type' => 'structure', 'required' => [ 'resourceType', ], 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceIds' => [ 'shape' => 'ResourceIdList', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'limit' => [ 'shape' => 'Limit', ], 'includeDeletedResources' => [ 'shape' => 'Boolean', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'ListDiscoveredResourcesResponse' => [ 'type' => 'structure', 'members' => [ 'resourceIdentifiers' => [ 'shape' => 'ResourceIdentifierList', ], 'nextToken' => [ 'shape' => 'NextToken', ], ], ], 'MaxNumberOfConfigRulesExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaxNumberOfConfigurationRecordersExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaxNumberOfDeliveryChannelsExceededException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'MaximumExecutionFrequency' => [ 'type' => 'string', 'enum' => [ 'One_Hour', 'Three_Hours', 'Six_Hours', 'Twelve_Hours', 'TwentyFour_Hours', ], ], 'MessageType' => [ 'type' => 'string', 'enum' => [ 'ConfigurationItemChangeNotification', 'ConfigurationSnapshotDeliveryCompleted', ], ], 'Name' => [ 'type' => 'string', ], 'NextToken' => [ 'type' => 'string', ], 'NoAvailableConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoAvailableDeliveryChannelException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoRunningConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchBucketException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchConfigRuleException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchConfigurationRecorderException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchDeliveryChannelException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'OrderingTimestamp' => [ 'type' => 'timestamp', ], 'Owner' => [ 'type' => 'string', 'enum' => [ 'CUSTOM_LAMBDA', 'AWS', ], ], 'PutConfigRuleRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigRule', ], 'members' => [ 'ConfigRule' => [ 'shape' => 'ConfigRule', ], ], ], 'PutConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorder', ], 'members' => [ 'ConfigurationRecorder' => [ 'shape' => 'ConfigurationRecorder', ], ], ], 'PutDeliveryChannelRequest' => [ 'type' => 'structure', 'required' => [ 'DeliveryChannel', ], 'members' => [ 'DeliveryChannel' => [ 'shape' => 'DeliveryChannel', ], ], ], 'PutEvaluationsRequest' => [ 'type' => 'structure', 'required' => [ 'ResultToken', ], 'members' => [ 'Evaluations' => [ 'shape' => 'Evaluations', ], 'ResultToken' => [ 'shape' => 'String', ], ], ], 'PutEvaluationsResponse' => [ 'type' => 'structure', 'members' => [ 'FailedEvaluations' => [ 'shape' => 'Evaluations', ], ], ], 'RecorderName' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'RecorderStatus' => [ 'type' => 'string', 'enum' => [ 'Pending', 'Success', 'Failure', ], ], 'RecordingGroup' => [ 'type' => 'structure', 'members' => [ 'allSupported' => [ 'shape' => 'AllSupported', ], 'includeGlobalResourceTypes' => [ 'shape' => 'IncludeGlobalResourceTypes', ], 'resourceTypes' => [ 'shape' => 'ResourceTypeList', ], ], ], 'RelatedEvent' => [ 'type' => 'string', ], 'RelatedEventList' => [ 'type' => 'list', 'member' => [ 'shape' => 'RelatedEvent', ], ], 'Relationship' => [ 'type' => 'structure', 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'relationshipName' => [ 'shape' => 'RelationshipName', ], ], ], 'RelationshipList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Relationship', ], ], 'RelationshipName' => [ 'type' => 'string', ], 'ResourceCreationTime' => [ 'type' => 'timestamp', ], 'ResourceDeletionTime' => [ 'type' => 'timestamp', ], 'ResourceId' => [ 'type' => 'string', ], 'ResourceIdList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceId', ], ], 'ResourceIdentifier' => [ 'type' => 'structure', 'members' => [ 'resourceType' => [ 'shape' => 'ResourceType', ], 'resourceId' => [ 'shape' => 'ResourceId', ], 'resourceName' => [ 'shape' => 'ResourceName', ], 'resourceDeletionTime' => [ 'shape' => 'ResourceDeletionTime', ], ], ], 'ResourceIdentifierList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceIdentifier', ], ], 'ResourceInUseException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ResourceName' => [ 'type' => 'string', ], 'ResourceNotDiscoveredException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ResourceType' => [ 'type' => 'string', 'enum' => [ 'AWS::EC2::CustomerGateway', 'AWS::EC2::EIP', 'AWS::EC2::Host', 'AWS::EC2::Instance', 'AWS::EC2::InternetGateway', 'AWS::EC2::NetworkAcl', 'AWS::EC2::NetworkInterface', 'AWS::EC2::RouteTable', 'AWS::EC2::SecurityGroup', 'AWS::EC2::Subnet', 'AWS::CloudTrail::Trail', 'AWS::EC2::Volume', 'AWS::EC2::VPC', 'AWS::EC2::VPNConnection', 'AWS::EC2::VPNGateway', 'AWS::IAM::Group', 'AWS::IAM::Policy', 'AWS::IAM::Role', 'AWS::IAM::User', ], ], 'ResourceTypeList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ResourceType', ], ], 'ResourceTypes' => [ 'type' => 'list', 'member' => [ 'shape' => 'StringWithCharLimit256', ], 'max' => 100, 'min' => 0, ], 'Scope' => [ 'type' => 'structure', 'members' => [ 'ComplianceResourceTypes' => [ 'shape' => 'ComplianceResourceTypes', ], 'TagKey' => [ 'shape' => 'StringWithCharLimit128', ], 'TagValue' => [ 'shape' => 'StringWithCharLimit256', ], 'ComplianceResourceId' => [ 'shape' => 'StringWithCharLimit256', ], ], ], 'Source' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'SourceIdentifier' => [ 'shape' => 'StringWithCharLimit256', ], 'SourceDetails' => [ 'shape' => 'SourceDetails', ], ], ], 'SourceDetail' => [ 'type' => 'structure', 'members' => [ 'EventSource' => [ 'shape' => 'EventSource', ], 'MessageType' => [ 'shape' => 'MessageType', ], ], ], 'SourceDetails' => [ 'type' => 'list', 'member' => [ 'shape' => 'SourceDetail', ], 'max' => 25, 'min' => 0, ], 'StartConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorderName', ], 'members' => [ 'ConfigurationRecorderName' => [ 'shape' => 'RecorderName', ], ], ], 'StopConfigurationRecorderRequest' => [ 'type' => 'structure', 'required' => [ 'ConfigurationRecorderName', ], 'members' => [ 'ConfigurationRecorderName' => [ 'shape' => 'RecorderName', ], ], ], 'String' => [ 'type' => 'string', ], 'StringWithCharLimit128' => [ 'type' => 'string', 'max' => 128, 'min' => 1, ], 'StringWithCharLimit256' => [ 'type' => 'string', 'max' => 256, 'min' => 1, ], 'StringWithCharLimit64' => [ 'type' => 'string', 'max' => 64, 'min' => 1, ], 'Tags' => [ 'type' => 'map', 'key' => [ 'shape' => 'Name', ], 'value' => [ 'shape' => 'Value', ], ], 'ValidationException' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'Value' => [ 'type' => 'string', ], 'Version' => [ 'type' => 'string', ], ],];
|
includes/aws/Aws/data/config/2014-11-12/paginators-1.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/config/2014-11-12/paginators-1.json
|
3 |
+
return [ 'pagination' => [ 'GetResourceConfigHistory' => [ 'input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'limit', 'result_key' => 'configurationItems', ], ],];
|
includes/aws/Aws/data/endpoints.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/endpoints.json
|
3 |
+
return [ 'version' => 2, 'endpoints' => [ '*/*' => [ 'endpoint' => '{service}.{region}.amazonaws.com', ], 'cn-north-1/*' => [ 'endpoint' => '{service}.{region}.amazonaws.com.cn', 'signatureVersion' => 'v4', ], 'us-gov-west-1/iam' => [ 'endpoint' => 'iam.us-gov.amazonaws.com', ], 'us-gov-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], '*/cloudfront' => [ 'endpoint' => 'cloudfront.amazonaws.com', ], '*/iam' => [ 'endpoint' => 'iam.amazonaws.com', ], 'us-gov-west-1/sts' => [ 'endpoint' => 'sts.us-gov-west-1.amazonaws.com', ], '*/importexport' => [ 'endpoint' => 'importexport.amazonaws.com', ], '*/route53' => [ 'endpoint' => 'route53.amazonaws.com', ], '*/sts' => [ 'endpoint' => 'sts.amazonaws.com', ], '*/waf' => [ 'endpoint' => 'waf.amazonaws.com', ], 'us-east-1/sdb' => [ 'endpoint' => 'sdb.amazonaws.com', ], 'us-east-1/s3' => [ 'endpoint' => 's3.amazonaws.com', ], 'us-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'us-west-2/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'eu-west-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-southeast-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-southeast-2/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'ap-northeast-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], 'sa-east-1/s3' => [ 'endpoint' => 's3-{region}.amazonaws.com', ], ],];
|
includes/aws/Aws/data/manifest.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/manifest.json
|
3 |
+
return [ 'apigateway' => [ 'namespace' => 'ApiGateway', 'versions' => [ 'latest' => '2015-07-09', '2015-07-09' => '2015-07-09', '2015-06-01' => '2015-07-09', ], ], 'autoscaling' => [ 'namespace' => 'AutoScaling', 'versions' => [ 'latest' => '2011-01-01', '2011-01-01' => '2011-01-01', ], ], 'cloudformation' => [ 'namespace' => 'CloudFormation', 'versions' => [ 'latest' => '2010-05-15', '2010-05-15' => '2010-05-15', ], ], 'cloudfront' => [ 'namespace' => 'CloudFront', 'versions' => [ 'latest' => '2015-09-17', '2015-09-17' => '2015-09-17', '2015-07-27' => '2015-09-17', '2015-04-17' => '2015-09-17', '2014-11-06' => '2015-09-17', ], ], 'cloudhsm' => [ 'namespace' => 'CloudHsm', 'versions' => [ 'latest' => '2014-05-30', '2014-05-30' => '2014-05-30', ], ], 'cloudsearch' => [ 'namespace' => 'CloudSearch', 'versions' => [ 'latest' => '2013-01-01', '2013-01-01' => '2013-01-01', ], ], 'cloudsearchdomain' => [ 'namespace' => 'CloudSearchDomain', 'versions' => [ 'latest' => '2013-01-01', '2013-01-01' => '2013-01-01', ], ], 'cloudtrail' => [ 'namespace' => 'CloudTrail', 'versions' => [ 'latest' => '2013-11-01', '2013-11-01' => '2013-11-01', ], ], 'codecommit' => [ 'namespace' => 'CodeCommit', 'versions' => [ 'latest' => '2015-04-13', '2015-04-13' => '2015-04-13', ], ], 'codedeploy' => [ 'namespace' => 'CodeDeploy', 'versions' => [ 'latest' => '2014-10-06', '2014-10-06' => '2014-10-06', ], ], 'codepipeline' => [ 'namespace' => 'CodePipeline', 'versions' => [ 'latest' => '2015-07-09', '2015-07-09' => '2015-07-09', ], ], 'cognito-identity' => [ 'namespace' => 'CognitoIdentity', 'versions' => [ 'latest' => '2014-06-30', '2014-06-30' => '2014-06-30', ], ], 'cognito-sync' => [ 'namespace' => 'CognitoSync', 'versions' => [ 'latest' => '2014-06-30', '2014-06-30' => '2014-06-30', ], ], 'config' => [ 'namespace' => 'ConfigService', 'versions' => [ 'latest' => '2014-11-12', '2014-11-12' => '2014-11-12', ], ], 'data.iot' => [ 'namespace' => 'IotDataPlane', 'versions' => [ 'latest' => '2015-05-28', '2015-05-28' => '2015-05-28', ], ], 'datapipeline' => [ 'namespace' => 'DataPipeline', 'versions' => [ 'latest' => '2012-10-29', '2012-10-29' => '2012-10-29', ], ], 'devicefarm' => [ 'namespace' => 'DeviceFarm', 'versions' => [ 'latest' => '2015-06-23', '2015-06-23' => '2015-06-23', ], ], 'directconnect' => [ 'namespace' => 'DirectConnect', 'versions' => [ 'latest' => '2012-10-25', '2012-10-25' => '2012-10-25', ], ], 'ds' => [ 'namespace' => 'DirectoryService', 'versions' => [ 'latest' => '2015-04-16', '2015-04-16' => '2015-04-16', ], ], 'dynamodb' => [ 'namespace' => 'DynamoDb', 'versions' => [ 'latest' => '2012-08-10', '2012-08-10' => '2012-08-10', ], ], 'ec2' => [ 'namespace' => 'Ec2', 'versions' => [ 'latest' => '2015-10-01', '2015-10-01' => '2015-10-01', '2015-04-15' => '2015-10-01', ], ], 'ecr' => [ 'namespace' => 'Ecr', 'versions' => [ 'latest' => '2015-09-21', '2015-09-21' => '2015-09-21', ], ], 'ecs' => [ 'namespace' => 'Ecs', 'versions' => [ 'latest' => '2014-11-13', '2014-11-13' => '2014-11-13', ], ], 'elasticache' => [ 'namespace' => 'ElastiCache', 'versions' => [ 'latest' => '2015-02-02', '2015-02-02' => '2015-02-02', ], ], 'elasticbeanstalk' => [ 'namespace' => 'ElasticBeanstalk', 'versions' => [ 'latest' => '2010-12-01', '2010-12-01' => '2010-12-01', ], ], 'elasticfilesystem' => [ 'namespace' => 'Efs', 'versions' => [ 'latest' => '2015-02-01', '2015-02-01' => '2015-02-01', ], ], 'elasticloadbalancing' => [ 'namespace' => 'ElasticLoadBalancing', 'versions' => [ 'latest' => '2012-06-01', '2012-06-01' => '2012-06-01', ], ], 'elasticmapreduce' => [ 'namespace' => 'Emr', 'versions' => [ 'latest' => '2009-03-31', '2009-03-31' => '2009-03-31', ], ], 'elastictranscoder' => [ 'namespace' => 'ElasticTranscoder', 'versions' => [ 'latest' => '2012-09-25', '2012-09-25' => '2012-09-25', ], ], 'email' => [ 'namespace' => 'Ses', 'versions' => [ 'latest' => '2010-12-01', '2010-12-01' => '2010-12-01', ], ], 'es' => [ 'namespace' => 'ElasticsearchService', 'versions' => [ 'latest' => '2015-01-01', '2015-01-01' => '2015-01-01', ], ], 'firehose' => [ 'namespace' => 'Firehose', 'versions' => [ 'latest' => '2015-08-04', '2015-08-04' => '2015-08-04', ], ], 'glacier' => [ 'namespace' => 'Glacier', 'versions' => [ 'latest' => '2012-06-01', '2012-06-01' => '2012-06-01', ], ], 'iam' => [ 'namespace' => 'Iam', 'versions' => [ 'latest' => '2010-05-08', '2010-05-08' => '2010-05-08', ], ], 'inspector' => [ 'namespace' => 'Inspector', 'versions' => [ 'latest' => '2015-08-18', '2015-08-18' => '2015-08-18', ], ], 'iot' => [ 'namespace' => 'Iot', 'versions' => [ 'latest' => '2015-05-28', '2015-05-28' => '2015-05-28', ], ], 'kinesis' => [ 'namespace' => 'Kinesis', 'versions' => [ 'latest' => '2013-12-02', '2013-12-02' => '2013-12-02', ], ], 'kms' => [ 'namespace' => 'Kms', 'versions' => [ 'latest' => '2014-11-01', '2014-11-01' => '2014-11-01', ], ], 'lambda' => [ 'namespace' => 'Lambda', 'versions' => [ 'latest' => '2015-03-31', '2015-03-31' => '2015-03-31', ], ], 'logs' => [ 'namespace' => 'CloudWatchLogs', 'versions' => [ 'latest' => '2014-03-28', '2014-03-28' => '2014-03-28', ], ], 'machinelearning' => [ 'namespace' => 'MachineLearning', 'versions' => [ 'latest' => '2014-12-12', '2014-12-12' => '2014-12-12', ], ], 'marketplacecommerceanalytics' => [ 'namespace' => 'MarketplaceCommerceAnalytics', 'versions' => [ 'latest' => '2015-07-01', '2015-07-01' => '2015-07-01', ], ], 'monitoring' => [ 'namespace' => 'CloudWatch', 'versions' => [ 'latest' => '2010-08-01', '2010-08-01' => '2010-08-01', ], ], 'opsworks' => [ 'namespace' => 'OpsWorks', 'versions' => [ 'latest' => '2013-02-18', '2013-02-18' => '2013-02-18', ], ], 'rds' => [ 'namespace' => 'Rds', 'versions' => [ 'latest' => '2014-10-31', '2014-10-31' => '2014-10-31', ], ], 'redshift' => [ 'namespace' => 'Redshift', 'versions' => [ 'latest' => '2012-12-01', '2012-12-01' => '2012-12-01', ], ], 'route53' => [ 'namespace' => 'Route53', 'versions' => [ 'latest' => '2013-04-01', '2013-04-01' => '2013-04-01', ], ], 'route53domains' => [ 'namespace' => 'Route53Domains', 'versions' => [ 'latest' => '2014-05-15', '2014-05-15' => '2014-05-15', ], ], 's3' => [ 'namespace' => 'S3', 'versions' => [ 'latest' => '2006-03-01', '2006-03-01' => '2006-03-01', ], ], 'sns' => [ 'namespace' => 'Sns', 'versions' => [ 'latest' => '2010-03-31', '2010-03-31' => '2010-03-31', ], ], 'sqs' => [ 'namespace' => 'Sqs', 'versions' => [ 'latest' => '2012-11-05', '2012-11-05' => '2012-11-05', ], ], 'ssm' => [ 'namespace' => 'Ssm', 'versions' => [ 'latest' => '2014-11-06', '2014-11-06' => '2014-11-06', ], ], 'storagegateway' => [ 'namespace' => 'StorageGateway', 'versions' => [ 'latest' => '2013-06-30', '2013-06-30' => '2013-06-30', ], ], 'streams.dynamodb' => [ 'namespace' => 'DynamoDbStreams', 'versions' => [ 'latest' => '2012-08-10', '2012-08-10' => '2012-08-10', ], ], 'sts' => [ 'namespace' => 'Sts', 'versions' => [ 'latest' => '2011-06-15', '2011-06-15' => '2011-06-15', ], ], 'support' => [ 'namespace' => 'Support', 'versions' => [ 'latest' => '2013-04-15', '2013-04-15' => '2013-04-15', ], ], 'swf' => [ 'namespace' => 'Swf', 'versions' => [ 'latest' => '2012-01-25', '2012-01-25' => '2012-01-25', ], ], 'waf' => [ 'namespace' => 'Waf', 'versions' => [ 'latest' => '2015-08-24', '2015-08-24' => '2015-08-24', ], ], 'workspaces' => [ 'namespace' => 'WorkSpaces', 'versions' => [ 'latest' => '2015-04-08', '2015-04-08' => '2015-04-08', ], ],];
|
includes/aws/Aws/data/s3/2006-03-01/api-2.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/s3/2006-03-01/api-2.json
|
3 |
+
return [ 'version' => '2.0', 'metadata' => [ 'apiVersion' => '2006-03-01', 'checksumFormat' => 'md5', 'endpointPrefix' => 's3', 'globalEndpoint' => 's3.amazonaws.com', 'protocol' => 'rest-xml', 'serviceAbbreviation' => 'Amazon S3', 'serviceFullName' => 'Amazon Simple Storage Service', 'signatureVersion' => 'v4', 'timestampFormat' => 'rfc822', ], 'operations' => [ 'AbortMultipartUpload' => [ 'name' => 'AbortMultipartUpload', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'AbortMultipartUploadRequest', ], 'output' => [ 'shape' => 'AbortMultipartUploadOutput', ], 'errors' => [ [ 'shape' => 'NoSuchUpload', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadAbort.html', ], 'CompleteMultipartUpload' => [ 'name' => 'CompleteMultipartUpload', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'CompleteMultipartUploadRequest', ], 'output' => [ 'shape' => 'CompleteMultipartUploadOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html', ], 'CopyObject' => [ 'name' => 'CopyObject', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'CopyObjectRequest', ], 'output' => [ 'shape' => 'CopyObjectOutput', ], 'errors' => [ [ 'shape' => 'ObjectNotInActiveTierError', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectCOPY.html', 'alias' => 'PutObjectCopy', ], 'CreateBucket' => [ 'name' => 'CreateBucket', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'CreateBucketRequest', ], 'output' => [ 'shape' => 'CreateBucketOutput', ], 'errors' => [ [ 'shape' => 'BucketAlreadyExists', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUT.html', 'alias' => 'PutBucket', ], 'CreateMultipartUpload' => [ 'name' => 'CreateMultipartUpload', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}?uploads', ], 'input' => [ 'shape' => 'CreateMultipartUploadRequest', ], 'output' => [ 'shape' => 'CreateMultipartUploadOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html', 'alias' => 'InitiateMultipartUpload', ], 'DeleteBucket' => [ 'name' => 'DeleteBucket', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'DeleteBucketRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETE.html', ], 'DeleteBucketCors' => [ 'name' => 'DeleteBucketCors', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'DeleteBucketCorsRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEcors.html', ], 'DeleteBucketLifecycle' => [ 'name' => 'DeleteBucketLifecycle', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'DeleteBucketLifecycleRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETElifecycle.html', ], 'DeleteBucketPolicy' => [ 'name' => 'DeleteBucketPolicy', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'DeleteBucketPolicyRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEpolicy.html', ], 'DeleteBucketReplication' => [ 'name' => 'DeleteBucketReplication', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'DeleteBucketReplicationRequest', ], ], 'DeleteBucketTagging' => [ 'name' => 'DeleteBucketTagging', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'DeleteBucketTaggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEtagging.html', ], 'DeleteBucketWebsite' => [ 'name' => 'DeleteBucketWebsite', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'DeleteBucketWebsiteRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEwebsite.html', ], 'DeleteObject' => [ 'name' => 'DeleteObject', 'http' => [ 'method' => 'DELETE', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'DeleteObjectRequest', ], 'output' => [ 'shape' => 'DeleteObjectOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html', ], 'DeleteObjects' => [ 'name' => 'DeleteObjects', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}?delete', ], 'input' => [ 'shape' => 'DeleteObjectsRequest', ], 'output' => [ 'shape' => 'DeleteObjectsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/multiobjectdeleteapi.html', 'alias' => 'DeleteMultipleObjects', ], 'GetBucketAcl' => [ 'name' => 'GetBucketAcl', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?acl', ], 'input' => [ 'shape' => 'GetBucketAclRequest', ], 'output' => [ 'shape' => 'GetBucketAclOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETacl.html', ], 'GetBucketCors' => [ 'name' => 'GetBucketCors', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'GetBucketCorsRequest', ], 'output' => [ 'shape' => 'GetBucketCorsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETcors.html', ], 'GetBucketLifecycle' => [ 'name' => 'GetBucketLifecycle', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'GetBucketLifecycleRequest', ], 'output' => [ 'shape' => 'GetBucketLifecycleOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlifecycle.html', 'deprecated' => true, ], 'GetBucketLifecycleConfiguration' => [ 'name' => 'GetBucketLifecycleConfiguration', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'GetBucketLifecycleConfigurationRequest', ], 'output' => [ 'shape' => 'GetBucketLifecycleConfigurationOutput', ], ], 'GetBucketLocation' => [ 'name' => 'GetBucketLocation', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?location', ], 'input' => [ 'shape' => 'GetBucketLocationRequest', ], 'output' => [ 'shape' => 'GetBucketLocationOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlocation.html', ], 'GetBucketLogging' => [ 'name' => 'GetBucketLogging', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?logging', ], 'input' => [ 'shape' => 'GetBucketLoggingRequest', ], 'output' => [ 'shape' => 'GetBucketLoggingOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlogging.html', ], 'GetBucketNotification' => [ 'name' => 'GetBucketNotification', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'GetBucketNotificationConfigurationRequest', ], 'output' => [ 'shape' => 'NotificationConfigurationDeprecated', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETnotification.html', 'deprecated' => true, ], 'GetBucketNotificationConfiguration' => [ 'name' => 'GetBucketNotificationConfiguration', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'GetBucketNotificationConfigurationRequest', ], 'output' => [ 'shape' => 'NotificationConfiguration', ], ], 'GetBucketPolicy' => [ 'name' => 'GetBucketPolicy', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'GetBucketPolicyRequest', ], 'output' => [ 'shape' => 'GetBucketPolicyOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETpolicy.html', ], 'GetBucketReplication' => [ 'name' => 'GetBucketReplication', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'GetBucketReplicationRequest', ], 'output' => [ 'shape' => 'GetBucketReplicationOutput', ], ], 'GetBucketRequestPayment' => [ 'name' => 'GetBucketRequestPayment', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?requestPayment', ], 'input' => [ 'shape' => 'GetBucketRequestPaymentRequest', ], 'output' => [ 'shape' => 'GetBucketRequestPaymentOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTrequestPaymentGET.html', ], 'GetBucketTagging' => [ 'name' => 'GetBucketTagging', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'GetBucketTaggingRequest', ], 'output' => [ 'shape' => 'GetBucketTaggingOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETtagging.html', ], 'GetBucketVersioning' => [ 'name' => 'GetBucketVersioning', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?versioning', ], 'input' => [ 'shape' => 'GetBucketVersioningRequest', ], 'output' => [ 'shape' => 'GetBucketVersioningOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETversioningStatus.html', ], 'GetBucketWebsite' => [ 'name' => 'GetBucketWebsite', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'GetBucketWebsiteRequest', ], 'output' => [ 'shape' => 'GetBucketWebsiteOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETwebsite.html', ], 'GetObject' => [ 'name' => 'GetObject', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'GetObjectRequest', ], 'output' => [ 'shape' => 'GetObjectOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGET.html', ], 'GetObjectAcl' => [ 'name' => 'GetObjectAcl', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}?acl', ], 'input' => [ 'shape' => 'GetObjectAclRequest', ], 'output' => [ 'shape' => 'GetObjectAclOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGETacl.html', ], 'GetObjectTorrent' => [ 'name' => 'GetObjectTorrent', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}?torrent', ], 'input' => [ 'shape' => 'GetObjectTorrentRequest', ], 'output' => [ 'shape' => 'GetObjectTorrentOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGETtorrent.html', ], 'HeadBucket' => [ 'name' => 'HeadBucket', 'http' => [ 'method' => 'HEAD', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'HeadBucketRequest', ], 'errors' => [ [ 'shape' => 'NoSuchBucket', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketHEAD.html', ], 'HeadObject' => [ 'name' => 'HeadObject', 'http' => [ 'method' => 'HEAD', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'HeadObjectRequest', ], 'output' => [ 'shape' => 'HeadObjectOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectHEAD.html', ], 'ListBuckets' => [ 'name' => 'ListBuckets', 'http' => [ 'method' => 'GET', 'requestUri' => '/', ], 'output' => [ 'shape' => 'ListBucketsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTServiceGET.html', 'alias' => 'GetService', ], 'ListMultipartUploads' => [ 'name' => 'ListMultipartUploads', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?uploads', ], 'input' => [ 'shape' => 'ListMultipartUploadsRequest', ], 'output' => [ 'shape' => 'ListMultipartUploadsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListMPUpload.html', ], 'ListObjectVersions' => [ 'name' => 'ListObjectVersions', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}?versions', ], 'input' => [ 'shape' => 'ListObjectVersionsRequest', ], 'output' => [ 'shape' => 'ListObjectVersionsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETVersion.html', 'alias' => 'GetBucketObjectVersions', ], 'ListObjects' => [ 'name' => 'ListObjects', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}', ], 'input' => [ 'shape' => 'ListObjectsRequest', ], 'output' => [ 'shape' => 'ListObjectsOutput', ], 'errors' => [ [ 'shape' => 'NoSuchBucket', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGET.html', 'alias' => 'GetBucket', ], 'ListParts' => [ 'name' => 'ListParts', 'http' => [ 'method' => 'GET', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'ListPartsRequest', ], 'output' => [ 'shape' => 'ListPartsOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListParts.html', ], 'PutBucketAcl' => [ 'name' => 'PutBucketAcl', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?acl', ], 'input' => [ 'shape' => 'PutBucketAclRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTacl.html', ], 'PutBucketCors' => [ 'name' => 'PutBucketCors', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?cors', ], 'input' => [ 'shape' => 'PutBucketCorsRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTcors.html', ], 'PutBucketLifecycle' => [ 'name' => 'PutBucketLifecycle', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'PutBucketLifecycleRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html', 'deprecated' => true, ], 'PutBucketLifecycleConfiguration' => [ 'name' => 'PutBucketLifecycleConfiguration', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?lifecycle', ], 'input' => [ 'shape' => 'PutBucketLifecycleConfigurationRequest', ], ], 'PutBucketLogging' => [ 'name' => 'PutBucketLogging', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?logging', ], 'input' => [ 'shape' => 'PutBucketLoggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlogging.html', ], 'PutBucketNotification' => [ 'name' => 'PutBucketNotification', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'PutBucketNotificationRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTnotification.html', 'deprecated' => true, ], 'PutBucketNotificationConfiguration' => [ 'name' => 'PutBucketNotificationConfiguration', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?notification', ], 'input' => [ 'shape' => 'PutBucketNotificationConfigurationRequest', ], ], 'PutBucketPolicy' => [ 'name' => 'PutBucketPolicy', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?policy', ], 'input' => [ 'shape' => 'PutBucketPolicyRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTpolicy.html', ], 'PutBucketReplication' => [ 'name' => 'PutBucketReplication', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?replication', ], 'input' => [ 'shape' => 'PutBucketReplicationRequest', ], ], 'PutBucketRequestPayment' => [ 'name' => 'PutBucketRequestPayment', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?requestPayment', ], 'input' => [ 'shape' => 'PutBucketRequestPaymentRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTrequestPaymentPUT.html', ], 'PutBucketTagging' => [ 'name' => 'PutBucketTagging', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?tagging', ], 'input' => [ 'shape' => 'PutBucketTaggingRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTtagging.html', ], 'PutBucketVersioning' => [ 'name' => 'PutBucketVersioning', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?versioning', ], 'input' => [ 'shape' => 'PutBucketVersioningRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html', ], 'PutBucketWebsite' => [ 'name' => 'PutBucketWebsite', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}?website', ], 'input' => [ 'shape' => 'PutBucketWebsiteRequest', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html', ], 'PutObject' => [ 'name' => 'PutObject', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'PutObjectRequest', ], 'output' => [ 'shape' => 'PutObjectOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUT.html', ], 'PutObjectAcl' => [ 'name' => 'PutObjectAcl', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}?acl', ], 'input' => [ 'shape' => 'PutObjectAclRequest', ], 'output' => [ 'shape' => 'PutObjectAclOutput', ], 'errors' => [ [ 'shape' => 'NoSuchKey', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUTacl.html', ], 'RestoreObject' => [ 'name' => 'RestoreObject', 'http' => [ 'method' => 'POST', 'requestUri' => '/{Bucket}/{Key+}?restore', ], 'input' => [ 'shape' => 'RestoreObjectRequest', ], 'output' => [ 'shape' => 'RestoreObjectOutput', ], 'errors' => [ [ 'shape' => 'ObjectAlreadyInActiveTierError', ], ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectRestore.html', 'alias' => 'PostObjectRestore', ], 'UploadPart' => [ 'name' => 'UploadPart', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'UploadPartRequest', ], 'output' => [ 'shape' => 'UploadPartOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html', ], 'UploadPartCopy' => [ 'name' => 'UploadPartCopy', 'http' => [ 'method' => 'PUT', 'requestUri' => '/{Bucket}/{Key+}', ], 'input' => [ 'shape' => 'UploadPartCopyRequest', ], 'output' => [ 'shape' => 'UploadPartCopyOutput', ], 'documentationUrl' => 'http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html', ], ], 'shapes' => [ 'AbortMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'AbortMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'AcceptRanges' => [ 'type' => 'string', ], 'AccessControlPolicy' => [ 'type' => 'structure', 'members' => [ 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'AllowedHeader' => [ 'type' => 'string', ], 'AllowedHeaders' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedHeader', ], 'flattened' => true, ], 'AllowedMethod' => [ 'type' => 'string', ], 'AllowedMethods' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedMethod', ], 'flattened' => true, ], 'AllowedOrigin' => [ 'type' => 'string', ], 'AllowedOrigins' => [ 'type' => 'list', 'member' => [ 'shape' => 'AllowedOrigin', ], 'flattened' => true, ], 'Body' => [ 'type' => 'blob', ], 'Bucket' => [ 'type' => 'structure', 'members' => [ 'Name' => [ 'shape' => 'BucketName', ], 'CreationDate' => [ 'shape' => 'CreationDate', ], ], ], 'BucketAlreadyExists' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'BucketCannedACL' => [ 'type' => 'string', 'enum' => [ 'private', 'public-read', 'public-read-write', 'authenticated-read', ], ], 'BucketLifecycleConfiguration' => [ 'type' => 'structure', 'required' => [ 'Rules', ], 'members' => [ 'Rules' => [ 'shape' => 'LifecycleRules', 'locationName' => 'Rule', ], ], ], 'BucketLocationConstraint' => [ 'type' => 'string', 'enum' => [ 'EU', 'eu-west-1', 'us-west-1', 'us-west-2', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1', 'cn-north-1', 'eu-central-1', ], ], 'BucketLoggingStatus' => [ 'type' => 'structure', 'members' => [ 'LoggingEnabled' => [ 'shape' => 'LoggingEnabled', ], ], ], 'BucketLogsPermission' => [ 'type' => 'string', 'enum' => [ 'FULL_CONTROL', 'READ', 'WRITE', ], ], 'BucketName' => [ 'type' => 'string', ], 'BucketVersioningStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Suspended', ], ], 'Buckets' => [ 'type' => 'list', 'member' => [ 'shape' => 'Bucket', 'locationName' => 'Bucket', ], ], 'CORSConfiguration' => [ 'type' => 'structure', 'required' => [ 'CORSRules', ], 'members' => [ 'CORSRules' => [ 'shape' => 'CORSRules', 'locationName' => 'CORSRule', ], ], ], 'CORSRule' => [ 'type' => 'structure', 'required' => [ 'AllowedMethods', 'AllowedOrigins', ], 'members' => [ 'AllowedHeaders' => [ 'shape' => 'AllowedHeaders', 'locationName' => 'AllowedHeader', ], 'AllowedMethods' => [ 'shape' => 'AllowedMethods', 'locationName' => 'AllowedMethod', ], 'AllowedOrigins' => [ 'shape' => 'AllowedOrigins', 'locationName' => 'AllowedOrigin', ], 'ExposeHeaders' => [ 'shape' => 'ExposeHeaders', 'locationName' => 'ExposeHeader', ], 'MaxAgeSeconds' => [ 'shape' => 'MaxAgeSeconds', ], ], ], 'CORSRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'CORSRule', ], 'flattened' => true, ], 'CacheControl' => [ 'type' => 'string', ], 'CloudFunction' => [ 'type' => 'string', ], 'CloudFunctionConfiguration' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'CloudFunction' => [ 'shape' => 'CloudFunction', ], 'InvocationRole' => [ 'shape' => 'CloudFunctionInvocationRole', ], ], ], 'CloudFunctionInvocationRole' => [ 'type' => 'string', ], 'Code' => [ 'type' => 'string', ], 'CommonPrefix' => [ 'type' => 'structure', 'members' => [ 'Prefix' => [ 'shape' => 'Prefix', ], ], ], 'CommonPrefixList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CommonPrefix', ], 'flattened' => true, ], 'CompleteMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'Location', ], 'Bucket' => [ 'shape' => 'BucketName', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'ETag' => [ 'shape' => 'ETag', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'CompleteMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MultipartUpload' => [ 'shape' => 'CompletedMultipartUpload', 'locationName' => 'CompleteMultipartUpload', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'MultipartUpload', ], 'CompletedMultipartUpload' => [ 'type' => 'structure', 'members' => [ 'Parts' => [ 'shape' => 'CompletedPartList', 'locationName' => 'Part', ], ], ], 'CompletedPart' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'PartNumber' => [ 'shape' => 'PartNumber', ], ], ], 'CompletedPartList' => [ 'type' => 'list', 'member' => [ 'shape' => 'CompletedPart', ], 'flattened' => true, ], 'Condition' => [ 'type' => 'structure', 'members' => [ 'HttpErrorCodeReturnedEquals' => [ 'shape' => 'HttpErrorCodeReturnedEquals', ], 'KeyPrefixEquals' => [ 'shape' => 'KeyPrefixEquals', ], ], ], 'ContentDisposition' => [ 'type' => 'string', ], 'ContentEncoding' => [ 'type' => 'string', ], 'ContentLanguage' => [ 'type' => 'string', ], 'ContentLength' => [ 'type' => 'integer', ], 'ContentMD5' => [ 'type' => 'string', ], 'ContentRange' => [ 'type' => 'string', ], 'ContentType' => [ 'type' => 'string', ], 'CopyObjectOutput' => [ 'type' => 'structure', 'members' => [ 'CopyObjectResult' => [ 'shape' => 'CopyObjectResult', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'CopySourceVersionId' => [ 'shape' => 'CopySourceVersionId', 'location' => 'header', 'locationName' => 'x-amz-copy-source-version-id', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'CopyObjectResult', ], 'CopyObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CopySource', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'CopySource' => [ 'shape' => 'CopySource', 'location' => 'header', 'locationName' => 'x-amz-copy-source', ], 'CopySourceIfMatch' => [ 'shape' => 'CopySourceIfMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-match', ], 'CopySourceIfModifiedSince' => [ 'shape' => 'CopySourceIfModifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-modified-since', ], 'CopySourceIfNoneMatch' => [ 'shape' => 'CopySourceIfNoneMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-none-match', ], 'CopySourceIfUnmodifiedSince' => [ 'shape' => 'CopySourceIfUnmodifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-unmodified-since', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'MetadataDirective' => [ 'shape' => 'MetadataDirective', 'location' => 'header', 'locationName' => 'x-amz-metadata-directive', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'CopySourceSSECustomerAlgorithm' => [ 'shape' => 'CopySourceSSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-algorithm', ], 'CopySourceSSECustomerKey' => [ 'shape' => 'CopySourceSSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key', ], 'CopySourceSSECustomerKeyMD5' => [ 'shape' => 'CopySourceSSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'CopyObjectResult' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'CopyPartResult' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'CopySource' => [ 'type' => 'string', 'pattern' => '\\/.+\\/.+', ], 'CopySourceIfMatch' => [ 'type' => 'string', ], 'CopySourceIfModifiedSince' => [ 'type' => 'timestamp', ], 'CopySourceIfNoneMatch' => [ 'type' => 'string', ], 'CopySourceIfUnmodifiedSince' => [ 'type' => 'timestamp', ], 'CopySourceRange' => [ 'type' => 'string', ], 'CopySourceSSECustomerAlgorithm' => [ 'type' => 'string', ], 'CopySourceSSECustomerKey' => [ 'type' => 'string', 'sensitive' => true, ], 'CopySourceSSECustomerKeyMD5' => [ 'type' => 'string', ], 'CopySourceVersionId' => [ 'type' => 'string', ], 'CreateBucketConfiguration' => [ 'type' => 'structure', 'members' => [ 'LocationConstraint' => [ 'shape' => 'BucketLocationConstraint', ], ], ], 'CreateBucketOutput' => [ 'type' => 'structure', 'members' => [ 'Location' => [ 'shape' => 'Location', 'location' => 'header', 'locationName' => 'Location', ], ], ], 'CreateBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'ACL' => [ 'shape' => 'BucketCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CreateBucketConfiguration' => [ 'shape' => 'CreateBucketConfiguration', 'locationName' => 'CreateBucketConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], ], 'payload' => 'CreateBucketConfiguration', ], 'CreateMultipartUploadOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'CreateMultipartUploadRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'CreationDate' => [ 'type' => 'timestamp', ], 'Date' => [ 'type' => 'timestamp', 'timestampFormat' => 'iso8601', ], 'Days' => [ 'type' => 'integer', ], 'Delete' => [ 'type' => 'structure', 'required' => [ 'Objects', ], 'members' => [ 'Objects' => [ 'shape' => 'ObjectIdentifierList', 'locationName' => 'Object', ], 'Quiet' => [ 'shape' => 'Quiet', ], ], ], 'DeleteBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'DeleteMarker' => [ 'type' => 'boolean', ], 'DeleteMarkerEntry' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'IsLatest' => [ 'shape' => 'IsLatest', ], 'LastModified' => [ 'shape' => 'LastModified', ], ], ], 'DeleteMarkerVersionId' => [ 'type' => 'string', ], 'DeleteMarkers' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeleteMarkerEntry', ], 'flattened' => true, ], 'DeleteObjectOutput' => [ 'type' => 'structure', 'members' => [ 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'DeleteObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'DeleteObjectsOutput' => [ 'type' => 'structure', 'members' => [ 'Deleted' => [ 'shape' => 'DeletedObjects', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'Errors' => [ 'shape' => 'Errors', 'locationName' => 'Error', ], ], ], 'DeleteObjectsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Delete', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delete' => [ 'shape' => 'Delete', 'locationName' => 'Delete', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Delete', ], 'DeletedObject' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'DeleteMarker' => [ 'shape' => 'DeleteMarker', ], 'DeleteMarkerVersionId' => [ 'shape' => 'DeleteMarkerVersionId', ], ], ], 'DeletedObjects' => [ 'type' => 'list', 'member' => [ 'shape' => 'DeletedObject', ], 'flattened' => true, ], 'Delimiter' => [ 'type' => 'string', ], 'Destination' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], ], ], 'DisplayName' => [ 'type' => 'string', ], 'ETag' => [ 'type' => 'string', ], 'EmailAddress' => [ 'type' => 'string', ], 'EncodingType' => [ 'type' => 'string', 'enum' => [ 'url', ], ], 'Error' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'Code' => [ 'shape' => 'Code', ], 'Message' => [ 'shape' => 'Message', ], ], ], 'ErrorDocument' => [ 'type' => 'structure', 'required' => [ 'Key', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], ], ], 'Errors' => [ 'type' => 'list', 'member' => [ 'shape' => 'Error', ], 'flattened' => true, ], 'Event' => [ 'type' => 'string', 'enum' => [ 's3:ReducedRedundancyLostObject', 's3:ObjectCreated:*', 's3:ObjectCreated:Put', 's3:ObjectCreated:Post', 's3:ObjectCreated:Copy', 's3:ObjectCreated:CompleteMultipartUpload', 's3:ObjectRemoved:*', 's3:ObjectRemoved:Delete', 's3:ObjectRemoved:DeleteMarkerCreated', ], ], 'EventList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Event', ], 'flattened' => true, ], 'Expiration' => [ 'type' => 'string', ], 'ExpirationStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'Expires' => [ 'type' => 'timestamp', ], 'ExposeHeader' => [ 'type' => 'string', ], 'ExposeHeaders' => [ 'type' => 'list', 'member' => [ 'shape' => 'ExposeHeader', ], 'flattened' => true, ], 'FilterRule' => [ 'type' => 'structure', 'members' => [ 'Name' => [ 'shape' => 'FilterRuleName', ], 'Value' => [ 'shape' => 'FilterRuleValue', ], ], ], 'FilterRuleList' => [ 'type' => 'list', 'member' => [ 'shape' => 'FilterRule', ], 'flattened' => true, ], 'FilterRuleName' => [ 'type' => 'string', 'enum' => [ 'prefix', 'suffix', ], ], 'FilterRuleValue' => [ 'type' => 'string', ], 'GetBucketAclOutput' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], ], ], 'GetBucketAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketCorsOutput' => [ 'type' => 'structure', 'members' => [ 'CORSRules' => [ 'shape' => 'CORSRules', 'locationName' => 'CORSRule', ], ], ], 'GetBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLifecycleConfigurationOutput' => [ 'type' => 'structure', 'members' => [ 'Rules' => [ 'shape' => 'LifecycleRules', 'locationName' => 'Rule', ], ], ], 'GetBucketLifecycleConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLifecycleOutput' => [ 'type' => 'structure', 'members' => [ 'Rules' => [ 'shape' => 'Rules', 'locationName' => 'Rule', ], ], ], 'GetBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLocationOutput' => [ 'type' => 'structure', 'members' => [ 'LocationConstraint' => [ 'shape' => 'BucketLocationConstraint', ], ], ], 'GetBucketLocationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketLoggingOutput' => [ 'type' => 'structure', 'members' => [ 'LoggingEnabled' => [ 'shape' => 'LoggingEnabled', ], ], ], 'GetBucketLoggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketNotificationConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketPolicyOutput' => [ 'type' => 'structure', 'members' => [ 'Policy' => [ 'shape' => 'Policy', ], ], 'payload' => 'Policy', ], 'GetBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketReplicationOutput' => [ 'type' => 'structure', 'members' => [ 'ReplicationConfiguration' => [ 'shape' => 'ReplicationConfiguration', ], ], 'payload' => 'ReplicationConfiguration', ], 'GetBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketRequestPaymentOutput' => [ 'type' => 'structure', 'members' => [ 'Payer' => [ 'shape' => 'Payer', ], ], ], 'GetBucketRequestPaymentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketTaggingOutput' => [ 'type' => 'structure', 'required' => [ 'TagSet', ], 'members' => [ 'TagSet' => [ 'shape' => 'TagSet', ], ], ], 'GetBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketVersioningOutput' => [ 'type' => 'structure', 'members' => [ 'Status' => [ 'shape' => 'BucketVersioningStatus', ], 'MFADelete' => [ 'shape' => 'MFADeleteStatus', 'locationName' => 'MfaDelete', ], ], ], 'GetBucketVersioningRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetBucketWebsiteOutput' => [ 'type' => 'structure', 'members' => [ 'RedirectAllRequestsTo' => [ 'shape' => 'RedirectAllRequestsTo', ], 'IndexDocument' => [ 'shape' => 'IndexDocument', ], 'ErrorDocument' => [ 'shape' => 'ErrorDocument', ], 'RoutingRules' => [ 'shape' => 'RoutingRules', ], ], ], 'GetBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'GetObjectAclOutput' => [ 'type' => 'structure', 'members' => [ 'Owner' => [ 'shape' => 'Owner', ], 'Grants' => [ 'shape' => 'Grants', 'locationName' => 'AccessControlList', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'GetObjectAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'GetObjectOutput' => [ 'type' => 'structure', 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'AcceptRanges' => [ 'shape' => 'AcceptRanges', 'location' => 'header', 'locationName' => 'accept-ranges', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'Restore' => [ 'shape' => 'Restore', 'location' => 'header', 'locationName' => 'x-amz-restore', ], 'LastModified' => [ 'shape' => 'LastModified', 'location' => 'header', 'locationName' => 'Last-Modified', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'MissingMeta' => [ 'shape' => 'MissingMeta', 'location' => 'header', 'locationName' => 'x-amz-missing-meta', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentRange' => [ 'shape' => 'ContentRange', 'location' => 'header', 'locationName' => 'Content-Range', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'ReplicationStatus' => [ 'shape' => 'ReplicationStatus', 'location' => 'header', 'locationName' => 'x-amz-replication-status', ], ], 'payload' => 'Body', ], 'GetObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'IfMatch' => [ 'shape' => 'IfMatch', 'location' => 'header', 'locationName' => 'If-Match', ], 'IfModifiedSince' => [ 'shape' => 'IfModifiedSince', 'location' => 'header', 'locationName' => 'If-Modified-Since', ], 'IfNoneMatch' => [ 'shape' => 'IfNoneMatch', 'location' => 'header', 'locationName' => 'If-None-Match', ], 'IfUnmodifiedSince' => [ 'shape' => 'IfUnmodifiedSince', 'location' => 'header', 'locationName' => 'If-Unmodified-Since', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Range' => [ 'shape' => 'Range', 'location' => 'header', 'locationName' => 'Range', ], 'ResponseCacheControl' => [ 'shape' => 'ResponseCacheControl', 'location' => 'querystring', 'locationName' => 'response-cache-control', ], 'ResponseContentDisposition' => [ 'shape' => 'ResponseContentDisposition', 'location' => 'querystring', 'locationName' => 'response-content-disposition', ], 'ResponseContentEncoding' => [ 'shape' => 'ResponseContentEncoding', 'location' => 'querystring', 'locationName' => 'response-content-encoding', ], 'ResponseContentLanguage' => [ 'shape' => 'ResponseContentLanguage', 'location' => 'querystring', 'locationName' => 'response-content-language', ], 'ResponseContentType' => [ 'shape' => 'ResponseContentType', 'location' => 'querystring', 'locationName' => 'response-content-type', ], 'ResponseExpires' => [ 'shape' => 'ResponseExpires', 'location' => 'querystring', 'locationName' => 'response-expires', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'GetObjectTorrentOutput' => [ 'type' => 'structure', 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'Body', ], 'GetObjectTorrentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'Grant' => [ 'type' => 'structure', 'members' => [ 'Grantee' => [ 'shape' => 'Grantee', ], 'Permission' => [ 'shape' => 'Permission', ], ], ], 'GrantFullControl' => [ 'type' => 'string', ], 'GrantRead' => [ 'type' => 'string', ], 'GrantReadACP' => [ 'type' => 'string', ], 'GrantWrite' => [ 'type' => 'string', ], 'GrantWriteACP' => [ 'type' => 'string', ], 'Grantee' => [ 'type' => 'structure', 'required' => [ 'Type', ], 'members' => [ 'DisplayName' => [ 'shape' => 'DisplayName', ], 'EmailAddress' => [ 'shape' => 'EmailAddress', ], 'ID' => [ 'shape' => 'ID', ], 'Type' => [ 'shape' => 'Type', 'locationName' => 'xsi:type', 'xmlAttribute' => true, ], 'URI' => [ 'shape' => 'URI', ], ], 'xmlNamespace' => [ 'prefix' => 'xsi', 'uri' => 'http://www.w3.org/2001/XMLSchema-instance', ], ], 'Grants' => [ 'type' => 'list', 'member' => [ 'shape' => 'Grant', 'locationName' => 'Grant', ], ], 'HeadBucketRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], ], ], 'HeadObjectOutput' => [ 'type' => 'structure', 'members' => [ 'DeleteMarker' => [ 'shape' => 'DeleteMarker', 'location' => 'header', 'locationName' => 'x-amz-delete-marker', ], 'AcceptRanges' => [ 'shape' => 'AcceptRanges', 'location' => 'header', 'locationName' => 'accept-ranges', ], 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'Restore' => [ 'shape' => 'Restore', 'location' => 'header', 'locationName' => 'x-amz-restore', ], 'LastModified' => [ 'shape' => 'LastModified', 'location' => 'header', 'locationName' => 'Last-Modified', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'MissingMeta' => [ 'shape' => 'MissingMeta', 'location' => 'header', 'locationName' => 'x-amz-missing-meta', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], 'ReplicationStatus' => [ 'shape' => 'ReplicationStatus', 'location' => 'header', 'locationName' => 'x-amz-replication-status', ], ], ], 'HeadObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'IfMatch' => [ 'shape' => 'IfMatch', 'location' => 'header', 'locationName' => 'If-Match', ], 'IfModifiedSince' => [ 'shape' => 'IfModifiedSince', 'location' => 'header', 'locationName' => 'If-Modified-Since', ], 'IfNoneMatch' => [ 'shape' => 'IfNoneMatch', 'location' => 'header', 'locationName' => 'If-None-Match', ], 'IfUnmodifiedSince' => [ 'shape' => 'IfUnmodifiedSince', 'location' => 'header', 'locationName' => 'If-Unmodified-Since', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Range' => [ 'shape' => 'Range', 'location' => 'header', 'locationName' => 'Range', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'HostName' => [ 'type' => 'string', ], 'HttpErrorCodeReturnedEquals' => [ 'type' => 'string', ], 'HttpRedirectCode' => [ 'type' => 'string', ], 'ID' => [ 'type' => 'string', ], 'IfMatch' => [ 'type' => 'string', ], 'IfModifiedSince' => [ 'type' => 'timestamp', ], 'IfNoneMatch' => [ 'type' => 'string', ], 'IfUnmodifiedSince' => [ 'type' => 'timestamp', ], 'IndexDocument' => [ 'type' => 'structure', 'required' => [ 'Suffix', ], 'members' => [ 'Suffix' => [ 'shape' => 'Suffix', ], ], ], 'Initiated' => [ 'type' => 'timestamp', ], 'Initiator' => [ 'type' => 'structure', 'members' => [ 'ID' => [ 'shape' => 'ID', ], 'DisplayName' => [ 'shape' => 'DisplayName', ], ], ], 'IsLatest' => [ 'type' => 'boolean', ], 'IsTruncated' => [ 'type' => 'boolean', ], 'KeyMarker' => [ 'type' => 'string', ], 'KeyPrefixEquals' => [ 'type' => 'string', ], 'LambdaFunctionArn' => [ 'type' => 'string', ], 'LambdaFunctionConfiguration' => [ 'type' => 'structure', 'required' => [ 'LambdaFunctionArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'LambdaFunctionArn' => [ 'shape' => 'LambdaFunctionArn', 'locationName' => 'CloudFunction', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'LambdaFunctionConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'LambdaFunctionConfiguration', ], 'flattened' => true, ], 'LastModified' => [ 'type' => 'timestamp', ], 'LifecycleConfiguration' => [ 'type' => 'structure', 'required' => [ 'Rules', ], 'members' => [ 'Rules' => [ 'shape' => 'Rules', 'locationName' => 'Rule', ], ], ], 'LifecycleExpiration' => [ 'type' => 'structure', 'members' => [ 'Date' => [ 'shape' => 'Date', ], 'Days' => [ 'shape' => 'Days', ], ], ], 'LifecycleRule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', ], 'members' => [ 'Expiration' => [ 'shape' => 'LifecycleExpiration', ], 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ExpirationStatus', ], 'Transitions' => [ 'shape' => 'TransitionList', 'locationName' => 'Transition', ], 'NoncurrentVersionTransitions' => [ 'shape' => 'NoncurrentVersionTransitionList', 'locationName' => 'NoncurrentVersionTransition', ], 'NoncurrentVersionExpiration' => [ 'shape' => 'NoncurrentVersionExpiration', ], ], ], 'LifecycleRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'LifecycleRule', ], 'flattened' => true, ], 'ListBucketsOutput' => [ 'type' => 'structure', 'members' => [ 'Buckets' => [ 'shape' => 'Buckets', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ListMultipartUploadsOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', ], 'UploadIdMarker' => [ 'shape' => 'UploadIdMarker', ], 'NextKeyMarker' => [ 'shape' => 'NextKeyMarker', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'NextUploadIdMarker' => [ 'shape' => 'NextUploadIdMarker', ], 'MaxUploads' => [ 'shape' => 'MaxUploads', ], 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Uploads' => [ 'shape' => 'MultipartUploadList', 'locationName' => 'Upload', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListMultipartUploadsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', 'location' => 'querystring', 'locationName' => 'key-marker', ], 'MaxUploads' => [ 'shape' => 'MaxUploads', 'location' => 'querystring', 'locationName' => 'max-uploads', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], 'UploadIdMarker' => [ 'shape' => 'UploadIdMarker', 'location' => 'querystring', 'locationName' => 'upload-id-marker', ], ], ], 'ListObjectVersionsOutput' => [ 'type' => 'structure', 'members' => [ 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', ], 'VersionIdMarker' => [ 'shape' => 'VersionIdMarker', ], 'NextKeyMarker' => [ 'shape' => 'NextKeyMarker', ], 'NextVersionIdMarker' => [ 'shape' => 'NextVersionIdMarker', ], 'Versions' => [ 'shape' => 'ObjectVersionList', 'locationName' => 'Version', ], 'DeleteMarkers' => [ 'shape' => 'DeleteMarkers', 'locationName' => 'DeleteMarker', ], 'Name' => [ 'shape' => 'BucketName', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListObjectVersionsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'KeyMarker' => [ 'shape' => 'KeyMarker', 'location' => 'querystring', 'locationName' => 'key-marker', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', 'location' => 'querystring', 'locationName' => 'max-keys', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], 'VersionIdMarker' => [ 'shape' => 'VersionIdMarker', 'location' => 'querystring', 'locationName' => 'version-id-marker', ], ], ], 'ListObjectsOutput' => [ 'type' => 'structure', 'members' => [ 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Marker' => [ 'shape' => 'Marker', ], 'NextMarker' => [ 'shape' => 'NextMarker', ], 'Contents' => [ 'shape' => 'ObjectList', ], 'Name' => [ 'shape' => 'BucketName', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Delimiter' => [ 'shape' => 'Delimiter', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', ], 'CommonPrefixes' => [ 'shape' => 'CommonPrefixList', ], 'EncodingType' => [ 'shape' => 'EncodingType', ], ], ], 'ListObjectsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Delimiter' => [ 'shape' => 'Delimiter', 'location' => 'querystring', 'locationName' => 'delimiter', ], 'EncodingType' => [ 'shape' => 'EncodingType', 'location' => 'querystring', 'locationName' => 'encoding-type', ], 'Marker' => [ 'shape' => 'Marker', 'location' => 'querystring', 'locationName' => 'marker', ], 'MaxKeys' => [ 'shape' => 'MaxKeys', 'location' => 'querystring', 'locationName' => 'max-keys', ], 'Prefix' => [ 'shape' => 'Prefix', 'location' => 'querystring', 'locationName' => 'prefix', ], ], ], 'ListPartsOutput' => [ 'type' => 'structure', 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'PartNumberMarker' => [ 'shape' => 'PartNumberMarker', ], 'NextPartNumberMarker' => [ 'shape' => 'NextPartNumberMarker', ], 'MaxParts' => [ 'shape' => 'MaxParts', ], 'IsTruncated' => [ 'shape' => 'IsTruncated', ], 'Parts' => [ 'shape' => 'Parts', 'locationName' => 'Part', ], 'Initiator' => [ 'shape' => 'Initiator', ], 'Owner' => [ 'shape' => 'Owner', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'ListPartsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'MaxParts' => [ 'shape' => 'MaxParts', 'location' => 'querystring', 'locationName' => 'max-parts', ], 'PartNumberMarker' => [ 'shape' => 'PartNumberMarker', 'location' => 'querystring', 'locationName' => 'part-number-marker', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'Location' => [ 'type' => 'string', ], 'LoggingEnabled' => [ 'type' => 'structure', 'members' => [ 'TargetBucket' => [ 'shape' => 'TargetBucket', ], 'TargetGrants' => [ 'shape' => 'TargetGrants', ], 'TargetPrefix' => [ 'shape' => 'TargetPrefix', ], ], ], 'MFA' => [ 'type' => 'string', ], 'MFADelete' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'MFADeleteStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'Marker' => [ 'type' => 'string', ], 'MaxAgeSeconds' => [ 'type' => 'integer', ], 'MaxKeys' => [ 'type' => 'integer', ], 'MaxParts' => [ 'type' => 'integer', ], 'MaxUploads' => [ 'type' => 'integer', ], 'Message' => [ 'type' => 'string', ], 'Metadata' => [ 'type' => 'map', 'key' => [ 'shape' => 'MetadataKey', ], 'value' => [ 'shape' => 'MetadataValue', ], ], 'MetadataDirective' => [ 'type' => 'string', 'enum' => [ 'COPY', 'REPLACE', ], ], 'MetadataKey' => [ 'type' => 'string', ], 'MetadataValue' => [ 'type' => 'string', ], 'MissingMeta' => [ 'type' => 'integer', ], 'MultipartUpload' => [ 'type' => 'structure', 'members' => [ 'UploadId' => [ 'shape' => 'MultipartUploadId', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'Initiated' => [ 'shape' => 'Initiated', ], 'StorageClass' => [ 'shape' => 'StorageClass', ], 'Owner' => [ 'shape' => 'Owner', ], 'Initiator' => [ 'shape' => 'Initiator', ], ], ], 'MultipartUploadId' => [ 'type' => 'string', ], 'MultipartUploadList' => [ 'type' => 'list', 'member' => [ 'shape' => 'MultipartUpload', ], 'flattened' => true, ], 'NextKeyMarker' => [ 'type' => 'string', ], 'NextMarker' => [ 'type' => 'string', ], 'NextPartNumberMarker' => [ 'type' => 'integer', ], 'NextUploadIdMarker' => [ 'type' => 'string', ], 'NextVersionIdMarker' => [ 'type' => 'string', ], 'NoSuchBucket' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchKey' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoSuchUpload' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'NoncurrentVersionExpiration' => [ 'type' => 'structure', 'members' => [ 'NoncurrentDays' => [ 'shape' => 'Days', ], ], ], 'NoncurrentVersionTransition' => [ 'type' => 'structure', 'members' => [ 'NoncurrentDays' => [ 'shape' => 'Days', ], 'StorageClass' => [ 'shape' => 'TransitionStorageClass', ], ], ], 'NoncurrentVersionTransitionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'NoncurrentVersionTransition', ], 'flattened' => true, ], 'NotificationConfiguration' => [ 'type' => 'structure', 'members' => [ 'TopicConfigurations' => [ 'shape' => 'TopicConfigurationList', 'locationName' => 'TopicConfiguration', ], 'QueueConfigurations' => [ 'shape' => 'QueueConfigurationList', 'locationName' => 'QueueConfiguration', ], 'LambdaFunctionConfigurations' => [ 'shape' => 'LambdaFunctionConfigurationList', 'locationName' => 'CloudFunctionConfiguration', ], ], ], 'NotificationConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'TopicConfiguration' => [ 'shape' => 'TopicConfigurationDeprecated', ], 'QueueConfiguration' => [ 'shape' => 'QueueConfigurationDeprecated', ], 'CloudFunctionConfiguration' => [ 'shape' => 'CloudFunctionConfiguration', ], ], ], 'NotificationConfigurationFilter' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'S3KeyFilter', 'locationName' => 'S3Key', ], ], ], 'NotificationId' => [ 'type' => 'string', ], 'Object' => [ 'type' => 'structure', 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], 'StorageClass' => [ 'shape' => 'ObjectStorageClass', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ObjectAlreadyInActiveTierError' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ObjectCannedACL' => [ 'type' => 'string', 'enum' => [ 'private', 'public-read', 'public-read-write', 'authenticated-read', 'aws-exec-read', 'bucket-owner-read', 'bucket-owner-full-control', ], ], 'ObjectIdentifier' => [ 'type' => 'structure', 'required' => [ 'Key', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], ], ], 'ObjectIdentifierList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ObjectIdentifier', ], 'flattened' => true, ], 'ObjectKey' => [ 'type' => 'string', 'min' => 1, ], 'ObjectList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Object', ], 'flattened' => true, ], 'ObjectNotInActiveTierError' => [ 'type' => 'structure', 'members' => [], 'exception' => true, ], 'ObjectStorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', 'REDUCED_REDUNDANCY', 'GLACIER', ], ], 'ObjectVersion' => [ 'type' => 'structure', 'members' => [ 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], 'StorageClass' => [ 'shape' => 'ObjectVersionStorageClass', ], 'Key' => [ 'shape' => 'ObjectKey', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', ], 'IsLatest' => [ 'shape' => 'IsLatest', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'Owner' => [ 'shape' => 'Owner', ], ], ], 'ObjectVersionId' => [ 'type' => 'string', ], 'ObjectVersionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'ObjectVersion', ], 'flattened' => true, ], 'ObjectVersionStorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', ], ], 'Owner' => [ 'type' => 'structure', 'members' => [ 'DisplayName' => [ 'shape' => 'DisplayName', ], 'ID' => [ 'shape' => 'ID', ], ], ], 'Part' => [ 'type' => 'structure', 'members' => [ 'PartNumber' => [ 'shape' => 'PartNumber', ], 'LastModified' => [ 'shape' => 'LastModified', ], 'ETag' => [ 'shape' => 'ETag', ], 'Size' => [ 'shape' => 'Size', ], ], ], 'PartNumber' => [ 'type' => 'integer', ], 'PartNumberMarker' => [ 'type' => 'integer', ], 'Parts' => [ 'type' => 'list', 'member' => [ 'shape' => 'Part', ], 'flattened' => true, ], 'Payer' => [ 'type' => 'string', 'enum' => [ 'Requester', 'BucketOwner', ], ], 'Permission' => [ 'type' => 'string', 'enum' => [ 'FULL_CONTROL', 'WRITE', 'WRITE_ACP', 'READ', 'READ_ACP', ], ], 'Policy' => [ 'type' => 'string', ], 'Prefix' => [ 'type' => 'string', ], 'Protocol' => [ 'type' => 'string', 'enum' => [ 'http', 'https', ], ], 'PutBucketAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'ACL' => [ 'shape' => 'BucketCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'AccessControlPolicy' => [ 'shape' => 'AccessControlPolicy', 'locationName' => 'AccessControlPolicy', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], ], 'payload' => 'AccessControlPolicy', ], 'PutBucketCorsRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CORSConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CORSConfiguration' => [ 'shape' => 'CORSConfiguration', 'locationName' => 'CORSConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], ], 'payload' => 'CORSConfiguration', ], 'PutBucketLifecycleConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'LifecycleConfiguration' => [ 'shape' => 'BucketLifecycleConfiguration', 'locationName' => 'LifecycleConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'LifecycleConfiguration', ], 'PutBucketLifecycleRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'LifecycleConfiguration' => [ 'shape' => 'LifecycleConfiguration', 'locationName' => 'LifecycleConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'LifecycleConfiguration', ], 'PutBucketLoggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'BucketLoggingStatus', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'BucketLoggingStatus' => [ 'shape' => 'BucketLoggingStatus', 'locationName' => 'BucketLoggingStatus', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], ], 'payload' => 'BucketLoggingStatus', ], 'PutBucketNotificationConfigurationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'NotificationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'NotificationConfiguration' => [ 'shape' => 'NotificationConfiguration', 'locationName' => 'NotificationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'NotificationConfiguration', ], 'PutBucketNotificationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'NotificationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'NotificationConfiguration' => [ 'shape' => 'NotificationConfigurationDeprecated', 'locationName' => 'NotificationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'NotificationConfiguration', ], 'PutBucketPolicyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Policy', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Policy' => [ 'shape' => 'Policy', ], ], 'payload' => 'Policy', ], 'PutBucketReplicationRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'ReplicationConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'ReplicationConfiguration' => [ 'shape' => 'ReplicationConfiguration', 'locationName' => 'ReplicationConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'ReplicationConfiguration', ], 'PutBucketRequestPaymentRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'RequestPaymentConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'RequestPaymentConfiguration' => [ 'shape' => 'RequestPaymentConfiguration', 'locationName' => 'RequestPaymentConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'RequestPaymentConfiguration', ], 'PutBucketTaggingRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Tagging', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Tagging' => [ 'shape' => 'Tagging', 'locationName' => 'Tagging', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'Tagging', ], 'PutBucketVersioningRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'VersioningConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'MFA' => [ 'shape' => 'MFA', 'location' => 'header', 'locationName' => 'x-amz-mfa', ], 'VersioningConfiguration' => [ 'shape' => 'VersioningConfiguration', 'locationName' => 'VersioningConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'VersioningConfiguration', ], 'PutBucketWebsiteRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'WebsiteConfiguration', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'WebsiteConfiguration' => [ 'shape' => 'WebsiteConfiguration', 'locationName' => 'WebsiteConfiguration', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], ], 'payload' => 'WebsiteConfiguration', ], 'PutObjectAclOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'PutObjectAclRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'AccessControlPolicy' => [ 'shape' => 'AccessControlPolicy', 'locationName' => 'AccessControlPolicy', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWrite' => [ 'shape' => 'GrantWrite', 'location' => 'header', 'locationName' => 'x-amz-grant-write', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'AccessControlPolicy', ], 'PutObjectOutput' => [ 'type' => 'structure', 'members' => [ 'Expiration' => [ 'shape' => 'Expiration', 'location' => 'header', 'locationName' => 'x-amz-expiration', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'header', 'locationName' => 'x-amz-version-id', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'PutObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'ACL' => [ 'shape' => 'ObjectCannedACL', 'location' => 'header', 'locationName' => 'x-amz-acl', ], 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CacheControl' => [ 'shape' => 'CacheControl', 'location' => 'header', 'locationName' => 'Cache-Control', ], 'ContentDisposition' => [ 'shape' => 'ContentDisposition', 'location' => 'header', 'locationName' => 'Content-Disposition', ], 'ContentEncoding' => [ 'shape' => 'ContentEncoding', 'location' => 'header', 'locationName' => 'Content-Encoding', ], 'ContentLanguage' => [ 'shape' => 'ContentLanguage', 'location' => 'header', 'locationName' => 'Content-Language', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'ContentType' => [ 'shape' => 'ContentType', 'location' => 'header', 'locationName' => 'Content-Type', ], 'Expires' => [ 'shape' => 'Expires', 'location' => 'header', 'locationName' => 'Expires', ], 'GrantFullControl' => [ 'shape' => 'GrantFullControl', 'location' => 'header', 'locationName' => 'x-amz-grant-full-control', ], 'GrantRead' => [ 'shape' => 'GrantRead', 'location' => 'header', 'locationName' => 'x-amz-grant-read', ], 'GrantReadACP' => [ 'shape' => 'GrantReadACP', 'location' => 'header', 'locationName' => 'x-amz-grant-read-acp', ], 'GrantWriteACP' => [ 'shape' => 'GrantWriteACP', 'location' => 'header', 'locationName' => 'x-amz-grant-write-acp', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'Metadata' => [ 'shape' => 'Metadata', 'location' => 'headers', 'locationName' => 'x-amz-meta-', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'StorageClass' => [ 'shape' => 'StorageClass', 'location' => 'header', 'locationName' => 'x-amz-storage-class', ], 'WebsiteRedirectLocation' => [ 'shape' => 'WebsiteRedirectLocation', 'location' => 'header', 'locationName' => 'x-amz-website-redirect-location', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Body', ], 'QueueArn' => [ 'type' => 'string', ], 'QueueConfiguration' => [ 'type' => 'structure', 'required' => [ 'QueueArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'QueueArn' => [ 'shape' => 'QueueArn', 'locationName' => 'Queue', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'QueueConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Queue' => [ 'shape' => 'QueueArn', ], ], ], 'QueueConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'QueueConfiguration', ], 'flattened' => true, ], 'Quiet' => [ 'type' => 'boolean', ], 'Range' => [ 'type' => 'string', ], 'Redirect' => [ 'type' => 'structure', 'members' => [ 'HostName' => [ 'shape' => 'HostName', ], 'HttpRedirectCode' => [ 'shape' => 'HttpRedirectCode', ], 'Protocol' => [ 'shape' => 'Protocol', ], 'ReplaceKeyPrefixWith' => [ 'shape' => 'ReplaceKeyPrefixWith', ], 'ReplaceKeyWith' => [ 'shape' => 'ReplaceKeyWith', ], ], ], 'RedirectAllRequestsTo' => [ 'type' => 'structure', 'required' => [ 'HostName', ], 'members' => [ 'HostName' => [ 'shape' => 'HostName', ], 'Protocol' => [ 'shape' => 'Protocol', ], ], ], 'ReplaceKeyPrefixWith' => [ 'type' => 'string', ], 'ReplaceKeyWith' => [ 'type' => 'string', ], 'ReplicationConfiguration' => [ 'type' => 'structure', 'required' => [ 'Role', 'Rules', ], 'members' => [ 'Role' => [ 'shape' => 'Role', ], 'Rules' => [ 'shape' => 'ReplicationRules', 'locationName' => 'Rule', ], ], ], 'ReplicationRule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', 'Destination', ], 'members' => [ 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ReplicationRuleStatus', ], 'Destination' => [ 'shape' => 'Destination', ], ], ], 'ReplicationRuleStatus' => [ 'type' => 'string', 'enum' => [ 'Enabled', 'Disabled', ], ], 'ReplicationRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'ReplicationRule', ], 'flattened' => true, ], 'ReplicationStatus' => [ 'type' => 'string', 'enum' => [ 'COMPLETE', 'PENDING', 'FAILED', 'REPLICA', ], ], 'RequestCharged' => [ 'type' => 'string', 'enum' => [ 'requester', ], ], 'RequestPayer' => [ 'type' => 'string', 'enum' => [ 'requester', ], ], 'RequestPaymentConfiguration' => [ 'type' => 'structure', 'required' => [ 'Payer', ], 'members' => [ 'Payer' => [ 'shape' => 'Payer', ], ], ], 'ResponseCacheControl' => [ 'type' => 'string', ], 'ResponseContentDisposition' => [ 'type' => 'string', ], 'ResponseContentEncoding' => [ 'type' => 'string', ], 'ResponseContentLanguage' => [ 'type' => 'string', ], 'ResponseContentType' => [ 'type' => 'string', ], 'ResponseExpires' => [ 'type' => 'timestamp', ], 'Restore' => [ 'type' => 'string', ], 'RestoreObjectOutput' => [ 'type' => 'structure', 'members' => [ 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'RestoreObjectRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'VersionId' => [ 'shape' => 'ObjectVersionId', 'location' => 'querystring', 'locationName' => 'versionId', ], 'RestoreRequest' => [ 'shape' => 'RestoreRequest', 'locationName' => 'RestoreRequest', 'xmlNamespace' => [ 'uri' => 'http://s3.amazonaws.com/doc/2006-03-01/', ], ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'RestoreRequest', ], 'RestoreRequest' => [ 'type' => 'structure', 'required' => [ 'Days', ], 'members' => [ 'Days' => [ 'shape' => 'Days', ], ], ], 'Role' => [ 'type' => 'string', ], 'RoutingRule' => [ 'type' => 'structure', 'required' => [ 'Redirect', ], 'members' => [ 'Condition' => [ 'shape' => 'Condition', ], 'Redirect' => [ 'shape' => 'Redirect', ], ], ], 'RoutingRules' => [ 'type' => 'list', 'member' => [ 'shape' => 'RoutingRule', 'locationName' => 'RoutingRule', ], ], 'Rule' => [ 'type' => 'structure', 'required' => [ 'Prefix', 'Status', ], 'members' => [ 'Expiration' => [ 'shape' => 'LifecycleExpiration', ], 'ID' => [ 'shape' => 'ID', ], 'Prefix' => [ 'shape' => 'Prefix', ], 'Status' => [ 'shape' => 'ExpirationStatus', ], 'Transition' => [ 'shape' => 'Transition', ], 'NoncurrentVersionTransition' => [ 'shape' => 'NoncurrentVersionTransition', ], 'NoncurrentVersionExpiration' => [ 'shape' => 'NoncurrentVersionExpiration', ], ], ], 'Rules' => [ 'type' => 'list', 'member' => [ 'shape' => 'Rule', ], 'flattened' => true, ], 'S3KeyFilter' => [ 'type' => 'structure', 'members' => [ 'FilterRules' => [ 'shape' => 'FilterRuleList', 'locationName' => 'FilterRule', ], ], ], 'SSECustomerAlgorithm' => [ 'type' => 'string', ], 'SSECustomerKey' => [ 'type' => 'string', 'sensitive' => true, ], 'SSECustomerKeyMD5' => [ 'type' => 'string', ], 'SSEKMSKeyId' => [ 'type' => 'string', 'sensitive' => true, ], 'ServerSideEncryption' => [ 'type' => 'string', 'enum' => [ 'AES256', 'aws:kms', ], ], 'Size' => [ 'type' => 'integer', ], 'StorageClass' => [ 'type' => 'string', 'enum' => [ 'STANDARD', 'REDUCED_REDUNDANCY', 'STANDARD_IA', ], ], 'Suffix' => [ 'type' => 'string', ], 'Tag' => [ 'type' => 'structure', 'required' => [ 'Key', 'Value', ], 'members' => [ 'Key' => [ 'shape' => 'ObjectKey', ], 'Value' => [ 'shape' => 'Value', ], ], ], 'TagSet' => [ 'type' => 'list', 'member' => [ 'shape' => 'Tag', 'locationName' => 'Tag', ], ], 'Tagging' => [ 'type' => 'structure', 'required' => [ 'TagSet', ], 'members' => [ 'TagSet' => [ 'shape' => 'TagSet', ], ], ], 'TargetBucket' => [ 'type' => 'string', ], 'TargetGrant' => [ 'type' => 'structure', 'members' => [ 'Grantee' => [ 'shape' => 'Grantee', ], 'Permission' => [ 'shape' => 'BucketLogsPermission', ], ], ], 'TargetGrants' => [ 'type' => 'list', 'member' => [ 'shape' => 'TargetGrant', 'locationName' => 'Grant', ], ], 'TargetPrefix' => [ 'type' => 'string', ], 'TopicArn' => [ 'type' => 'string', ], 'TopicConfiguration' => [ 'type' => 'structure', 'required' => [ 'TopicArn', 'Events', ], 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'TopicArn' => [ 'shape' => 'TopicArn', 'locationName' => 'Topic', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Filter' => [ 'shape' => 'NotificationConfigurationFilter', ], ], ], 'TopicConfigurationDeprecated' => [ 'type' => 'structure', 'members' => [ 'Id' => [ 'shape' => 'NotificationId', ], 'Events' => [ 'shape' => 'EventList', 'locationName' => 'Event', ], 'Event' => [ 'shape' => 'Event', 'deprecated' => true, ], 'Topic' => [ 'shape' => 'TopicArn', ], ], ], 'TopicConfigurationList' => [ 'type' => 'list', 'member' => [ 'shape' => 'TopicConfiguration', ], 'flattened' => true, ], 'Transition' => [ 'type' => 'structure', 'members' => [ 'Date' => [ 'shape' => 'Date', ], 'Days' => [ 'shape' => 'Days', ], 'StorageClass' => [ 'shape' => 'TransitionStorageClass', ], ], ], 'TransitionList' => [ 'type' => 'list', 'member' => [ 'shape' => 'Transition', ], 'flattened' => true, ], 'TransitionStorageClass' => [ 'type' => 'string', 'enum' => [ 'GLACIER', 'STANDARD_IA', ], ], 'Type' => [ 'type' => 'string', 'enum' => [ 'CanonicalUser', 'AmazonCustomerByEmail', 'Group', ], ], 'URI' => [ 'type' => 'string', ], 'UploadIdMarker' => [ 'type' => 'string', ], 'UploadPartCopyOutput' => [ 'type' => 'structure', 'members' => [ 'CopySourceVersionId' => [ 'shape' => 'CopySourceVersionId', 'location' => 'header', 'locationName' => 'x-amz-copy-source-version-id', ], 'CopyPartResult' => [ 'shape' => 'CopyPartResult', ], 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], 'payload' => 'CopyPartResult', ], 'UploadPartCopyRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'CopySource', 'Key', 'PartNumber', 'UploadId', ], 'members' => [ 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'CopySource' => [ 'shape' => 'CopySource', 'location' => 'header', 'locationName' => 'x-amz-copy-source', ], 'CopySourceIfMatch' => [ 'shape' => 'CopySourceIfMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-match', ], 'CopySourceIfModifiedSince' => [ 'shape' => 'CopySourceIfModifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-modified-since', ], 'CopySourceIfNoneMatch' => [ 'shape' => 'CopySourceIfNoneMatch', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-none-match', ], 'CopySourceIfUnmodifiedSince' => [ 'shape' => 'CopySourceIfUnmodifiedSince', 'location' => 'header', 'locationName' => 'x-amz-copy-source-if-unmodified-since', ], 'CopySourceRange' => [ 'shape' => 'CopySourceRange', 'location' => 'header', 'locationName' => 'x-amz-copy-source-range', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'PartNumber' => [ 'shape' => 'PartNumber', 'location' => 'querystring', 'locationName' => 'partNumber', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'CopySourceSSECustomerAlgorithm' => [ 'shape' => 'CopySourceSSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-algorithm', ], 'CopySourceSSECustomerKey' => [ 'shape' => 'CopySourceSSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key', ], 'CopySourceSSECustomerKeyMD5' => [ 'shape' => 'CopySourceSSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-copy-source-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], ], 'UploadPartOutput' => [ 'type' => 'structure', 'members' => [ 'ServerSideEncryption' => [ 'shape' => 'ServerSideEncryption', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption', ], 'ETag' => [ 'shape' => 'ETag', 'location' => 'header', 'locationName' => 'ETag', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'SSEKMSKeyId' => [ 'shape' => 'SSEKMSKeyId', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-aws-kms-key-id', ], 'RequestCharged' => [ 'shape' => 'RequestCharged', 'location' => 'header', 'locationName' => 'x-amz-request-charged', ], ], ], 'UploadPartRequest' => [ 'type' => 'structure', 'required' => [ 'Bucket', 'Key', 'PartNumber', 'UploadId', ], 'members' => [ 'Body' => [ 'shape' => 'Body', 'streaming' => true, ], 'Bucket' => [ 'shape' => 'BucketName', 'location' => 'uri', 'locationName' => 'Bucket', ], 'ContentLength' => [ 'shape' => 'ContentLength', 'location' => 'header', 'locationName' => 'Content-Length', ], 'ContentMD5' => [ 'shape' => 'ContentMD5', 'location' => 'header', 'locationName' => 'Content-MD5', ], 'Key' => [ 'shape' => 'ObjectKey', 'location' => 'uri', 'locationName' => 'Key', ], 'PartNumber' => [ 'shape' => 'PartNumber', 'location' => 'querystring', 'locationName' => 'partNumber', ], 'UploadId' => [ 'shape' => 'MultipartUploadId', 'location' => 'querystring', 'locationName' => 'uploadId', ], 'SSECustomerAlgorithm' => [ 'shape' => 'SSECustomerAlgorithm', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-algorithm', ], 'SSECustomerKey' => [ 'shape' => 'SSECustomerKey', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key', ], 'SSECustomerKeyMD5' => [ 'shape' => 'SSECustomerKeyMD5', 'location' => 'header', 'locationName' => 'x-amz-server-side-encryption-customer-key-MD5', ], 'RequestPayer' => [ 'shape' => 'RequestPayer', 'location' => 'header', 'locationName' => 'x-amz-request-payer', ], ], 'payload' => 'Body', ], 'Value' => [ 'type' => 'string', ], 'VersionIdMarker' => [ 'type' => 'string', ], 'VersioningConfiguration' => [ 'type' => 'structure', 'members' => [ 'MFADelete' => [ 'shape' => 'MFADelete', 'locationName' => 'MfaDelete', ], 'Status' => [ 'shape' => 'BucketVersioningStatus', ], ], ], 'WebsiteConfiguration' => [ 'type' => 'structure', 'members' => [ 'ErrorDocument' => [ 'shape' => 'ErrorDocument', ], 'IndexDocument' => [ 'shape' => 'IndexDocument', ], 'RedirectAllRequestsTo' => [ 'shape' => 'RedirectAllRequestsTo', ], 'RoutingRules' => [ 'shape' => 'RoutingRules', ], ], ], 'WebsiteRedirectLocation' => [ 'type' => 'string', ], ],];
|
includes/aws/Aws/data/s3/2006-03-01/paginators-1.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/s3/2006-03-01/paginators-1.json
|
3 |
+
return [ 'pagination' => [ 'ListBuckets' => [ 'result_key' => 'Buckets', ], 'ListMultipartUploads' => [ 'input_token' => [ 'KeyMarker', 'UploadIdMarker', ], 'limit_key' => 'MaxUploads', 'more_results' => 'IsTruncated', 'output_token' => [ 'NextKeyMarker', 'NextUploadIdMarker', ], 'result_key' => [ 'Uploads', 'CommonPrefixes', ], ], 'ListObjectVersions' => [ 'input_token' => [ 'KeyMarker', 'VersionIdMarker', ], 'limit_key' => 'MaxKeys', 'more_results' => 'IsTruncated', 'output_token' => [ 'NextKeyMarker', 'NextVersionIdMarker', ], 'result_key' => [ 'Versions', 'DeleteMarkers', 'CommonPrefixes', ], ], 'ListObjects' => [ 'input_token' => 'Marker', 'limit_key' => 'MaxKeys', 'more_results' => 'IsTruncated', 'output_token' => 'NextMarker || Contents[-1].Key', 'result_key' => [ 'Contents', 'CommonPrefixes', ], ], 'ListParts' => [ 'input_token' => 'PartNumberMarker', 'limit_key' => 'MaxParts', 'more_results' => 'IsTruncated', 'output_token' => 'NextPartNumberMarker', 'result_key' => 'Parts', ], ],];
|
includes/aws/Aws/data/s3/2006-03-01/waiters-2.json.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// This file was auto-generated from sdk-root/src/data/s3/2006-03-01/waiters-2.json
|
3 |
+
return [ 'version' => 2, 'waiters' => [ 'BucketExists' => [ 'acceptors' => [ [ 'expected' => 200, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 403, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 404, 'matcher' => 'status', 'state' => 'retry', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadBucket', ], 'BucketNotExists' => [ 'acceptors' => [ [ 'expected' => 404, 'matcher' => 'status', 'state' => 'success', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadBucket', ], 'ObjectExists' => [ 'acceptors' => [ [ 'expected' => 200, 'matcher' => 'status', 'state' => 'success', ], [ 'expected' => 404, 'matcher' => 'status', 'state' => 'retry', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadObject', ], 'ObjectNotExists' => [ 'acceptors' => [ [ 'expected' => 404, 'matcher' => 'status', 'state' => 'success', ], ], 'delay' => 5, 'maxAttempts' => 20, 'operation' => 'HeadObject', ], ],];
|
includes/aws/Aws/functions.php
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aws;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use GuzzleHttp\ClientInterface;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
|
8 |
+
//-----------------------------------------------------------------------------
|
9 |
+
// Functional functions
|
10 |
+
//-----------------------------------------------------------------------------
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Returns a function that always returns the same value;
|
14 |
+
*
|
15 |
+
* @param mixed $value Value to return.
|
16 |
+
*
|
17 |
+
* @return callable
|
18 |
+
*/
|
19 |
+
function constantly($value)
|
20 |
+
{
|
21 |
+
return function () use ($value) { return $value; };
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Filters values that do not satisfy the predicate function $pred.
|
26 |
+
*
|
27 |
+
* @param mixed $iterable Iterable sequence of data.
|
28 |
+
* @param callable $pred Function that accepts a value and returns true/false
|
29 |
+
*
|
30 |
+
* @return \Generator
|
31 |
+
*/
|
32 |
+
function filter($iterable, callable $pred)
|
33 |
+
{
|
34 |
+
foreach ($iterable as $value) {
|
35 |
+
if ($pred($value)) {
|
36 |
+
yield $value;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Applies a map function $f to each value in a collection.
|
43 |
+
*
|
44 |
+
* @param mixed $iterable Iterable sequence of data.
|
45 |
+
* @param callable $f Map function to apply.
|
46 |
+
*
|
47 |
+
* @return \Generator
|
48 |
+
*/
|
49 |
+
function map($iterable, callable $f)
|
50 |
+
{
|
51 |
+
foreach ($iterable as $value) {
|
52 |
+
yield $f($value);
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Creates a generator that iterates over a sequence, then iterates over each
|
58 |
+
* value in the sequence and yields the application of the map function to each
|
59 |
+
* value.
|
60 |
+
*
|
61 |
+
* @param mixed $iterable Iterable sequence of data.
|
62 |
+
* @param callable $f Map function to apply.
|
63 |
+
*
|
64 |
+
* @return \Generator
|
65 |
+
*/
|
66 |
+
function flatmap($iterable, callable $f)
|
67 |
+
{
|
68 |
+
foreach (map($iterable, $f) as $outer) {
|
69 |
+
foreach ($outer as $inner) {
|
70 |
+
yield $inner;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Partitions the input sequence into partitions of the specified size.
|
77 |
+
*
|
78 |
+
* @param mixed $iterable Iterable sequence of data.
|
79 |
+
* @param int $size Size to make each partition (except possibly the last chunk)
|
80 |
+
*
|
81 |
+
* @return \Generator
|
82 |
+
*/
|
83 |
+
function partition($iterable, $size)
|
84 |
+
{
|
85 |
+
$buffer = [];
|
86 |
+
foreach ($iterable as $value) {
|
87 |
+
$buffer[] = $value;
|
88 |
+
if (count($buffer) === $size) {
|
89 |
+
yield $buffer;
|
90 |
+
$buffer = [];
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
if ($buffer) {
|
95 |
+
yield $buffer;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Returns a function that invokes the provided variadic functions one
|
101 |
+
* after the other until one of the functions returns a non-null value.
|
102 |
+
* The return function will call each passed function with any arguments it
|
103 |
+
* is provided.
|
104 |
+
*
|
105 |
+
* $a = function ($x, $y) { return null; };
|
106 |
+
* $b = function ($x, $y) { return $x + $y; };
|
107 |
+
* $fn = \Aws\or_chain($a, $b);
|
108 |
+
* echo $fn(1, 2); // 3
|
109 |
+
*
|
110 |
+
* @return callable
|
111 |
+
*/
|
112 |
+
function or_chain()
|
113 |
+
{
|
114 |
+
$fns = func_get_args();
|
115 |
+
return function () use ($fns) {
|
116 |
+
$args = func_get_args();
|
117 |
+
foreach ($fns as $fn) {
|
118 |
+
$result = $args ? call_user_func_array($fn, $args) : $fn();
|
119 |
+
if ($result) {
|
120 |
+
return $result;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
return null;
|
124 |
+
};
|
125 |
+
}
|
126 |
+
|
127 |
+
//-----------------------------------------------------------------------------
|
128 |
+
// JSON compiler and loading functions
|
129 |
+
//-----------------------------------------------------------------------------
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Loads a compiled JSON file from a PHP file.
|
133 |
+
*
|
134 |
+
* If the JSON file has not been cached to disk as a PHP file, it will be loaded
|
135 |
+
* from the JSON source file and returned.
|
136 |
+
*
|
137 |
+
* @param string $path Path to the JSON file on disk
|
138 |
+
*
|
139 |
+
* @return mixed Returns the JSON decoded data. Note that JSON objects are
|
140 |
+
* decoded as associative arrays.
|
141 |
+
*/
|
142 |
+
function load_compiled_json($path)
|
143 |
+
{
|
144 |
+
if ($compiled = @include("$path.php")) {
|
145 |
+
return $compiled;
|
146 |
+
}
|
147 |
+
|
148 |
+
if (!file_exists($path)) {
|
149 |
+
throw new \InvalidArgumentException(
|
150 |
+
sprintf("File not found: %s", $path)
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
return json_decode(file_get_contents($path), true);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* No-op
|
159 |
+
*/
|
160 |
+
function clear_compiled_json()
|
161 |
+
{
|
162 |
+
// pass
|
163 |
+
}
|
164 |
+
|
165 |
+
//-----------------------------------------------------------------------------
|
166 |
+
// Directory iterator functions.
|
167 |
+
//-----------------------------------------------------------------------------
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Iterates over the files in a directory and works with custom wrappers.
|
171 |
+
*
|
172 |
+
* @param string $path Path to open (e.g., "s3://foo/bar").
|
173 |
+
* @param resource $context Stream wrapper context.
|
174 |
+
*
|
175 |
+
* @return \Generator Yields relative filename strings.
|
176 |
+
*/
|
177 |
+
function dir_iterator($path, $context = null)
|
178 |
+
{
|
179 |
+
$dh = $context ? opendir($path, $context) : opendir($path);
|
180 |
+
if (!$dh) {
|
181 |
+
throw new \InvalidArgumentException('File not found: ' . $path);
|
182 |
+
}
|
183 |
+
while (($file = readdir($dh)) !== false) {
|
184 |
+
yield $file;
|
185 |
+
}
|
186 |
+
closedir($dh);
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Returns a recursive directory iterator that yields absolute filenames.
|
191 |
+
*
|
192 |
+
* This iterator is not broken like PHP's built-in DirectoryIterator (which
|
193 |
+
* will read the first file from a stream wrapper, then rewind, then read
|
194 |
+
* it again).
|
195 |
+
*
|
196 |
+
* @param string $path Path to traverse (e.g., s3://bucket/key, /tmp)
|
197 |
+
* @param resource $context Stream context options.
|
198 |
+
*
|
199 |
+
* @return \Generator Yields absolute filenames.
|
200 |
+
*/
|
201 |
+
function recursive_dir_iterator($path, $context = null)
|
202 |
+
{
|
203 |
+
$invalid = ['.' => true, '..' => true];
|
204 |
+
$pathLen = strlen($path) + 1;
|
205 |
+
$iterator = dir_iterator($path, $context);
|
206 |
+
$queue = [];
|
207 |
+
do {
|
208 |
+
while ($iterator->valid()) {
|
209 |
+
$file = $iterator->current();
|
210 |
+
$iterator->next();
|
211 |
+
if (isset($invalid[basename($file)])) {
|
212 |
+
continue;
|
213 |
+
}
|
214 |
+
$fullPath = "{$path}/{$file}";
|
215 |
+
yield $fullPath;
|
216 |
+
if (is_dir($fullPath)) {
|
217 |
+
$queue[] = $iterator;
|
218 |
+
$iterator = map(
|
219 |
+
dir_iterator($fullPath, $context),
|
220 |
+
function ($file) use ($fullPath, $pathLen) {
|
221 |
+
return substr("{$fullPath}/{$file}", $pathLen);
|
222 |
+
}
|
223 |
+
);
|
224 |
+
continue;
|
225 |
+
}
|
226 |
+
}
|
227 |
+
$iterator = array_pop($queue);
|
228 |
+
} while ($iterator);
|
229 |
+
}
|
230 |
+
|
231 |
+
//-----------------------------------------------------------------------------
|
232 |
+
// Misc. functions.
|
233 |
+
//-----------------------------------------------------------------------------
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Debug function used to describe the provided value type and class.
|
237 |
+
*
|
238 |
+
* @param mixed $input
|
239 |
+
*
|
240 |
+
* @return string Returns a string containing the type of the variable and
|
241 |
+
* if a class is provided, the class name.
|
242 |
+
*/
|
243 |
+
function describe_type($input)
|
244 |
+
{
|
245 |
+
switch (gettype($input)) {
|
246 |
+
case 'object':
|
247 |
+
return 'object(' . get_class($input) . ')';
|
248 |
+
case 'array':
|
249 |
+
return 'array(' . count($input) . ')';
|
250 |
+
default:
|
251 |
+
ob_start();
|
252 |
+
var_dump($input);
|
253 |
+
// normalize float vs double
|
254 |
+
return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
255 |
+
}
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Creates a default HTTP handler based on the available clients.
|
260 |
+
*
|
261 |
+
* @return callable
|
262 |
+
*/
|
263 |
+
function default_http_handler()
|
264 |
+
{
|
265 |
+
$version = (string) ClientInterface::VERSION;
|
266 |
+
if ($version[0] === '5') {
|
267 |
+
return new \Aws\Handler\GuzzleV5\GuzzleHandler();
|
268 |
+
} elseif ($version[0] === '6') {
|
269 |
+
return new \Aws\Handler\GuzzleV6\GuzzleHandler();
|
270 |
+
} else {
|
271 |
+
throw new \RuntimeException('Unknown Guzzle version: ' . $version);
|
272 |
+
}
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Serialize a request for a command but do not send it.
|
277 |
+
*
|
278 |
+
* Returns a promise that is fulfilled with the serialized request.
|
279 |
+
*
|
280 |
+
* @param CommandInterface $command Command to serialize.
|
281 |
+
*
|
282 |
+
* @return RequestInterface
|
283 |
+
* @throws \RuntimeException
|
284 |
+
*/
|
285 |
+
function serialize(CommandInterface $command)
|
286 |
+
{
|
287 |
+
$request = null;
|
288 |
+
$handlerList = $command->getHandlerList();
|
289 |
+
|
290 |
+
// Return a mock result.
|
291 |
+
$handlerList->setHandler(
|
292 |
+
function (CommandInterface $_, RequestInterface $r) use (&$request) {
|
293 |
+
$request = $r;
|
294 |
+
return new FulfilledPromise(new Result([]));
|
295 |
+
}
|
296 |
+
);
|
297 |
+
|
298 |
+
call_user_func($handlerList->resolve(), $command)->wait();
|
299 |
+
if (!$request instanceof RequestInterface) {
|
300 |
+
throw new \RuntimeException(
|
301 |
+
'Calling handler did not serialize request'
|
302 |
+
);
|
303 |
+
}
|
304 |
+
|
305 |
+
return $request;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Retrieves data for a service from the SDK's service manifest file.
|
310 |
+
*
|
311 |
+
* Manifest data is stored statically, so it does not need to be loaded more
|
312 |
+
* than once per process. The JSON data is also cached in opcache.
|
313 |
+
*
|
314 |
+
* @param string $service Case-insensitive namespace or endpoint prefix of the
|
315 |
+
* service for which you are retrieving manifest data.
|
316 |
+
*
|
317 |
+
* @return array
|
318 |
+
* @throws \InvalidArgumentException if the service is not supported.
|
319 |
+
*/
|
320 |
+
function manifest($service = null)
|
321 |
+
{
|
322 |
+
// Load the manifest and create aliases for lowercased namespaces
|
323 |
+
static $manifest = [];
|
324 |
+
static $aliases = [];
|
325 |
+
if (empty($manifest)) {
|
326 |
+
$manifest = load_compiled_json(__DIR__ . '/data/manifest.json');
|
327 |
+
foreach ($manifest as $endpoint => $info) {
|
328 |
+
$alias = strtolower($info['namespace']);
|
329 |
+
if ($alias !== $endpoint) {
|
330 |
+
$aliases[$alias] = $endpoint;
|
331 |
+
}
|
332 |
+
}
|
333 |
+
}
|
334 |
+
|
335 |
+
// If no service specified, then return the whole manifest.
|
336 |
+
if ($service === null) {
|
337 |
+
return $manifest;
|
338 |
+
}
|
339 |
+
|
340 |
+
// Look up the service's info in the manifest data.
|
341 |
+
$service = strtolower($service);
|
342 |
+
if (isset($manifest[$service])) {
|
343 |
+
return $manifest[$service] + ['endpoint' => $service];
|
344 |
+
} elseif (isset($aliases[$service])) {
|
345 |
+
return manifest($aliases[$service]);
|
346 |
+
} else {
|
347 |
+
throw new \InvalidArgumentException(
|
348 |
+
"The service \"{$service}\" is not provided by the AWS SDK for PHP."
|
349 |
+
);
|
350 |
+
}
|
351 |
+
}
|
includes/aws/CHANGELOG.md
ADDED
@@ -0,0 +1,1387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# CHANGELOG
|
2 |
+
|
3 |
+
## 3.12.0 - 2015-12-21
|
4 |
+
|
5 |
+
* `Aws\Ecr` - Added support for the Amazon EC2 Container Registry.
|
6 |
+
* `Aws\Emr` - Added support for specifying a service security group when calling
|
7 |
+
the RunJobFlow API.
|
8 |
+
|
9 |
+
## 3.11.7 - 2015-12-17
|
10 |
+
|
11 |
+
* `Aws\CloudFront` - Added support for generating signed cookies.
|
12 |
+
* `Aws\CloudFront` - Added support for GZip compression.
|
13 |
+
* `Aws\CloudTrail` - Added support for multi-region trails.
|
14 |
+
* `Aws\Config` - Added for IAM resource types.
|
15 |
+
* `Aws\Ec2` - Added support for managed NATs.
|
16 |
+
* `Aws\Rds` - Added support for enhanced monitoring.
|
17 |
+
|
18 |
+
## 3.11.6 - 2015-12-15
|
19 |
+
|
20 |
+
* `Aws\Ec2` - Added support for specifying encryption on CopyImage commands.
|
21 |
+
|
22 |
+
## 3.11.5 - 2015-12-08
|
23 |
+
|
24 |
+
* `Aws\AutoScaling` - Added support for setting and describing instance
|
25 |
+
protection status.
|
26 |
+
* `Aws\Emr` - Added support for using release labels instead of version numbers.
|
27 |
+
* `Aws\Rds` - Added support for Aurora encryption at rest.
|
28 |
+
|
29 |
+
## 3.11.4 - 2015-12-03
|
30 |
+
|
31 |
+
* `Aws\DirectoryService` - Added support for launching a fully managed Microsoft
|
32 |
+
Active Directory.
|
33 |
+
* `Aws\Rds` - Added support for specifying a port number when modifying database
|
34 |
+
instances.
|
35 |
+
* `Aws\Route53` - Added support for Traffic Flow, a traffic management service.
|
36 |
+
* `Aws\Ses` - Added support for generating SMTP passwords from credentials.
|
37 |
+
|
38 |
+
## 3.11.3 - 2015-12-01
|
39 |
+
|
40 |
+
* `Aws\Config` - Update documentation.
|
41 |
+
|
42 |
+
## 3.11.2 - 2015-11-23
|
43 |
+
|
44 |
+
* `Aws\Config` - Reverted doc model change.
|
45 |
+
|
46 |
+
## 3.11.1 - 2015-11-23
|
47 |
+
|
48 |
+
* `Aws\Ec2` - Added support for EC2 dedicated hosts.
|
49 |
+
* `Aws\Ecs` - Added support for task stopped reasons and task start and stop
|
50 |
+
times.
|
51 |
+
* `Aws\ElasticBeanstalk` - Added support for composable web applications.
|
52 |
+
* `Aws\S3` - Added support for the `aws-exec-read` canned ACL on objects.
|
53 |
+
|
54 |
+
## 3.11.0 - 2015-11-19
|
55 |
+
|
56 |
+
* `Aws\CognitoIdentity` - Added a CognitoIdentity credentials provider.
|
57 |
+
* `Aws\DeviceFarm` - Marked app ARN as optional on `ScheduleRun` and
|
58 |
+
`GetDevicePoolCompatibility` operations.
|
59 |
+
* `Aws\DynamoDb` - Fixed bug where calling `session_regenerate_id` without
|
60 |
+
changing session data would prevent data from being carried over from the
|
61 |
+
previous session ID.
|
62 |
+
* `Aws\Inspector` - Added support for client-side validation of required
|
63 |
+
parameters throughout service.
|
64 |
+
* Fixed error parser bug where certain errors could throw an uncaught
|
65 |
+
parsing exception.
|
66 |
+
|
67 |
+
## 3.10.1 - 2015-11-12
|
68 |
+
|
69 |
+
* `Aws\Config` - Fixed parsing of null responses.
|
70 |
+
* `Aws\Rds` - Added support for snapshot attributes.
|
71 |
+
|
72 |
+
## 3.10.0 - 2015-11-10
|
73 |
+
|
74 |
+
* `Aws\ApiGateway` - Added support for stage variables.
|
75 |
+
* `Aws\DynamoDb` - Updated the session handler to emit warnings on write and
|
76 |
+
delete failures.
|
77 |
+
* `Aws\DynamoDb` - Fixed session ID assignment timing bug encountered in PHP 7.
|
78 |
+
* `Aws\S3` - Removed ServerSideEncryption parameter from UploadPart operation.
|
79 |
+
* Added jitter to the default retry delay algorithm.
|
80 |
+
* Updated the compatibility test script.
|
81 |
+
|
82 |
+
## 3.9.4 - 2015-11-03
|
83 |
+
|
84 |
+
* `Aws\DeviceFarm` - Added support for managing projects, device pools, runs,
|
85 |
+
and uploads.
|
86 |
+
* `Aws\Sts` - Added support for 64-character role session names.
|
87 |
+
|
88 |
+
## 3.9.3 - 2015-11-02
|
89 |
+
|
90 |
+
* `Aws\Iam` - Added support for service-aware policy simulation.
|
91 |
+
|
92 |
+
## 3.9.2 - 2015-10-29
|
93 |
+
|
94 |
+
* `Aws\ApiGateway` - Fixed parameter name collision that occurred when calling
|
95 |
+
`PutIntegration`.
|
96 |
+
* `Aws\S3` - Added support for asynchronous copy and upload.
|
97 |
+
* `Aws\S3` - Added support for setting a location constraint other than the
|
98 |
+
region of the S3 client.
|
99 |
+
|
100 |
+
## 3.9.1 - 2015-10-26
|
101 |
+
|
102 |
+
* `Aws\ApiGateway` - Fixed erroneous version number. Previous version number
|
103 |
+
support kept for backwards compatibility, but "2015-06-01" should be
|
104 |
+
considered deprecated.
|
105 |
+
|
106 |
+
## 3.9.0 - 2015-10-26
|
107 |
+
|
108 |
+
* `Aws\ApiGateway` - Added support for the **AWS API Gateway** service.
|
109 |
+
* `Aws\Ssm` - Added support for EC2 Run Command, a new EC2 feature that enables
|
110 |
+
you to securely and remotely manage the configuration of your Amazon EC2
|
111 |
+
Windows instances.
|
112 |
+
|
113 |
+
## 3.8.2 - 2015-10-22
|
114 |
+
|
115 |
+
* `Aws\AutoScaling` - Added support for EBS encryption.
|
116 |
+
* `Aws\Iam` - Added support for resource-based policy simulations.
|
117 |
+
|
118 |
+
## 3.8.1 - 2015-10-15
|
119 |
+
|
120 |
+
* `Aws\Kms` - Added support for scheduling and cancelling key deletions and
|
121 |
+
listing retirable grants.
|
122 |
+
* `Aws\S3` - Added support for specifying server side encryption on an when
|
123 |
+
uploading a part of a multipart upload.
|
124 |
+
|
125 |
+
## 3.8.0 - 2015-10-08
|
126 |
+
|
127 |
+
* `Aws\Ecs` - Added support for more Docker options hostname, Docker labels,
|
128 |
+
working directory, networking disabled, privileged execution, read-only root
|
129 |
+
filesystem, DNS servers, DNS search domains, ulimits, log configuration, extra
|
130 |
+
hosts (hosts to add to /etc/hosts), and security options (for MLS systems like
|
131 |
+
SELinux).
|
132 |
+
* `Aws\Iot` - Added support for the **AWS IoT** service.
|
133 |
+
* `Aws\IotDataPlane` - Added support for the **AWS IoT Data Plane** service.
|
134 |
+
* `Aws\Lambda` - Added support for function versioning.
|
135 |
+
|
136 |
+
## 3.7.0 - 2015-10-07
|
137 |
+
|
138 |
+
* `Aws\ConfigService` - Added support for config rules, evaluation strategies,
|
139 |
+
and compliance querying.
|
140 |
+
* `Aws\Firehose` - Added support for the **Amazon Kinesis Firehose** service.
|
141 |
+
* `Aws\Inspector` - Added support for the **Amazon Inspector** service.
|
142 |
+
* `Aws\Kinesis` - Added support for increasing and decreasing stream retention
|
143 |
+
periods.
|
144 |
+
* `Aws\MarketplaceCommerceAnalytics` - Added support for the **AWS Marketplace
|
145 |
+
Commerce Analytics** service.
|
146 |
+
|
147 |
+
## 3.6.0 - 2015-10-06
|
148 |
+
|
149 |
+
* `Aws\CloudFront` - Added support for WebACL identifiers and related
|
150 |
+
operations.
|
151 |
+
* `Aws\CloudFront` - Fixed URL presigner to always sign URL-encoded URLs.
|
152 |
+
* `Aws\Ec2` - Added support for spot blocks.
|
153 |
+
* `Aws\S3` - Fixed byte range specified on multipart copies.
|
154 |
+
* `Aws\Waf` - Added support for AWS WAF.
|
155 |
+
|
156 |
+
## 3.5.0 - 2015-10-01
|
157 |
+
|
158 |
+
* `Aws\Cloudtrail` - Added support for log file integrity validation, log
|
159 |
+
encryption with AWS KMS–Managed Keys (SSE-KMS), and trail tagging.
|
160 |
+
* `Aws\ElasticsearchService` - Added support for the Amazon Elasticsearch
|
161 |
+
Service.
|
162 |
+
* `Aws\Rds` - Added support for resource tags.
|
163 |
+
* `Aws\S3` - Added support for copying objects of any size.
|
164 |
+
* `Aws\Workspaces` - Added support for storage volume encryption with AWS KMS.
|
165 |
+
|
166 |
+
## 3.4.1 - 2015-09-29
|
167 |
+
|
168 |
+
* `Aws\CloudFormation` - Added support for specifying affected resource types
|
169 |
+
in `CreateStack` and `UpdateStack` operations.
|
170 |
+
* `Aws\CloudFormation` - Added support for the `DescribeAccountLimits` API.
|
171 |
+
* `Aws\Ec2` - Added support modifying previously created spot fleet requests.
|
172 |
+
* `Aws\Ses` - Added support for inbound email APIs.
|
173 |
+
* Fixed validation to allow using objects implementing `__toString` for string
|
174 |
+
fields in serialized output.
|
175 |
+
|
176 |
+
## 3.4.0 - 2015-09-24
|
177 |
+
|
178 |
+
* `Aws\S3` - Fixed retry handling of networking errors and client socket timeout
|
179 |
+
errors to ensure the client `retries` option is respected.
|
180 |
+
* Added `@method` annotations on all clients to support autocomplete and static
|
181 |
+
analysis.
|
182 |
+
* Added performance tests to the acceptance test suite.
|
183 |
+
* Fixed error when `getIterator` was called on a paginator with no specified
|
184 |
+
`output_token`.
|
185 |
+
* Added support for reading the `aws_session_token` parameter from credentials
|
186 |
+
files.
|
187 |
+
|
188 |
+
## 3.3.8 - 2015-09-17
|
189 |
+
|
190 |
+
* `Aws\CloudWatchLogs` - Added support for export task operations.
|
191 |
+
|
192 |
+
## 3.3.7 - 2015-09-16
|
193 |
+
|
194 |
+
* `Aws\S3` - Added support for new `STANDARD_IA` storage class.
|
195 |
+
* `Aws\S3` - Added support for specifying storage class in cross-region
|
196 |
+
replication configuration.
|
197 |
+
* `Aws\Sqs` - Added a 'QueueExists' waiter to create a queue and wait until it
|
198 |
+
has been fully provisioned.
|
199 |
+
|
200 |
+
## 3.3.6 - 2015-09-15
|
201 |
+
|
202 |
+
* `Aws\Ec2` - Added support for the "diversified" SpotFleet allocation strategy.
|
203 |
+
* `Aws\Ec2` - Added support for reading `StateMessage` and `DataEncryptionKeyId`
|
204 |
+
from a `DescribeSnapshots` response.
|
205 |
+
* `Aws\Efs` - Added support for using a `MountTargetId` parameter instead of a
|
206 |
+
`FileSystemId` parameter with the `DescribeMountTargets` command.
|
207 |
+
* `Aws\Route53` - Added support for calculated and latency health checks.
|
208 |
+
* `Aws\S3` - Fixed warning emitted by `BatchDelete` when no matching objects
|
209 |
+
were found to delete.
|
210 |
+
|
211 |
+
## 3.3.5 - 2015-09-10
|
212 |
+
|
213 |
+
* `Aws\Iam` - Added support for new policy simulation APIs.
|
214 |
+
* `Aws\Kinesis` - Added support for timestamped GetRecords call.
|
215 |
+
* `Aws\MachineLearning` - Fixed invalid validation constraint on `Predict`
|
216 |
+
operation.
|
217 |
+
* `Aws\S3` - Added support for retrying special error cases with the
|
218 |
+
`ListObjects`, `CompleteMultipartUpload`, `CopyObject`, and `UploadPartCopy`.
|
219 |
+
|
220 |
+
## 3.3.4 - 2015-09-03
|
221 |
+
|
222 |
+
* `Aws\StorageGateway` - Added support for tagging and untagging resources.
|
223 |
+
|
224 |
+
## 3.3.3 - 2015-08-31
|
225 |
+
|
226 |
+
* `Aws\Ec2` - Added support for using instance weights with the
|
227 |
+
`RequestSpotFleet` API.
|
228 |
+
|
229 |
+
## 3.3.2 - 2015-08-27
|
230 |
+
|
231 |
+
* `Aws\ConfigService` - Added support for the `ListDiscoveredResources`
|
232 |
+
operation and new resource types.
|
233 |
+
|
234 |
+
## 3.3.1 - 2015-08-25
|
235 |
+
|
236 |
+
* `Aws\CodePipeline` - Added support for using encryption keys with artifact
|
237 |
+
stores.
|
238 |
+
|
239 |
+
## 3.3.0 - 2015-08-20
|
240 |
+
|
241 |
+
* `Aws\S3` - Added support for event notification filters.
|
242 |
+
* Fixed waiter logic to always retry connection errors.
|
243 |
+
* Added support for per-command retry count overrides.
|
244 |
+
* Added support for defining custom patterns for the client debug log to use
|
245 |
+
to scrub sensitive data from the output logged.
|
246 |
+
* Moved the work being done by `Aws\JsonCompiler` from run time to build time.
|
247 |
+
* Fixed bug causing the phar autoloader not to be found when the phar was loaded
|
248 |
+
from opcache instead of from the filesystem.
|
249 |
+
|
250 |
+
## 3.2.6 - 2015-08-12
|
251 |
+
|
252 |
+
* `Aws\ElasticBeanstalk` - Added support for enhanced health reporting.
|
253 |
+
* `Aws\S3` - Fixed retry middleware to ensure that S3 requests are retried
|
254 |
+
following errors raised by the HTTP handler.
|
255 |
+
* `Aws\S3` - Made the keys of the configuration array passed to the constructor
|
256 |
+
of `MultipartUploader` case-insensitive so that its configuration would not
|
257 |
+
rely on differently-cased keys from that of the `S3Client::putObject`
|
258 |
+
operation.
|
259 |
+
* Added an endpoint validation step to the `Aws\AwsClient` constructor so that
|
260 |
+
invalid endpoint would be reported immediately.
|
261 |
+
|
262 |
+
## 3.2.5 - 2015-08-06
|
263 |
+
|
264 |
+
* `Aws\Swf` - Added support for invoking AWS Lambda tasks from an Amazon SWF
|
265 |
+
workflow.
|
266 |
+
|
267 |
+
## 3.2.4 - 2015-08-04
|
268 |
+
|
269 |
+
* `Aws\DeviceFarm` - Added support for the `GetAccountSettings` operation and
|
270 |
+
update documentation to reflect new iOS support.
|
271 |
+
* Made PHP7 test failures fail the build.
|
272 |
+
* Added support for custom user-agent additions.
|
273 |
+
|
274 |
+
## 3.2.3 - 2015-07-30
|
275 |
+
|
276 |
+
* `Aws\OpsWorks` - Added support for operations on ECS clusters.
|
277 |
+
* `Aws\Rds` - Added support for cluster operations for Amazon Aurora.
|
278 |
+
|
279 |
+
## 3.2.2 - 2015-07-28
|
280 |
+
|
281 |
+
* `Aws\S3` - Added support for receiving the storage class in the responses for
|
282 |
+
`GetObject` and `HeadObject` operations.
|
283 |
+
* `Aws\CloudWatchLogs` - Added support for 4 new operations: `PutDestination`,
|
284 |
+
`PutDestinationPolicy`, `DescribeDestinations`, and `DeleteDestination`.
|
285 |
+
|
286 |
+
## 3.2.1 - 2015-07-23
|
287 |
+
|
288 |
+
* **SECURITY FIX**: This release addresses a security issue associated with
|
289 |
+
CVE-2015-5723, specifically, fixes improper default directory umask behavior
|
290 |
+
that could potentially allow unauthorized modifications of PHP code.
|
291 |
+
* `Aws\Ec2` - Added support for SpotFleetLaunchSpecification.
|
292 |
+
* `Aws\Emr` - Added support for Amazon EMR release 4.0.0, which includes a new
|
293 |
+
application installation and configuration experience, upgraded versions of
|
294 |
+
Hadoop, Hive, and Spark, and now uses open source standards for ports and
|
295 |
+
paths. To specify an Amazon EMR release, use the release label parameter (AMI
|
296 |
+
versions 3.x and 2.x can still be specified with the AMI version parameter).
|
297 |
+
* `Aws\Glacier` - Added support for the InitiateVaultLock, GetVaultLock,
|
298 |
+
AbortVaultLock, and CompleteVaultLock API operations.
|
299 |
+
* Fixed a memory leak that occurred when clients were created and never used.
|
300 |
+
* Updated JsonCompiler by addressing a potential race condition and ensuring
|
301 |
+
that caches are invalidated when upgrading to a new version of the SDK.
|
302 |
+
* Updated protocol and acceptance tests.
|
303 |
+
|
304 |
+
## 3.2.0 - 2015-07-14
|
305 |
+
|
306 |
+
* `Aws\DeviceFarm` - Added support for AWS DeviceFarm, an app testing service
|
307 |
+
that enables you to test your Android and Fire OS apps on real, physical
|
308 |
+
phones and tablets that are hosted by AWS.
|
309 |
+
* `Aws\DynamoDb` - Added support for consistent scans and update streams.
|
310 |
+
* `Aws\DynamoDbStreams` - Added support for Amazon DynamoDB Streams, giving you
|
311 |
+
the ability to subscribe to the transactional log of all changes transpiring
|
312 |
+
in your DynamoDB table.
|
313 |
+
* `Aws\S3` - Fixed checksum encoding on multipart upload of non-seekable
|
314 |
+
streams.
|
315 |
+
* `Aws\S3\StreamWrapper` - Added guard on rename functionality to ensure wrapper
|
316 |
+
initialized.
|
317 |
+
|
318 |
+
|
319 |
+
## 3.1.0 - 2015-07-09
|
320 |
+
|
321 |
+
* `Aws\CodeCommit` - Added support for AWS CodeCommit, a secure, highly
|
322 |
+
scalable, managed source control service that hosts private Git repositories.
|
323 |
+
* `Aws\CodePipeline` - Added support for AWS CodePipeline, a continuous delivery
|
324 |
+
service that enables you to model, visualize, and automate the steps required
|
325 |
+
to release your software.
|
326 |
+
* `Aws\Iam` - Added support for uploading SSH public keys for authentication
|
327 |
+
with AWS CodeCommit.
|
328 |
+
* `Aws\Ses` - Added support for cross-account sending through the sending
|
329 |
+
authorization feature.
|
330 |
+
|
331 |
+
## 3.0.7 - 2015-07-07
|
332 |
+
|
333 |
+
* `Aws\AutoScaling` - Added support for step policies.
|
334 |
+
* `Aws\CloudHsm` - Fixed a naming collision with the `GetConfig` operation. This
|
335 |
+
operation is now available through the `GetConfigFiles` method.
|
336 |
+
* `Aws\DynamoDb` - Improved performance when unmarshalling complex documents.
|
337 |
+
* `Aws\DynamoDb` - Fixed checksum comparison of uncompressed responses.
|
338 |
+
* `Aws\Ec2` - Added support for encrypted snapshots.
|
339 |
+
* `Aws\S3` - Added support for user-provided SHA256 checksums for S3 uploads.
|
340 |
+
* `Aws\S3` - Added support for custom protocols in `Aws\S3\StreamWrapper`.
|
341 |
+
* Added cucumber integration tests.
|
342 |
+
* Updated the test suite to be compatible with PHP 7-alpha 2.
|
343 |
+
|
344 |
+
## 3.0.6 - 2015-06-24
|
345 |
+
|
346 |
+
* `Aws\CloudFront` - Added support for configurable `MaxTTL` and `DefaultTTL`.
|
347 |
+
* `Aws\ConfigService` - Added support for recording changes for specific
|
348 |
+
resource types.
|
349 |
+
* `Aws\Ecs` - Added support for sorting, deregistering, and overriding
|
350 |
+
environment variables for task definitions.
|
351 |
+
* `Aws\Glacier` - Added support for the `AddTagsToVault`, `ListTagsForVault`,
|
352 |
+
and `RemoveTagsFromVault` API operations.
|
353 |
+
* `Aws\OpwWorks` - Added support for specifying agent versions to be used on
|
354 |
+
instances.
|
355 |
+
* `Aws\Redshift` - Added support for the `CreateSnapshotCopyGrant`,
|
356 |
+
`DescribeSnapshotCopyGrants`, and `DeleteSnapshotCopyGrant` API operations.
|
357 |
+
* Fixed XML attribute serialization.
|
358 |
+
|
359 |
+
## 3.0.5 - 2015-06-18
|
360 |
+
|
361 |
+
* `Aws\CognitoSync` - Fixed an issue in the Signature Version 4 implementation
|
362 |
+
that was causing issues when signing requests to the Cognito Sync service.
|
363 |
+
* `Aws\ConfigService` - Fixed an issue that was preventing the
|
364 |
+
`ConfigServiceClient` from working properly.
|
365 |
+
* `Aws\Ecs` - Added support for sorting, deregistering, and overriding
|
366 |
+
environment variables for task definitions.
|
367 |
+
* `Aws\Iam` - Added new paginator and waiter configurations.
|
368 |
+
* `Aws\S3` - Added support for the `SaveAs` parameter that was in V2.
|
369 |
+
* `Aws\Sqs` - Fixed an issue that was preventing batch message deletion from
|
370 |
+
working properly.
|
371 |
+
* `Aws` - The `Aws\Sdk::createClient()` method is no longer case-sensitive with
|
372 |
+
service names.
|
373 |
+
|
374 |
+
## 3.0.4 - 2015-06-11
|
375 |
+
|
376 |
+
* `Aws\AutoScaling` - Added support for attaching and detaching load balancers.
|
377 |
+
* `Aws\CloudWatchLogs` - Added support for the PutSubscriptionFilter,
|
378 |
+
DescribeSubscriptionFilters, and DeleteSubscriptionFilter operations.
|
379 |
+
* `Aws\CognitoIdentity` - Added support for the DeleteIdentities operation,
|
380 |
+
and hiding disabled identities with the ListIdentities operation.
|
381 |
+
* `Aws\Ec2` - Added support for VPC flow logs and the M4 instance types.
|
382 |
+
* `Aws\Ecs` - Added support for the UpdateContainerAgent operation.
|
383 |
+
* `Aws\S3` - Improvements to how errors are handled in the `StreamWrapper`.
|
384 |
+
* `Aws\StorageGateway` - Added support for the ListVolumeInitiators operation.
|
385 |
+
* `Aws` - Fixes a bug such that empty maps are handled correctly in JSON
|
386 |
+
requests.
|
387 |
+
|
388 |
+
## 3.0.3 - 2015-06-01
|
389 |
+
|
390 |
+
* `Aws\MachineLearning` - Fixed the `Predict` operation to use the provided
|
391 |
+
`PredictEndpoint` as the host.
|
392 |
+
|
393 |
+
## 3.0.2 - 2015-05-29
|
394 |
+
|
395 |
+
* `Aws` - Fixed an issue preventing some clients from being instantiated via
|
396 |
+
their constructors due to a mismatch between class name and endpoint prefix.
|
397 |
+
|
398 |
+
## 3.0.1 - 2015-05-28
|
399 |
+
|
400 |
+
* `Aws\Lambda` - Added Amazon S3 upload support.
|
401 |
+
|
402 |
+
## 3.0.0 - 2015-05-27
|
403 |
+
|
404 |
+
* Asynchronous requests.
|
405 |
+
* Features like _waiters_ and _multipart uploaders_ can also be used
|
406 |
+
asynchronously.
|
407 |
+
* Asynchronous workflows can be created using _promises_ and _coroutines_.
|
408 |
+
* Improved performance of concurrent/batched requests via _command pools_.
|
409 |
+
* Decoupled HTTP layer.
|
410 |
+
* [Guzzle 6](http://guzzlephp.org) is used by default to send requests,
|
411 |
+
but Guzzle 5 is also supported out of the box.
|
412 |
+
* The SDK can now work in environments where cURL is not available.
|
413 |
+
* Custom HTTP handlers are also supported.
|
414 |
+
* Follows the [PSR-4 and PSR-7 standards](http://php-fig.org).
|
415 |
+
* Middleware system for customizing service client behavior.
|
416 |
+
* Flexible _paginators_ for iterating through paginated results.
|
417 |
+
* Ability to query data from _result_ and _paginator_ objects with
|
418 |
+
[JMESPath](http://jmespath.org/).
|
419 |
+
* Easy debugging via the `'debug'` client configuration option.
|
420 |
+
* Customizable retries via the `'retries'` client configuration option.
|
421 |
+
* More flexibility in credential loading via _credential providers_.
|
422 |
+
* Strictly follows the [SemVer](http://semver.org/) standard going forward.
|
423 |
+
* **For more details about what has changed, see the
|
424 |
+
[Migration Guide](http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/migration.html)**.
|
425 |
+
|
426 |
+
## 2.8.7 - 2015-05-26
|
427 |
+
|
428 |
+
* `Aws\Efs` - Added support for the [Amazon Elastic File System (Amazon
|
429 |
+
EFS)](http://aws.amazon.com/efs/)
|
430 |
+
* Failing to parse an XML error response will now fail gracefully as a
|
431 |
+
`PhpInternalXmlParseError` AWS error code.
|
432 |
+
|
433 |
+
## 2.8.6 - 2015-05-21
|
434 |
+
|
435 |
+
* `Aws\ElasticBeanstalk` - Added support for ResourceName configuration.
|
436 |
+
* `Aws\ElasticTranscoder` - Added support for configuring AudioPackingMode and
|
437 |
+
additional CodecOptions.
|
438 |
+
* `Aws\Kinesis` - Added support for MillisBehindLatest in the result of
|
439 |
+
GetRecordsOutput.
|
440 |
+
* `Aws\Kms` - Added support for the UpdateAlias operation.
|
441 |
+
* `Aws\Lambda` - Fixed an issue with the UpdateFunctionCode operation.
|
442 |
+
|
443 |
+
## 2.8.5 - 2015-05-18
|
444 |
+
|
445 |
+
* `Aws\Ec2\Ec2Client` - Added support for the new spot fleet API operations.
|
446 |
+
* `Aws\OpsWorks\OpsWorksClient` - Added support for custom auto-scaling based
|
447 |
+
on CloudWatch alarms.
|
448 |
+
|
449 |
+
## 2.8.4 - 2015-05-14
|
450 |
+
|
451 |
+
* `Aws\DirectoryService` - Added support for the AWS Directory Service.
|
452 |
+
* `Aws\CloudWatchLogs` - Adds support for the FilterLogEvents operation.
|
453 |
+
* `Aws\CloudFormation` - Adds additional data to the GetTemplateSummary
|
454 |
+
operation.
|
455 |
+
* `Aws\Ec2` - Adds support for Amazon VPC endpoints for Amazon S3 and APIs for
|
456 |
+
migrating Elastic IP Address from EC2-Classic to EC2-VPC.
|
457 |
+
* `Aws\Ec2` - Fixed an issue with cross-region CopySnapshot such that it now
|
458 |
+
works with temporary credentials.
|
459 |
+
* `Aws\Common` - During credential discovery, an invalid credentials file now
|
460 |
+
allows failover to Instance Profile credentials.
|
461 |
+
|
462 |
+
## 2.8.3 - 2015-05-07
|
463 |
+
|
464 |
+
* `Aws\Glacier` - Added support for vault access policies.
|
465 |
+
* `Aws\Route53` - Fixed a `GetCheckerIpRangesResponse` response parsing issue.
|
466 |
+
* `Aws\S3` - Retrying CompleteMultipartUpload failures by retrying the request.
|
467 |
+
* `Aws\S3` - Corrected some response handling in the S3 multipart upload
|
468 |
+
abstraction.
|
469 |
+
* Expiring instance metadata credentials 30 minutes in advance for more eager
|
470 |
+
refreshes before the credentials expire.
|
471 |
+
|
472 |
+
## 2.8.2 - 2015-04-23
|
473 |
+
|
474 |
+
* `Aws\Ec2` - Added support for new VM Import APIs, `including ImportImage`.
|
475 |
+
* `Aws\Iam` - Added support for the `GetAccessKeyLastUsed` operation.
|
476 |
+
* `Aws\CloudSearchDomain` - Search responses now include the expressions requested.
|
477 |
+
|
478 |
+
## 2.8.1 - 2015-04-16
|
479 |
+
|
480 |
+
* `Aws\ConfigService` - Added the 'GetResourceConfigHistory' iterator.
|
481 |
+
* `Aws\CognitoSync` - Added support for events.
|
482 |
+
* `Aws\Lambda` - Fixed an issue with the Invoke operation.
|
483 |
+
|
484 |
+
## 2.8.0 - 2015-04-09
|
485 |
+
|
486 |
+
See the [Upgrading Guide](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md)
|
487 |
+
for details about any changes you may need to make to your code for this upgrade.
|
488 |
+
|
489 |
+
* `Aws\MachineLearning` - Added support for the Amazon Machine Learning service.
|
490 |
+
* `Aws\WorkSpaces` - Added support for the Amazon WorkSpaces service.
|
491 |
+
* `Aws\Ecs` - Added support for the ECS service scheduler operations.
|
492 |
+
* `Aws\S3` - Added support for the `getBucketNotificationConfiguration` and
|
493 |
+
`putBucketNotificationConfiguration` operations to the `S3Client` to replace
|
494 |
+
the, now deprecated, `getBucketNotification` and `putBucketNotification`
|
495 |
+
operations.
|
496 |
+
* [BC] `Aws\Lambda` - Added support for the new AWS Lambda API, which has been
|
497 |
+
changed based on customer feedback during Lambda's preview period.
|
498 |
+
* `Aws\Common` - Deprecated "facades". They will not be present in Version 3 of
|
499 |
+
the SDK.
|
500 |
+
* `Aws\Common` - Added `getAwsErrorCode`, `getAwsErrorType` and `getAwsRequestId`
|
501 |
+
methods to the `ServiceResponseException` to be forward-compatible with
|
502 |
+
Version 3 of the SDK.
|
503 |
+
|
504 |
+
## 2.7.27 - 2015-04-07
|
505 |
+
|
506 |
+
* `Aws\DataPipeline` - Added support for `DeactivatePipeline`
|
507 |
+
* `Aws\ElasticBeanstalk` - Added support for `AbortEnvironmentUpdate`
|
508 |
+
|
509 |
+
## 2.7.26 - 2015-04-02
|
510 |
+
|
511 |
+
* `Aws\CodeDeploy` - Added support deployments to on-premises instances.
|
512 |
+
* `Aws\Rds` - Added support for the `DescribeCertificates` operation.
|
513 |
+
* `Aws\ElasticTranscoder` - Added support for protecting content with PlayReady
|
514 |
+
Digital Rights Management (DRM).
|
515 |
+
|
516 |
+
## 2.7.25 - 2015-03-26
|
517 |
+
|
518 |
+
* `Aws\ElasticTranscoder` - Added support for job timing.
|
519 |
+
* `Aws\Iam` - Added `NamedPolicy` to `GetAccountAuthorizationDetails`.
|
520 |
+
* `Aws\OpsWorks` - Added `BlockDeviceMapping` support.
|
521 |
+
|
522 |
+
## 2.7.24 - 2015-03-24
|
523 |
+
|
524 |
+
* `Aws\S3` - Added support for cross-region replication.
|
525 |
+
* `Aws\S3` - Added support for ["Requester Pays" buckets](http://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html).
|
526 |
+
|
527 |
+
## 2.7.23 - 2015-03-19
|
528 |
+
|
529 |
+
* `Aws\ElasticTranscoder` - API update to support AppliedColorSpaceConversion.
|
530 |
+
* `Aws\CloudSearchDomain` - Adding 504 status code to retry list.
|
531 |
+
|
532 |
+
## 2.7.22 - 2015-03-12
|
533 |
+
|
534 |
+
* `Aws\CloudFront` - Fixed #482, which affected pre-signing CloudFront URLs.
|
535 |
+
* `Aws\CloudTrail` - Added support for the `LookupEvents` operation.
|
536 |
+
* `Aws\CloudWatchLogs` - Added ordering parameters to the `DescribeLogStreams`
|
537 |
+
* `Aws\Ec2` - Added pagination parameters to the `DescribeSnapshots` operation.
|
538 |
+
operation.
|
539 |
+
|
540 |
+
## 2.7.21 - 2015-03-04
|
541 |
+
|
542 |
+
* `Aws\CognitoSync` - Added support for Amazon Cognito Streams.
|
543 |
+
|
544 |
+
## 2.7.20 - 2015-02-23
|
545 |
+
|
546 |
+
* `Aws\DataPipeline` - Added support for pipeline tagging via the `AddTags` and
|
547 |
+
`RemoveTags` operations.
|
548 |
+
* `Aws\Route53` - Added support for the `GetHostedZoneCount` and
|
549 |
+
`ListHostedZonesByName` operations.
|
550 |
+
|
551 |
+
## 2.7.19 - 2015-02-20
|
552 |
+
|
553 |
+
* `Aws\CloudFront` - Added support for origin paths in web distributions.
|
554 |
+
* `Aws\Ecs` - Added support for specifying volumes and mount points. Also
|
555 |
+
* `Aws\ElasticTranscoder` - Added support for cross-regional resource warnings.
|
556 |
+
* `Aws\Route53Domains` - Add iterators for `ListDomains` and `ListOperations`.
|
557 |
+
* `Aws\Ssm` - Added support for the **Amazon Simple Systems Management Service
|
558 |
+
(SSM)**.
|
559 |
+
* `Aws\Sts` - Added support for regional endpoints.
|
560 |
+
switched the client to use a JSON protocol.
|
561 |
+
* Changed our CHANGELOG format. ;-)
|
562 |
+
|
563 |
+
## 2.7.18 - 2015-02-12
|
564 |
+
|
565 |
+
* Added support for named and managed policies to the IAM client.
|
566 |
+
* Added support for tagging operations to the Route 53 Domains client.
|
567 |
+
* Added support for tagging operations to the ElastiCache client.
|
568 |
+
* Added support for the Scan API for secondary indexes to the DynamoDB client.
|
569 |
+
* Added forward compatibility for the `'credentials'`, `'endpoint'`, and
|
570 |
+
`'http'` configuration options.
|
571 |
+
* Made the `marshalValue()` and `unmarshalValue()` methods public in the
|
572 |
+
DynamoDB Marshaler.
|
573 |
+
|
574 |
+
## 2.7.17 - 2015-01-27
|
575 |
+
|
576 |
+
* Added support for `getShippingLabel` to the AWS Import/Export client.
|
577 |
+
* Added support for online indexing to the DynamoDB client.
|
578 |
+
* Updated the AWS Lambda client.
|
579 |
+
|
580 |
+
## 2.7.16 - 2015-01-20
|
581 |
+
|
582 |
+
* Added support for custom security groups to the Amazon EMR client.
|
583 |
+
* Added support for the latest APIs to the Amazon Cognito Identity client.
|
584 |
+
* Added support for ClassicLink to the Auto Scaling client.
|
585 |
+
* Added the ability to set a client's API version to "latest" for forwards
|
586 |
+
compatibility with v3.
|
587 |
+
|
588 |
+
## 2.7.15 - 2015-01-15
|
589 |
+
|
590 |
+
* Added support for [HLS Content Protection](https://aws.amazon.com/releasenotes/3388917394239147)
|
591 |
+
to the Elastic Transcoder client.
|
592 |
+
* Updated client factory logic to add the `SignatureListener`, even when
|
593 |
+
`NullCredentials` have been specified. This way, you can update a client's
|
594 |
+
credentials later if you want to begin signing requests.
|
595 |
+
|
596 |
+
## 2.7.14 - 2015-01-09
|
597 |
+
|
598 |
+
* Fixed a regression in the CloudSearch Domain client (#448).
|
599 |
+
|
600 |
+
## 2.7.13 - 2015-01-08
|
601 |
+
|
602 |
+
* Added the Amazon EC2 Container Service client.
|
603 |
+
* Added the Amazon CloudHSM client.
|
604 |
+
* Added support for dynamic fields to the Amazon CloudSearch client.
|
605 |
+
* Added support for the ClassicLink feature to the Amazon EC2 client.
|
606 |
+
* Updated the Amazon RDS client to use the latest 2014-10-31 API.
|
607 |
+
* Updated S3 signature so retries use a new Date header on each attempt.
|
608 |
+
|
609 |
+
## 2.7.12 - 2014-12-18
|
610 |
+
|
611 |
+
* Added support for task priorities to Amazon Simple Workflow Service.
|
612 |
+
|
613 |
+
## 2.7.11 - 2014-12-17
|
614 |
+
|
615 |
+
* Updated Amazon EMR to the latest API version.
|
616 |
+
* Added support for for the new ResetCache API operation to AWS Storage Gateway.
|
617 |
+
|
618 |
+
## 2.7.10 - 2014-12-12
|
619 |
+
|
620 |
+
* Added support for user data to Amazon Elastic Transcoder.
|
621 |
+
* Added support for data retrieval policies and audit logging to the Amazon
|
622 |
+
Glacier client.
|
623 |
+
* Corrected the AWS Security Token Service endpoint.
|
624 |
+
|
625 |
+
## 2.7.9 - 2014-12-08
|
626 |
+
|
627 |
+
* The Amazon Simple Queue Service client adds support for the PurgeQueue
|
628 |
+
operation.
|
629 |
+
* You can now use AWS OpsWorks with existing EC2 instances and on-premises
|
630 |
+
servers.
|
631 |
+
|
632 |
+
## 2.7.8 - 2014-12-04
|
633 |
+
|
634 |
+
* Added support for the `PutRecords` batch operation to `KinesisClient`.
|
635 |
+
* Added support for the `GetAccountAuthorizationDetails` operation to the
|
636 |
+
`IamClient`.
|
637 |
+
* Added support for the `UpdateHostedZoneComment` operation to `Route53Client`.
|
638 |
+
* Added iterators for `ListEventSources` and `ListFunctions` operations the
|
639 |
+
`LambdaClient`.
|
640 |
+
|
641 |
+
## 2.7.7 - 2014-11-25
|
642 |
+
|
643 |
+
* Added a DynamoDB `Marshaler` class, that allows you to marshal JSON documents
|
644 |
+
or native PHP arrays to the format that DynamoDB requires. You can also
|
645 |
+
unmarshal item data from operation results back into JSON documents or native
|
646 |
+
PHP arrays.
|
647 |
+
* Added support for media file encryption to Amazon Elastic Transcoder.
|
648 |
+
* Removing a few superfluous `x-amz-server-side-encryption-aws-kms-key-id` from
|
649 |
+
the Amazon S3 model.
|
650 |
+
* Added support for using AWS Data Pipeline templates to create pipelines and
|
651 |
+
bind values to parameters in the pipeline.
|
652 |
+
|
653 |
+
## 2.7.6 - 2014-11-20
|
654 |
+
|
655 |
+
* Added support for AWS KMS integration to the Amazon Redshift Client.
|
656 |
+
* Fixed cn-north-1 endpoint for AWS Identity and Access Management.
|
657 |
+
* Updated `S3Client::getBucketLocation` method to work cross-region regardless
|
658 |
+
of the region's signature requirements.
|
659 |
+
* Fixed an issue with the DynamoDbClient that allows it to work better with
|
660 |
+
with DynamoDB Local.
|
661 |
+
|
662 |
+
## 2.7.5 - 2014-11-13
|
663 |
+
|
664 |
+
* Added support for AWS Lambda.
|
665 |
+
* Added support for event notifications to the Amazon S3 client.
|
666 |
+
* Fixed an issue with S3 pre-signed URLs when using Signature V4.
|
667 |
+
|
668 |
+
## 2.7.4 - 2014-11-12
|
669 |
+
|
670 |
+
* Added support for the AWS Key Management Service (AWS KMS).
|
671 |
+
* Added support for AWS CodeDeploy.
|
672 |
+
* Added support for AWS Config.
|
673 |
+
* Added support for AWS KMS encryption to the Amazon S3 client.
|
674 |
+
* Added support for AWS KMS encryption to the Amazon EC2 client.
|
675 |
+
* Added support for Amazon CloudWatch Logs delivery to the AWS CloudTrail
|
676 |
+
client.
|
677 |
+
* Added the GetTemplateSummary operation to the AWS CloudFormation client.
|
678 |
+
* Fixed an issue with sending signature version 4 Amazon S3 requests that
|
679 |
+
contained a 0 length body.
|
680 |
+
|
681 |
+
## 2.7.3 - 2014-11-06
|
682 |
+
|
683 |
+
* Added support for private DNS for Amazon Virtual Private Clouds, health check
|
684 |
+
failure reasons, and reusable delegation sets to the Amazon Route 53 client.
|
685 |
+
* Updated the CloudFront model.
|
686 |
+
* Added support for configuring push synchronization to the Cognito Sync client.
|
687 |
+
* Updated docblocks in a few S3 and Glacier classes to improve IDE experience.
|
688 |
+
|
689 |
+
## 3.0.0-beta.1 - 2014-10-14
|
690 |
+
|
691 |
+
* New requirements on Guzzle 5 and PHP 5.5.
|
692 |
+
* Event system now uses Guzzle 5 events and no longer utilizes Symfony2.
|
693 |
+
* `version` and `region` are noww required parameter for each client
|
694 |
+
constructor. You can op-into using the latest version of a service by
|
695 |
+
setting `version` to `latest`.
|
696 |
+
* Removed `Aws\S3\ResumableDownload`.
|
697 |
+
* More information to follow.
|
698 |
+
|
699 |
+
## 2.7.2 - 2014-10-23
|
700 |
+
|
701 |
+
* Updated AWS Identity and Access Management (IAM) to the latest version.
|
702 |
+
* Updated Amazon Cognito Identity client to the latest version.
|
703 |
+
* Added auto-renew support to the Amazon Route 53 Domains client.
|
704 |
+
* Updated Amazon EC2 to the latest version.
|
705 |
+
|
706 |
+
## 2.7.1 - 2014-10-16
|
707 |
+
|
708 |
+
* Updated the Amazon RDS client to the 2014-09-01 API version.
|
709 |
+
* Added support for advanced Japanese language processing to the Amazon
|
710 |
+
CloudSearch client.
|
711 |
+
|
712 |
+
## 2.7.0 - 2014-10-08
|
713 |
+
|
714 |
+
* Added document model support to the Amazon DynamoDB client, including support
|
715 |
+
for the new data types (`L`, `M`, `BOOL`, and `NULL`), nested attributes, and
|
716 |
+
expressions.
|
717 |
+
* Deprecated the `Aws\DynamoDb\Model\Attribute`, `Aws\DynamoDb\Model\Item`,
|
718 |
+
and `Aws\DynamoDb\Iterator\ItemIterator` classes, and the
|
719 |
+
`Aws\DynamoDb\DynamoDbClient::formatValue` and
|
720 |
+
`Aws\DynamoDb\DynamoDbClient::formatAttribute` methods, since they do not
|
721 |
+
support the new types in the DynamoDB document model. These deprecated classes
|
722 |
+
and methods still work reliably with `S`, `N`, `B`, `SS`, `NS`, and `BS`
|
723 |
+
attributes.
|
724 |
+
* Updated the Amazon DynamoDB client to permanently disable client-side
|
725 |
+
parameter validation. This needed to be done in order to support the new
|
726 |
+
document model features.
|
727 |
+
* Updated the Amazon EC2 client to sign requests with Signature V4.
|
728 |
+
* Fixed an issue in the S3 service description to make the `VersionId`
|
729 |
+
work in `S3Client::restoreObject`.
|
730 |
+
|
731 |
+
## 2.6.16 - 2014-09-11
|
732 |
+
|
733 |
+
* Added support for tagging to the Amazon Kinesis client.
|
734 |
+
* Added support for setting environment variables to the AWS OpsWorks client.
|
735 |
+
* Fixed issue #334 to allow the `before_upload` callback to work in the
|
736 |
+
`S3Client::upload` method.
|
737 |
+
* Fixed an issue in the Signature V4 signer that was causing an issue with some
|
738 |
+
CloudSearch Domain operations.
|
739 |
+
|
740 |
+
## 2.6.15 - 2014-08-14
|
741 |
+
|
742 |
+
* Added support for signing requests to the Amazon CloudSearch Domain client.
|
743 |
+
* Added support for creating anonymous clients.
|
744 |
+
|
745 |
+
## 2.6.14 - 2014-08-11
|
746 |
+
|
747 |
+
* Added support for tagging to the Elastic Load Balancing client.
|
748 |
+
|
749 |
+
## 2.6.13 - 2014-07-31
|
750 |
+
|
751 |
+
* Added support for configurable idle timeouts to the Elastic Load Balancing
|
752 |
+
client.
|
753 |
+
* Added support for Lifecycle Hooks, Detach Instances, and Standby to the
|
754 |
+
AutoScaling client.
|
755 |
+
* Added support for creating Amazon ElastiCache for Memcached clusters with
|
756 |
+
nodes in multiple availability zones.
|
757 |
+
* Added minor fixes to the Amazon EC2 model for ImportVolume,
|
758 |
+
DescribeNetworkInterfaceAttribute, and DeleteVpcPeeringConnection
|
759 |
+
* Added support for getGeoLocation and listGeoLocations to the
|
760 |
+
Amazon Route 53 client.
|
761 |
+
* Added support for Amazon Route 53 Domains.
|
762 |
+
* Fixed an issue with deleting nested folders in the Amazon S3 stream wrapper.
|
763 |
+
* Fixed an issue with the Amazon S3 sync abstraction to ensure that S3->S3
|
764 |
+
communication works correctly.
|
765 |
+
* Added stricter validation to the Amazon SNS MessageValidator.
|
766 |
+
|
767 |
+
## 2.6.12 - 2014-07-16
|
768 |
+
|
769 |
+
* Added support for adding attachments to support case communications to the
|
770 |
+
AWS Support API client.
|
771 |
+
* Added support for credential reports and password rotation features to the
|
772 |
+
AWS IAM client.
|
773 |
+
* Added the `ap-northeast-1`, `ap-southeast-1`, and `ap-southeast-2` regions to
|
774 |
+
the Amazon Kinesis client.
|
775 |
+
* Added a `listFilter` stream context option that can be used when using
|
776 |
+
`opendir()` and the Amazon S3 stream wrapper. This option is used to filter
|
777 |
+
out specific objects from the files yielded from the stream wrapper.
|
778 |
+
* Fixed #322 so that the download sync builder ignores objects that have a
|
779 |
+
`GLACIER` storage class.
|
780 |
+
* Fixed an issue with the S3 SSE-C logic so that HTTPS is only required when
|
781 |
+
the SSE-C parameters are provided.
|
782 |
+
* Updated the Travis configuration to include running HHVM tests.
|
783 |
+
|
784 |
+
## 2.6.11 - 2014-07-09
|
785 |
+
|
786 |
+
* Added support for **Amazon Cognito Identity**.
|
787 |
+
* Added support for **Amazon Cognito Sync**.
|
788 |
+
* Added support for **Amazon CloudWatch Logs**.
|
789 |
+
* Added support for editing existing health checks and associating health checks
|
790 |
+
with tags to the Amazon Route 53 client.
|
791 |
+
* Added the ModifySubnetAttribute operation to the Amazon EC2 client.
|
792 |
+
|
793 |
+
## 2.6.10 - 2014-07-02
|
794 |
+
|
795 |
+
* Added the `ap-northeast-1`, `ap-southeast-1`, and `sa-east-1` regions to the
|
796 |
+
Amazon CloudTrail client.
|
797 |
+
* Added the `eu-west-1` and `us-west-2` regions to the Amazon Kinesis client.
|
798 |
+
* Fixed an issue with the SignatureV4 implementation when used with Amazon S3.
|
799 |
+
* Fixed an issue with a test that was causing failures when run on EC2 instances
|
800 |
+
that have associated Instance Metadata credentials.
|
801 |
+
|
802 |
+
## 2.6.9 - 2014-06-26
|
803 |
+
|
804 |
+
* Added support for the CloudSearchDomain client, which allows you to search and
|
805 |
+
upload documents to your CloudSearch domains.
|
806 |
+
* Added support for delivery notifications to the Amazon SES client.
|
807 |
+
* Updated the CloudFront client to support the 2014-05-31 API.
|
808 |
+
* Merged PR #316 as a better solution for issue #309.
|
809 |
+
|
810 |
+
## 2.6.8 - 2014-06-20
|
811 |
+
|
812 |
+
* Added support for closed captions to the Elastic Transcoder client.
|
813 |
+
* Added support for IAM roles to the Elastic MapReduce client.
|
814 |
+
* Updated the S3 PostObject to ease customization.
|
815 |
+
* Fixed an issue in some EC2 waiters by merging PR #306.
|
816 |
+
* Fixed an issue with the DynamoDB `WriteRequestBatch` by merging PR #310.
|
817 |
+
* Fixed issue #309, where the `url_stat()` logic in the S3 Stream Wrapper was
|
818 |
+
affected by a change in PHP 5.5.13.
|
819 |
+
|
820 |
+
## 2.6.7 - 2014-06-12
|
821 |
+
|
822 |
+
* Added support for Amazon S3 server-side encryption using customer-provided
|
823 |
+
encryption keys.
|
824 |
+
* Updated Amazon SNS to support message attributes.
|
825 |
+
* Updated the Amazon Redshift model to support new cluster parameters.
|
826 |
+
* Updated PHPUnit dev dependency to 4.* to work around a PHP serializing bug.
|
827 |
+
|
828 |
+
## 2.6.6 - 2014-05-29
|
829 |
+
|
830 |
+
* Added support for the [Desired Partition Count scaling
|
831 |
+
option](http://aws.amazon.com/releasenotes/2440176739861815) to the
|
832 |
+
CloudSearch client. Hebrew is also now a supported language.
|
833 |
+
* Updated the STS service description to the latest version.
|
834 |
+
* [Docs] Updated some of the documentation about credential profiles.
|
835 |
+
* Fixed an issue with the regular expression in the `S3Client::isValidBucketName`
|
836 |
+
method. See #298.
|
837 |
+
|
838 |
+
## 2.6.5 - 2014-05-22
|
839 |
+
|
840 |
+
* Added cross-region support for the Amazon EC2 CopySnapshot operation.
|
841 |
+
* Added AWS Relational Database (RDS) support to the AWS OpsWorks client.
|
842 |
+
* Added support for tagging environments to the AWS Elastic Beanstalk client.
|
843 |
+
* Refactored the signature version 4 implementation to be able to pre-sign
|
844 |
+
most operations.
|
845 |
+
|
846 |
+
## 2.6.4 - 2014-05-20
|
847 |
+
|
848 |
+
* Added support for lifecycles on versioning enabled buckets to the Amazon S3
|
849 |
+
client.
|
850 |
+
* Fixed an Amazon S3 sync issue which resulted in unnecessary transfers when no
|
851 |
+
`$keyPrefix` argument was utilized.
|
852 |
+
* Corrected the `CopySourceIfMatch` and `CopySourceIfNoneMatch` parameter for
|
853 |
+
Amazon S3 to not use a timestamp shape.
|
854 |
+
* Corrected the sending of Amazon S3 PutBucketVersioning requests that utilize
|
855 |
+
the `MFADelete` parameter.
|
856 |
+
|
857 |
+
## 2.6.3 - 2014-05-14
|
858 |
+
|
859 |
+
* Added the ability to modify Amazon SNS topic settings to the UpdateStack
|
860 |
+
operation of the AWS CloudFormation client.
|
861 |
+
* Added support for the us-west-1, ap-southeast-2, and eu-west-1 regions to the
|
862 |
+
AWS CloudTrail client.
|
863 |
+
* Removed no longer utilized AWS CloudTrail shapes from the model.
|
864 |
+
|
865 |
+
## 2.6.2 - 2014-05-06
|
866 |
+
|
867 |
+
* Added support for Amazon SQS message attributes.
|
868 |
+
* Fixed Amazon S3 multi-part uploads so that manually set ContentType values are not overwritten.
|
869 |
+
* No longer recalculating file sizes when an Amazon S3 socket timeout occurs because this was causing issues with
|
870 |
+
multi-part uploads and it is very unlikely ever the culprit of a socket timeout.
|
871 |
+
* Added better environment variable detection.
|
872 |
+
|
873 |
+
## 2.6.1 - 2014-04-25
|
874 |
+
|
875 |
+
* Added support for the `~/.aws/credentials` INI file and credential profiles (via the `profile` option) as a safer
|
876 |
+
alternative to using explicit credentials with the `key` and `secret` options.
|
877 |
+
* Added support for query filters and improved conditional expressions to the Amazon DynamoDB client.
|
878 |
+
* Added support for the `ChefConfiguration` parameter to a few operations on the AWS OpsWorks Client.
|
879 |
+
* Added support for Redis cache cluster snapshots to the Amazon ElastiCache client.
|
880 |
+
* Added support for the `PlacementTenancy` parameter to the `CreateLaunchConfiguration` operation of the Auto Scaling
|
881 |
+
client.
|
882 |
+
* Added support for the new R3 instance types to the Amazon EC2 client.
|
883 |
+
* Added the `SpotInstanceRequestFulfilled` waiter to the Amazon EC2 client (see #241).
|
884 |
+
* Improved the S3 Stream Wrapper by adding support for deleting pseudo directories (#264), updating error handling
|
885 |
+
(#276), and fixing `is_link()` for non-existent keys (#268).
|
886 |
+
* Fixed #252 and updated the DynamoDB `WriteRequestBatch` abstraction to handle batches that were completely rejected
|
887 |
+
due to exceeding provisioned throughput.
|
888 |
+
* Updated the SDK to support Guzzle 3.9.x
|
889 |
+
|
890 |
+
## 2.6.0 - 2014-03-25
|
891 |
+
|
892 |
+
* [BC] Updated the Amazon CloudSearch client to use the new 2013-01-01 API version (see [their release
|
893 |
+
notes](http://aws.amazon.com/releasenotes/6125075708216342)). This API version of CloudSearch is significantly
|
894 |
+
different than the previous one, and is not backwards compatible. See the
|
895 |
+
[Upgrading Guide](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md) for more details.
|
896 |
+
* Added support for the VPC peering features to the Amazon EC2 client.
|
897 |
+
* Updated the Amazon EC2 client to use the new 2014-02-01 API version.
|
898 |
+
* Added support for [resize progress data and the Cluster Revision Number
|
899 |
+
parameter](http://aws.amazon.com/releasenotes/0485739709714318) to the Amazon Redshift client.
|
900 |
+
* Added the `ap-northeast-1`, `ap-southeast-2`, and `sa-east-1` regions to the Amazon CloudSearch client.
|
901 |
+
|
902 |
+
## 2.5.4 - 2014-03-20
|
903 |
+
|
904 |
+
* Added support for [access logs](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/access-log-collection.html)
|
905 |
+
to the Elastic Load Balancing client.
|
906 |
+
* Updated the Elastic Load Balancing client to the latest API version.
|
907 |
+
* Added support for the `AWS_SECRET_ACCESS_KEY` environment variables.
|
908 |
+
* Updated the Amazon CloudFront client to use the 2014-01-31 API version. See [their release
|
909 |
+
notes](http://aws.amazon.com/releasenotes/1900016175520505).
|
910 |
+
* Updates the AWS OpsWorks client to the latest API version.
|
911 |
+
* Amazon S3 Stream Wrapper now works correctly with pseudo folder keys created by the AWS Management Console.
|
912 |
+
* Amazon S3 Stream Wrapper now implements `mkdir()` for nested folders similar to the AWS Management Console.
|
913 |
+
* Addressed an issue with Amazon S3 presigned-URLs where X-Amz-* headers were not being added to the query string.
|
914 |
+
* Addressed an issue with the Amazon S3 directory sync where paths that contained dot-segments were not properly.
|
915 |
+
resolved. Removing the dot segments consistently helps to ensure that files are uploaded to their intended.
|
916 |
+
destinations and that file key comparisons are accurately performed when determining which files to upload.
|
917 |
+
|
918 |
+
## 2.5.3 - 2014-02-27
|
919 |
+
|
920 |
+
* Added support for HTTP and HTTPS string-match health checks and HTTPS health checks to the Amazon Route 53 client
|
921 |
+
* Added support for the UPSERT action for the Amazon Route 53 ChangeResourceRecordSets operation
|
922 |
+
* Added support for SerialNumber and TokenCode to the AssumeRole operation of the IAM Security Token Service (STS).
|
923 |
+
* Added support for RequestInterval and FailureThreshold to the Amazon Route53 client.
|
924 |
+
* Added support for smooth streaming to the Amazon CloudFront client.
|
925 |
+
* Added the us-west-2, eu-west-1, ap-southeast-2, and ap-northeast-1 regions to the AWS Data Pipeline client.
|
926 |
+
* Added iterators to the Amazon Kinesis client
|
927 |
+
* Updated iterator configurations for all services to match our new iterator config spec (care was taken to continue
|
928 |
+
supporting manually-specified configurations in the old format to prevent BC)
|
929 |
+
* Updated the Amazon EC2 model to include the latest updates and documentation. Removed deprecated license-related
|
930 |
+
operations (this is not considered a BC since we have confirmed that these operations are not used by customers)
|
931 |
+
* Updated the Amazon Route 53 client to use the 2013-04-01 API version
|
932 |
+
* Fixed several iterator configurations for various services to better support existing operations and parameters
|
933 |
+
* Fixed an issue with the Amazon S3 client where an exception was thrown when trying to add a default Content-MD5
|
934 |
+
header to a request that uses a non-rewindable stream.
|
935 |
+
* Updated the Amazon S3 PostObject class to work with CNAME style buckets.
|
936 |
+
|
937 |
+
## 2.5.2 - 2014-01-29
|
938 |
+
|
939 |
+
* Added support for dead letter queues to Amazon SQS
|
940 |
+
* Added support for the new M3 medium and large instance types to the Amazon EC2 client
|
941 |
+
* Added support for using the `eu-west-1` and `us-west-2` regions to the Amazon SES client
|
942 |
+
* Adding content-type guessing to the Amazon S3 stream wrapper (see #210)
|
943 |
+
* Added an event to the Amazon S3 multipart upload helpers to allow granular customization of multipart uploads during
|
944 |
+
a sync (see #209)
|
945 |
+
* Updated Signature V4 logic for Amazon S3 to throw an exception if you attempt to create a presigned URL that expires
|
946 |
+
later than a week (see #215)
|
947 |
+
* Fixed the `downloadBucket` and `uploadDirectory` methods to support relative paths and better support
|
948 |
+
Windows (see #207)
|
949 |
+
* Fixed issue #195 in the Amazon S3 multipart upload helpers to properly support additional parameters (see #211)
|
950 |
+
* [Docs] Expanded examples in the [API reference](http://docs.aws.amazon.com/aws-sdk-php/latest/index.html) by default
|
951 |
+
so they don't get overlooked
|
952 |
+
* [Docs] Moved the API reference links in the [service-specific user guide
|
953 |
+
pages](http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html#service-specific-guides) to the bottom so
|
954 |
+
the page's content takes priority
|
955 |
+
|
956 |
+
## 2.5.1 - 2014-01-09
|
957 |
+
|
958 |
+
* Added support for attaching existing Amazon EC2 instances to an Auto Scaling group to the Auto Scaling client
|
959 |
+
* Added support for creating launch configurations from existing Amazon EC2 instances to the Auto Scaling client
|
960 |
+
* Added support for describing Auto Scaling account limits to the Auto Scaling client
|
961 |
+
* Added better support for block device mappings to the Amazon AutoScaling client when creating launch configurations
|
962 |
+
* Added support for [ranged inventory retrieval](http://docs.aws.amazon.com/amazonglacier/latest/dev/api-initiate-job-post.html#api-initiate-job-post-vault-inventory-list-filtering)
|
963 |
+
to the Amazon Glacier client
|
964 |
+
* [Docs] Updated and added a lot of content in the [User Guide](http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html)
|
965 |
+
* Fixed a bug where the `KinesisClient::getShardIterator()` method was not working properly
|
966 |
+
* Fixed an issue with Amazon SimpleDB where the 'Value' attribute was marked as required on DeleteAttribute and BatchDeleteAttributes
|
967 |
+
* Fixed an issue with the Amazon S3 stream wrapper where empty place holder keys were being marked as files instead of directories
|
968 |
+
* Added the ability to specify a custom signature implementation using a string identifier (e.g., 'v4', 'v2', etc)
|
969 |
+
|
970 |
+
## 2.5.0 - 2013-12-20
|
971 |
+
|
972 |
+
* Added support for the new **China (Beijing) Region** to various services. This region is currently in limited preview.
|
973 |
+
Please see <http://www.amazonaws.cn> for more information
|
974 |
+
* Added support for different audio compression schemes to the Elastic Transcoder client (includes AAC-LC, HE-AAC,
|
975 |
+
and HE-AACv2)
|
976 |
+
* Added support for preset and pipeline pagination to the Elastic Transcoder client. You can now view more than the
|
977 |
+
first 50 presets and pipelines with their corresponding list operations
|
978 |
+
* Added support for [geo restriction](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithDownloadDistributions.html#georestrictions)
|
979 |
+
to the Amazon CloudFront client
|
980 |
+
* [SDK] Added Signature V4 support to the Amazon S3 and Amazon EC2 clients for the new China (Beijing) Region
|
981 |
+
* [BC] Updated the AWS CloudTrail client to use their latest API changes due to early user feedback. Some parameters in
|
982 |
+
the `CreateTrail`, `UpdateTrail`, and `GetTrailStatus` have been deprecated and will be completely unavailable as
|
983 |
+
early as February 15th, 2014. Please see [this announcement on the CloudTrail
|
984 |
+
forum](https://forums.aws.amazon.com/ann.jspa?annID=2286). We are calling this out as a breaking change now to
|
985 |
+
encourage you to update your code at this time.
|
986 |
+
* Updated the Amazon CloudFront client to use the 2013-11-11 API version
|
987 |
+
* [BC] Updated the Amazon EC2 client to use the latest API. This resulted in a small change to a parameter in the
|
988 |
+
`RequestSpotInstances` operation. See [this commit](https://github.com/aws/aws-sdk-php/commit/36ae0f68d2a6dcc3bc28222f60ecb318449c4092#diff-bad2f6eac12565bb684f2015364c22bd)
|
989 |
+
for the change
|
990 |
+
* [BC] Removed Signature V3 support (no longer needed) and refactored parts of the signature-related classes
|
991 |
+
|
992 |
+
## 2.4.12 - 2013-12-12
|
993 |
+
|
994 |
+
* Added support for **Amazon Kinesis**
|
995 |
+
* Added the CloudTrail `LogRecordIterator`, `LogFileIterator`, and `LogFileReader` classes for reading log files
|
996 |
+
generated by the CloudTrail service
|
997 |
+
* Added support for resource-level permissions to the AWS OpsWorks client
|
998 |
+
* Added support for worker environment tiers to the AWS Elastic Beanstalk client
|
999 |
+
* Added support for the new I2 instance types to the Amazon EC2 client
|
1000 |
+
* Added support for resource tagging to the Amazon Elastic MapReduce client
|
1001 |
+
* Added support for specifying a key encoding type to the Amazon S3 client
|
1002 |
+
* Added support for global secondary indexes to the Amazon DynamoDB client
|
1003 |
+
* Updated the Amazon ElastiCache client to use Signature Version 4
|
1004 |
+
* Fixed an issue in the waiter factory that caused an error when getting the factory for service clients without any
|
1005 |
+
existing waiters
|
1006 |
+
* Fixed issue #187, where the DynamoDB Session Handler would fail to save the session if all the data is removed
|
1007 |
+
|
1008 |
+
## 2.4.11 - 2013-11-26
|
1009 |
+
|
1010 |
+
* Added support for copying DB snapshots from one AWS region to another to the Amazon RDS client
|
1011 |
+
* Added support for pagination of the `DescribeInstances` and `DescribeTags` operations to the Amazon EC2 client
|
1012 |
+
* Added support for the new C3 instance types and the g2.2xlarge instance type to the Amazon EC2 client
|
1013 |
+
* Added support for enabling *Single Root I/O Virtualization* (SR-IOV) support for the new C3 instance types to the
|
1014 |
+
Amazon EC2 client
|
1015 |
+
* Updated the Amazon EC2 client to use the 2013-10-15 API version
|
1016 |
+
* Updated the Amazon RDS client to use the 2013-09-09 API version
|
1017 |
+
* Updated the Amazon CloudWatch client to use Signature Version 4
|
1018 |
+
|
1019 |
+
## 2.4.10 - 2013-11-14
|
1020 |
+
|
1021 |
+
* Added support for **AWS CloudTrail**
|
1022 |
+
* Added support for identity federation using SAML 2.0 to the AWS STS client
|
1023 |
+
* Added support for configuring SAML-compliant identity providers to the AWS IAM client
|
1024 |
+
* Added support for event notifications to the Amazon Redshift client
|
1025 |
+
* Added support for HSM storage for encryption keys to the Amazon Redshift client
|
1026 |
+
* Added support for encryption key rotation to the Amazon Redshift client
|
1027 |
+
* Added support for database audit logging to the Amazon Redshift client
|
1028 |
+
|
1029 |
+
## 2.4.9 - 2013-11-08
|
1030 |
+
|
1031 |
+
* Added support for [cross-zone load balancing](http://aws.amazon.com/about-aws/whats-new/2013/11/06/elastic-load-balancing-adds-cross-zone-load-balancing/)
|
1032 |
+
to the Elastic Load Balancing client.
|
1033 |
+
* Added support for a [new gateway configuration](http://aws.amazon.com/about-aws/whats-new/2013/11/05/aws-storage-gateway-announces-gateway-virtual-tape-library/),
|
1034 |
+
Gateway-Virtual Tape Library, to the AWS Storage Gateway client.
|
1035 |
+
* Added support for stack policies to the the AWS CloudFormation client.
|
1036 |
+
* Fixed issue #176 where attempting to upload a direct to Amazon S3 using the `UploadBuilder` failed when using a custom
|
1037 |
+
iterator that needs to be rewound.
|
1038 |
+
|
1039 |
+
## 2.4.8 - 2013-10-31
|
1040 |
+
|
1041 |
+
* Updated the AWS Direct Connect client
|
1042 |
+
* Updated the Amazon Elastic MapReduce client to add support for new EMR APIs, termination of specific cluster
|
1043 |
+
instances, and unlimited EMR steps.
|
1044 |
+
|
1045 |
+
## 2.4.7 - 2013-10-17
|
1046 |
+
|
1047 |
+
* Added support for audio transcoding features to the Amazon Elastic Transcoder client
|
1048 |
+
* Added support for modifying Reserved Instances in a region to the Amazon EC2 client
|
1049 |
+
* Added support for new resource management features to the AWS OpsWorks client
|
1050 |
+
* Added support for additional HTTP methods to the Amazon CloudFront client
|
1051 |
+
* Added support for custom error page configuration to the Amazon CloudFront client
|
1052 |
+
* Added support for the public IP address association of instances in Auto Scaling group via the Auto Scaling client
|
1053 |
+
* Added support for tags and filters to various operations in the Amazon RDS client
|
1054 |
+
* Added the ability to easily specify event listeners on waiters
|
1055 |
+
* Added support for using the `ap-southeast-2` region to the Amazon Glacier client
|
1056 |
+
* Added support for using the `ap-southeast-1` and `ap-southeast-2` regions to the Amazon Redshift client
|
1057 |
+
* Updated the Amazon EC2 client to use the 2013-09-11 API version
|
1058 |
+
* Updated the Amazon CloudFront client to use the 2013-09-27 API version
|
1059 |
+
* Updated the AWS OpsWorks client to use the 2013-07-15 API version
|
1060 |
+
* Updated the Amazon CloudSearch client to use Signature Version 4
|
1061 |
+
* Fixed an issue with the Amazon S3 Client so that the top-level XML element of the `CompleteMultipartUpload` operation
|
1062 |
+
is correctly sent as `CompleteMultipartUpload`
|
1063 |
+
* Fixed an issue with the Amazon S3 Client so that you can now disable bucket logging using with the `PutBucketLogging`
|
1064 |
+
operation
|
1065 |
+
* Fixed an issue with the Amazon CloudFront so that query string parameters in pre-signed URLs are correctly URL-encoded
|
1066 |
+
* Fixed an issue with the Signature Version 4 implementation where headers with multiple values were sometimes sorted
|
1067 |
+
and signed incorrectly
|
1068 |
+
|
1069 |
+
## 2.4.6 - 2013-09-12
|
1070 |
+
|
1071 |
+
* Added support for modifying EC2 Reserved Instances to the Amazon EC2 client
|
1072 |
+
* Added support for VPC features to the AWS OpsWorks client
|
1073 |
+
* Updated the DynamoDB Session Handler to implement the SessionHandlerInterface of PHP 5.4 when available
|
1074 |
+
* Updated the SNS Message Validator to throw an exception, instead of an error, when the raw post data is invalid
|
1075 |
+
* Fixed an issue in the S3 signature which ensures that parameters are sorted correctly for signing
|
1076 |
+
* Fixed an issue in the S3 client where the Sydney region was not allowed as a `LocationConstraint` for the
|
1077 |
+
`PutObject` operation
|
1078 |
+
|
1079 |
+
## 2.4.5 - 2013-09-04
|
1080 |
+
|
1081 |
+
* Added support for replication groups to the Amazon ElastiCache client
|
1082 |
+
* Added support for using the `us-gov-west-1` region to the AWS CloudFormation client
|
1083 |
+
|
1084 |
+
## 2.4.4 - 2013-08-29
|
1085 |
+
|
1086 |
+
* Added support for assigning a public IP address to an instance at launch to the Amazon EC2 client
|
1087 |
+
* Updated the Amazon EC2 client to use the 2013-07-15 API version
|
1088 |
+
* Updated the Amazon SWF client to sign requests with Signature V4
|
1089 |
+
* Updated the Instance Metadata client to allow for higher and more customizable connection timeouts
|
1090 |
+
* Fixed an issue with the SDK where XML map structures were not being serialized correctly in some cases
|
1091 |
+
* Fixed issue #136 where a few of the new Amazon SNS mobile push operations were not working properly
|
1092 |
+
* Fixed an issue where the AWS STS `AssumeRoleWithWebIdentity` operation was requiring credentials and a signature
|
1093 |
+
unnecessarily
|
1094 |
+
* Fixed and issue with the `S3Client::uploadDirectory` method so that true key prefixes can be used
|
1095 |
+
* [Docs] Updated the API docs to include sample code for each operation that indicates the parameter structure
|
1096 |
+
* [Docs] Updated the API docs to include more information in the descriptions of operations and parameters
|
1097 |
+
* [Docs] Added a page about Iterators to the user guide
|
1098 |
+
|
1099 |
+
## 2.4.3 - 2013-08-12
|
1100 |
+
|
1101 |
+
* Added support for mobile push notifications to the Amazon SNS client
|
1102 |
+
* Added support for progress reporting on snapshot restore operations to the the Amazon Redshift client
|
1103 |
+
* Updated the Amazon Elastic MapReduce client to use JSON serialization
|
1104 |
+
* Updated the Amazon Elastic MapReduce client to sign requests with Signature V4
|
1105 |
+
* Updated the SDK to throw `Aws\Common\Exception\TransferException` exceptions when a network error occurs instead of a
|
1106 |
+
`Guzzle\Http\Exception\CurlException`. The TransferException class, however, extends from
|
1107 |
+
`Guzzle\Http\Exception\CurlException`. You can continue to catch the Guzzle `CurlException` or catch
|
1108 |
+
`Aws\Common\Exception\AwsExceptionInterface` to catch any exception that can be thrown by an AWS client
|
1109 |
+
* Fixed an issue with the Amazon S3 stream wrapper where trailing slashes were being added when listing directories
|
1110 |
+
|
1111 |
+
## 2.4.2 - 2013-07-25
|
1112 |
+
|
1113 |
+
* Added support for cross-account snapshot access control to the Amazon Redshift client
|
1114 |
+
* Added support for decoding authorization messages to the AWS STS client
|
1115 |
+
* Added support for checking for required permissions via the `DryRun` parameter to the Amazon EC2 client
|
1116 |
+
* Added support for custom Amazon Machine Images (AMIs) and Chef 11 to the AWS OpsWorks client
|
1117 |
+
* Added an SDK compatibility test to allow users to quickly determine if their system meets the requirements of the SDK
|
1118 |
+
* Updated the Amazon EC2 client to use the 2013-06-15 API version
|
1119 |
+
* Fixed an unmarshalling error with the Amazon EC2 `CreateKeyPair` operation
|
1120 |
+
* Fixed an unmarshalling error with the Amazon S3 `ListMultipartUploads` operation
|
1121 |
+
* Fixed an issue with the Amazon S3 stream wrapper "x" fopen mode
|
1122 |
+
* Fixed an issue with `Aws\S3\S3Client::downloadBucket` by removing leading slashes from the passed `$keyPrefix` argument
|
1123 |
+
|
1124 |
+
## 2.4.1 - 2013-06-08
|
1125 |
+
|
1126 |
+
* Added support for setting watermarks and max framerates to the Amazon Elastic Transcoder client
|
1127 |
+
* Added the `Aws\DynamoDb\Iterator\ItemIterator` class to make it easier to get items from the results of DynamoDB
|
1128 |
+
operations in a simpler form
|
1129 |
+
* Added support for the `cr1.8xlarge` EC2 instance type. Use `Aws\Ec2\Enum\InstanceType::CR1_8XLARGE`
|
1130 |
+
* Added support for the suppression list SES mailbox simulator. Use `Aws\Ses\Enum\MailboxSimulator::SUPPRESSION_LIST`
|
1131 |
+
* [SDK] Fixed an issue with data formats throughout the SDK due to a regression. Dates are now sent over the wire with
|
1132 |
+
the correct format. This issue affected the Amazon EC2, Amazon ElastiCache, AWS Elastic Beanstalk, Amazon EMR, and
|
1133 |
+
Amazon RDS clients
|
1134 |
+
* Fixed an issue with the parameter serialization of the `ImportInstance` operation in the Amazon EC2 client
|
1135 |
+
* Fixed an issue with the Amazon S3 client where the `RoutingRules.Redirect.HostName` parameter of the
|
1136 |
+
`PutBucketWebsite` operation was erroneously marked as required
|
1137 |
+
* Fixed an issue with the Amazon S3 client where the `DeleteObject` operation was missing parameters
|
1138 |
+
* Fixed an issue with the Amazon S3 client where the `Status` parameter of the `PutBucketVersioning` operation did not
|
1139 |
+
properly support the "Suspended" value
|
1140 |
+
* Fixed an issue with the Amazon Glacier `UploadPartGenerator` class so that an exception is thrown if the provided body
|
1141 |
+
to upload is less than 1 byte
|
1142 |
+
* Added MD5 validation to Amazon SQS ReceiveMessage operations
|
1143 |
+
|
1144 |
+
## 2.4.0 - 2013-06-18
|
1145 |
+
|
1146 |
+
* [BC] Updated the Amazon CloudFront client to use the new 2013-05-12 API version which includes changes in how you
|
1147 |
+
configure distributions. If you are not ready to upgrade to the new API, you can configure the SDK to use the previous
|
1148 |
+
version of the API by setting the `version` option to `2012-05-05` when you instantiate the client (See
|
1149 |
+
[`UPGRADING.md`](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md))
|
1150 |
+
* Added abstractions for uploading a local directory to an Amazon S3 bucket (`$s3->uploadDirectory()`)
|
1151 |
+
* Added abstractions for downloading an Amazon S3 bucket to local directory (`$s3->downloadBucket()`)
|
1152 |
+
* Added an easy to way to delete objects from an Amazon S3 bucket that match a regular expression or key prefix
|
1153 |
+
* Added an easy to way to upload an object to Amazon S3 that automatically uses a multipart upload if the size of the
|
1154 |
+
object exceeds a customizable threshold (`$s3->upload()`)
|
1155 |
+
* [SDK] Added facade classes for simple, static access to clients (e.g., `S3::putObject([...])`)
|
1156 |
+
* Added the `Aws\S3\S3Client::getObjectUrl` convenience method for getting the URL of an Amazon S3 object. This works
|
1157 |
+
for both public and pre-signed URLs
|
1158 |
+
* Added support for using the `ap-northeast-1` region to the Amazon Redshift client
|
1159 |
+
* Added support for configuring custom SSL certificates to the Amazon CloudFront client via the `ViewerCertificate`
|
1160 |
+
parameter
|
1161 |
+
* Added support for read replica status to the Amazon RDS client
|
1162 |
+
* Added "magic" access to iterators to make using iterators more convenient (e.g., `$s3->getListBucketsIterator()`)
|
1163 |
+
* Added the `waitUntilDBInstanceAvailable` and `waitUntilDBInstanceDeleted` waiters to the Amazon RDS client
|
1164 |
+
* Added the `createCredentials` method to the AWS STS client to make it easier to create a credentials object from the
|
1165 |
+
results of an STS operation
|
1166 |
+
* Updated the Amazon RDS client to use the 2013-05-15 API version
|
1167 |
+
* Updated request retrying logic to automatically refresh expired credentials and retry with new ones
|
1168 |
+
* Updated the Amazon CloudFront client to sign requests with Signature V4
|
1169 |
+
* Updated the Amazon SNS client to sign requests with Signature V4, which enables larger payloads
|
1170 |
+
* Updated the S3 Stream Wrapper so that you can use stream resources in any S3 operation without having to manually
|
1171 |
+
specify the `ContentLength` option
|
1172 |
+
* Fixed issue #94 so that the `Aws\S3\BucketStyleListener` is invoked on `command.after_prepare` and presigned URLs
|
1173 |
+
are generated correctly from S3 commands
|
1174 |
+
* Fixed an issue so that creating presigned URLs using the Amazon S3 client now works with temporary credentials
|
1175 |
+
* Fixed an issue so that the `CORSRules.AllowedHeaders` parameter is now available when configuring CORS for Amazon S3
|
1176 |
+
* Set the Guzzle dependency to ~3.7.0
|
1177 |
+
|
1178 |
+
## 2.3.4 - 2013-05-30
|
1179 |
+
|
1180 |
+
* Set the Guzzle dependency to ~3.6.0
|
1181 |
+
|
1182 |
+
## 2.3.3 - 2013-05-28
|
1183 |
+
|
1184 |
+
* Added support for web identity federation in the AWS Security Token Service (STS) API
|
1185 |
+
* Fixed an issue with creating pre-signed Amazon CloudFront RTMP URLs
|
1186 |
+
* Fixed issue #85 to correct the parameter serialization of NetworkInterfaces within the Amazon EC2 RequestSpotInstances
|
1187 |
+
operation
|
1188 |
+
|
1189 |
+
## 2.3.2 - 2013-05-15
|
1190 |
+
|
1191 |
+
* Added support for doing parallel scans to the Amazon DynamoDB client
|
1192 |
+
* [OpsWorks] Added support for using Elastic Load Balancer to the AWS OpsWorks client
|
1193 |
+
* Added support for using EBS-backed instances to the AWS OpsWorks client along with some other minor updates
|
1194 |
+
* Added support for finer-grained error messages to the AWS Data Pipeline client and updated the service description
|
1195 |
+
* Added the ability to set the `key_pair_id` and `private_key` options at the time of signing a CloudFront URL instead
|
1196 |
+
of when instantiating the client
|
1197 |
+
* Added a new [Zip Download](http://pear.amazonwebservices.com/get/aws.zip) for installing the SDK
|
1198 |
+
* Fixed the API version for the AWS Support client to be `2013-04-15`
|
1199 |
+
* Fixed issue #78 by implementing `Aws\S3\StreamWrapper::stream_cast()` for the S3 stream wrapper
|
1200 |
+
* Fixed issue #79 by updating the S3 `ClearBucket` object to work with the `ListObjects` operation
|
1201 |
+
* Fixed issue #80 where the `ETag` was incorrectly labeled as a header value instead of being in the XML body for
|
1202 |
+
the S3 `CompleteMultipartUpload` operation response
|
1203 |
+
* Fixed an issue where the `setCredentials()` method did not properly update the `SignatureListener`
|
1204 |
+
* Updated the required version of Guzzle to `">=3.4.3,<4"` to support Guzzle 3.5 which provides the SDK with improved
|
1205 |
+
memory management
|
1206 |
+
|
1207 |
+
## 2.3.1 - 2013-04-30
|
1208 |
+
|
1209 |
+
* Added support for **AWS Support**
|
1210 |
+
* Added support for using the `eu-west-1` region to the Amazon Redshift client
|
1211 |
+
* Fixed an issue with the Amazon RDS client where the `DownloadDBLogFilePortion` operation was not being serialized
|
1212 |
+
properly
|
1213 |
+
* Fixed an issue with the Amazon S3 client where the `PutObjectCopy` alias was interfering with the `CopyObject`
|
1214 |
+
operation
|
1215 |
+
* Added the ability to manually set a Content-Length header when using the `PutObject` and `UploadPart` operations of
|
1216 |
+
the Amazon S3 client
|
1217 |
+
* Fixed an issue where the Amazon S3 class was not throwing an exception for a non-followable 301 redirect response
|
1218 |
+
* Fixed an issue where `fflush()` was called during the shutdown process of the stream handler for read-only streams
|
1219 |
+
|
1220 |
+
## 2.3.0 - 2013-04-18
|
1221 |
+
|
1222 |
+
* Added support for Local Secondary Indexes to the Amazon DynamoDB client
|
1223 |
+
* [BC] Updated the Amazon DynamoDB client to use the new 2012-08-10 API version which includes changes in how you
|
1224 |
+
specify keys. If you are not ready to upgrade to the new API, you can configure the SDK to use the previous version of
|
1225 |
+
the API by setting the `version` option to `2011-12-05` when you instantiate the client (See
|
1226 |
+
[`UPGRADING.md`](https://github.com/aws/aws-sdk-php/blob/master/UPGRADING.md)).
|
1227 |
+
* Added an Amazon S3 stream wrapper that allows PHP native file functions to be used to interact with S3 buckets and
|
1228 |
+
objects
|
1229 |
+
* Added support for automatically retrying *throttled* requests with exponential backoff to all service clients
|
1230 |
+
* Added a new config option (`version`) to client objects to specify the API version to use if multiple are supported
|
1231 |
+
* Added a new config option (`gc_operation_delay`) to the DynamoDB Session Handler to specify a delay between requests
|
1232 |
+
to the service during garbage collection in order to help regulate the consumption of throughput
|
1233 |
+
* Added support for using the `us-west-2` region to the Amazon Redshift client
|
1234 |
+
* [Docs] Added a way to use marked integration test code as example code in the user guide and API docs
|
1235 |
+
* Updated the Amazon RDS client to sign requests with Signature V4
|
1236 |
+
* Updated the Amazon S3 client to automatically add the `Content-Type` to `PutObject` and other upload operations
|
1237 |
+
* Fixed an issue where service clients with a global endpoint could have their region for signing set incorrectly if a
|
1238 |
+
region other than `us-east-1` was specified.
|
1239 |
+
* Fixed an issue where reused command objects appended duplicate content to the user agent string
|
1240 |
+
* [SDK] Fixed an issue in a few operations (including `SQS::receiveMessage`) where the `curl.options` could not be
|
1241 |
+
modified
|
1242 |
+
* [Docs] Added key information to the DynamoDB service description to provide more accurate API docs for some operations
|
1243 |
+
* [Docs] Added a page about Waiters to the user guide
|
1244 |
+
* [Docs] Added a page about the DynamoDB Session Handler to the user guide
|
1245 |
+
* [Docs] Added a page about response Models to the user guide
|
1246 |
+
* Bumped the required version of Guzzle to ~3.4.1
|
1247 |
+
|
1248 |
+
## 2.2.1 - 2013-03-18
|
1249 |
+
|
1250 |
+
* Added support for viewing and downloading DB log files to the Amazon RDS client
|
1251 |
+
* Added the ability to validate incoming Amazon SNS messages. See the `Aws\Sns\MessageValidator` namespace
|
1252 |
+
* Added the ability to easily change the credentials that a client is configured to use via `$client->setCredentials()`
|
1253 |
+
* Added the `client.region_changed` and `client.credentials_changed` events on the client that are triggered when the
|
1254 |
+
`setRegion()` and `setCredentials()` methods are called, respectively
|
1255 |
+
* Added support for using the `ap-southeast-2` region with the Amazon ElastiCache client
|
1256 |
+
* Added support for using the `us-gov-west-1` region with the Amazon SWF client
|
1257 |
+
* Updated the Amazon RDS client to use the 2013-02-12 API version
|
1258 |
+
* Fixed an issue in the Amazon EC2 service description that was affecting the use of the new `ModifyVpcAttribute` and
|
1259 |
+
`DescribeVpcAttribute` operations
|
1260 |
+
* Added `ObjectURL` to the output of an Amazon S3 PutObject operation so that you can more easily retrieve the URL of an
|
1261 |
+
object after uploading
|
1262 |
+
* Added a `createPresignedUrl()` method to any command object created by the Amazon S3 client to more easily create
|
1263 |
+
presigned URLs
|
1264 |
+
|
1265 |
+
## 2.2.0 - 2013-03-11
|
1266 |
+
|
1267 |
+
* Added support for **Amazon Elastic MapReduce (Amazon EMR)**
|
1268 |
+
* Added support for **AWS Direct Connect**
|
1269 |
+
* Added support for **Amazon ElastiCache**
|
1270 |
+
* Added support for **AWS Storage Gateway**
|
1271 |
+
* Added support for **AWS Import/Export**
|
1272 |
+
* Added support for **AWS CloudFormation**
|
1273 |
+
* Added support for **Amazon CloudSearch**
|
1274 |
+
* Added support for [provisioned IOPS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.ProvisionedIOPS.html)
|
1275 |
+
to the the Amazon RDS client
|
1276 |
+
* Added support for promoting [read replicas](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html)
|
1277 |
+
to the Amazon RDS client
|
1278 |
+
* Added support for [event notification subscriptions](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html)
|
1279 |
+
to the Amazon RDS client
|
1280 |
+
* Added support for enabling\disabling DNS Hostnames and DNS Resolution in Amazon VPC to the Amazon EC2 client
|
1281 |
+
* Added support for enumerating account attributes to the Amazon EC2 client
|
1282 |
+
* Added support for copying AMIs across regions to the Amazon EC2 client
|
1283 |
+
* Added the ability to get a Waiter object from a client using the `getWaiter()` method
|
1284 |
+
* [SDK] Added the ability to load credentials from environmental variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_KEY`.
|
1285 |
+
This is compatible with AWS Elastic Beanstalk environment configurations
|
1286 |
+
* Added support for using the us-west-1, us-west-2, eu-west-1, and ap-southeast-1 regions with Amazon CloudSearch
|
1287 |
+
* Updated the Amazon RDS client to use the 2013-01-10 API version
|
1288 |
+
* Updated the Amazon EC2 client to use the 2013-02-01 API version
|
1289 |
+
* Added support for using SecurityToken with signature version 2 services
|
1290 |
+
* Added the client User-Agent header to exception messages for easier debugging
|
1291 |
+
* Added an easier way to disable operation parameter validation by setting `validation` to false when creating clients
|
1292 |
+
* Added the ability to disable the exponential backoff plugin
|
1293 |
+
* Added the ability to easily fetch the region name that a client is configured to use via `$client->getRegion()`
|
1294 |
+
* Added end-user guides available at http://docs.aws.amazon.com/aws-sdk-php/guide/latest/
|
1295 |
+
* Fixed issue #48 where signing Amazon S3 requests with null or empty metadata resulted in a signature error
|
1296 |
+
* Fixed issue #29 where Amazon S3 was intermittently closing a connection
|
1297 |
+
* Updated the Amazon S3 client to parse the AcceptRanges header for HeadObject and GetObject output
|
1298 |
+
* Updated the Amazon Glacier client to allow the `saveAs` parameter to be specified as an alias for `command.response_body`
|
1299 |
+
* Various performance improvements throughout the SDK
|
1300 |
+
* Removed endpoint providers and now placing service region information directly in service descriptions
|
1301 |
+
* Removed client resolvers when creating clients in a client's factory method (this should not have any impact to end users)
|
1302 |
+
|
1303 |
+
## 2.1.2 - 2013-02-18
|
1304 |
+
|
1305 |
+
* Added support for **AWS OpsWorks**
|
1306 |
+
|
1307 |
+
## 2.1.1 - 2013-02-15
|
1308 |
+
|
1309 |
+
* Added support for **Amazon Redshift**
|
1310 |
+
* Added support for **Amazon Simple Queue Service (Amazon SQS)**
|
1311 |
+
* Added support for **Amazon Simple Notification Service (Amazon SNS)**
|
1312 |
+
* Added support for **Amazon Simple Email Service (Amazon SES)**
|
1313 |
+
* Added support for **Auto Scaling**
|
1314 |
+
* Added support for **Amazon CloudWatch**
|
1315 |
+
* Added support for **Amazon Simple Workflow Service (Amazon SWF)**
|
1316 |
+
* Added support for **Amazon Relational Database Service (Amazon RDS)**
|
1317 |
+
* Added support for health checks and failover in Amazon Route 53
|
1318 |
+
* Updated the Amazon Route 53 client to use the 2012-12-12 API version
|
1319 |
+
* Updated `AbstractWaiter` to dispatch `waiter.before_attempt` and `waiter.before_wait` events
|
1320 |
+
* Updated `CallableWaiter` to allow for an array of context data to be passed to the callable
|
1321 |
+
* Fixed issue #29 so that the stat cache is cleared before performing multipart uploads
|
1322 |
+
* Fixed issue #38 so that Amazon CloudFront URLs are signed properly
|
1323 |
+
* Fixed an issue with Amazon S3 website redirects
|
1324 |
+
* Fixed a URL encoding inconsistency with Amazon S3 and pre-signed URLs
|
1325 |
+
* Fixed issue #42 to eliminate cURL error 65 for JSON services
|
1326 |
+
* Set Guzzle dependency to [~3.2.0](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md#320-2013-02-14)
|
1327 |
+
* Minimum version of PHP is now 5.3.3
|
1328 |
+
|
1329 |
+
## 2.1.0 - 2013-01-28
|
1330 |
+
|
1331 |
+
* Waiters now require an associative array as input for the underlying operation performed by a waiter. See
|
1332 |
+
`UPGRADING.md` for details.
|
1333 |
+
* Added support for **Amazon Elastic Compute Cloud (Amazon EC2)**
|
1334 |
+
* Added support for **Amazon Elastic Transcoder**
|
1335 |
+
* Added support for **Amazon SimpleDB**
|
1336 |
+
* Added support for **Elastic Load Balancing**
|
1337 |
+
* Added support for **AWS Elastic Beanstalk**
|
1338 |
+
* Added support for **AWS Identity and Access Management (IAM)**
|
1339 |
+
* Added support for Amazon S3 website redirection rules
|
1340 |
+
* Added support for the `RetrieveByteRange` parameter of the `InitiateJob` operation in Amazon Glacier
|
1341 |
+
* Added support for Signature Version 2
|
1342 |
+
* Clients now gain more information from service descriptions rather than client factory methods
|
1343 |
+
* Service descriptions are now versioned for clients
|
1344 |
+
* Fixed an issue where Amazon S3 did not use "restore" as a signable resource
|
1345 |
+
* Fixed an issue with Amazon S3 where `x-amz-meta-*` headers were not properly added with the CopyObject operation
|
1346 |
+
* Fixed an issue where the Amazon Glacier client was not using the correct User-Agent header
|
1347 |
+
* Fixed issue #13 in which constants defined by referencing other constants caused errors with early versions of PHP 5.3
|
1348 |
+
|
1349 |
+
## 2.0.3 - 2012-12-20
|
1350 |
+
|
1351 |
+
* Added support for **AWS Data Pipeline**
|
1352 |
+
* Added support for **Amazon Route 53**
|
1353 |
+
* Fixed an issue with the Amazon S3 client where object keys with slashes were causing errors
|
1354 |
+
* Added a `SaveAs` parameter to the Amazon S3 `GetObject` operation to allow saving the object directly to a file
|
1355 |
+
* Refactored iterators to remove code duplication and ease creation of future iterators
|
1356 |
+
|
1357 |
+
## 2.0.2 - 2012-12-10
|
1358 |
+
|
1359 |
+
* Fixed an issue with the Amazon S3 client where non-DNS compatible buckets that was previously causing a signature
|
1360 |
+
mismatch error
|
1361 |
+
* Fixed an issue with the service description for the Amazon S3 `UploadPart` operation so that it works correctly
|
1362 |
+
* Fixed an issue with the Amazon S3 service description dealing with `response-*` query parameters of `GetObject`
|
1363 |
+
* Fixed an issue with the Amazon S3 client where object keys prefixed by the bucket name were being treated incorrectly
|
1364 |
+
* Fixed an issue with `Aws\S3\Model\MultipartUpload\ParallelTransfer` class
|
1365 |
+
* Added support for the `AssumeRole` operation for AWS STS
|
1366 |
+
* Added a the `UploadBodyListener` which allows upload operations in Amazon S3 and Amazon Glacier to accept file handles
|
1367 |
+
in the `Body` parameter and file paths in the `SourceFile` parameter
|
1368 |
+
* Added Content-Type guessing for uploads
|
1369 |
+
* Added new region endpoints, including sa-east-1 and us-gov-west-1 for Amazon DynamoDB
|
1370 |
+
* Added methods to `Aws\S3\Model\MultipartUpload\UploadBuilder` class to make setting ACL and Content-Type easier
|
1371 |
+
|
1372 |
+
## 2.0.1 - 2012-11-13
|
1373 |
+
|
1374 |
+
* Fixed a signature issue encountered when a request to Amazon S3 is redirected
|
1375 |
+
* Added support for archiving Amazon S3 objects to Amazon Glacier
|
1376 |
+
* Added CRC32 validation of Amazon DynamoDB responses
|
1377 |
+
* Added ConsistentRead support to the `BatchGetItem` operation of Amazon DynamoDB
|
1378 |
+
* Added new region endpoints, including Sydney
|
1379 |
+
|
1380 |
+
## 2.0.0 - 2012-11-02
|
1381 |
+
|
1382 |
+
* Initial release of the AWS SDK for PHP Version 2. See <http://aws.amazon.com/sdkforphp2/> for more information.
|
1383 |
+
* Added support for **Amazon Simple Storage Service (Amazon S3)**
|
1384 |
+
* Added support for **Amazon DynamoDB**
|
1385 |
+
* Added support for **Amazon Glacier**
|
1386 |
+
* Added support for **Amazon CloudFront**
|
1387 |
+
* Added support for **AWS Security Token Service (AWS STS)**
|
includes/aws/GuzzleHttp/Client.php
ADDED
@@ -0,0 +1,397 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Cookie\CookieJar;
|
5 |
+
use GuzzleHttp\Promise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @method ResponseInterface get($uri, array $options = [])
|
13 |
+
* @method ResponseInterface head($uri, array $options = [])
|
14 |
+
* @method ResponseInterface put($uri, array $options = [])
|
15 |
+
* @method ResponseInterface post($uri, array $options = [])
|
16 |
+
* @method ResponseInterface patch($uri, array $options = [])
|
17 |
+
* @method ResponseInterface delete($uri, array $options = [])
|
18 |
+
* @method Promise\PromiseInterface getAsync($uri, array $options = [])
|
19 |
+
* @method Promise\PromiseInterface headAsync($uri, array $options = [])
|
20 |
+
* @method Promise\PromiseInterface putAsync($uri, array $options = [])
|
21 |
+
* @method Promise\PromiseInterface postAsync($uri, array $options = [])
|
22 |
+
* @method Promise\PromiseInterface patchAsync($uri, array $options = [])
|
23 |
+
* @method Promise\PromiseInterface deleteAsync($uri, array $options = [])
|
24 |
+
*/
|
25 |
+
class Client implements ClientInterface
|
26 |
+
{
|
27 |
+
/** @var array Default request options */
|
28 |
+
private $config;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Clients accept an array of constructor parameters.
|
32 |
+
*
|
33 |
+
* Here's an example of creating a client using a base_uri and an array of
|
34 |
+
* default request options to apply to each request:
|
35 |
+
*
|
36 |
+
* $client = new Client([
|
37 |
+
* 'base_uri' => 'http://www.foo.com/1.0/',
|
38 |
+
* 'timeout' => 0,
|
39 |
+
* 'allow_redirects' => false,
|
40 |
+
* 'proxy' => '192.168.16.1:10'
|
41 |
+
* ]);
|
42 |
+
*
|
43 |
+
* Client configuration settings include the following options:
|
44 |
+
*
|
45 |
+
* - handler: (callable) Function that transfers HTTP requests over the
|
46 |
+
* wire. The function is called with a Psr7\Http\Message\RequestInterface
|
47 |
+
* and array of transfer options, and must return a
|
48 |
+
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
|
49 |
+
* Psr7\Http\Message\ResponseInterface on success. "handler" is a
|
50 |
+
* constructor only option that cannot be overridden in per/request
|
51 |
+
* options. If no handler is provided, a default handler will be created
|
52 |
+
* that enables all of the request options below by attaching all of the
|
53 |
+
* default middleware to the handler.
|
54 |
+
* - base_uri: (string|UriInterface) Base URI of the client that is merged
|
55 |
+
* into relative URIs. Can be a string or instance of UriInterface.
|
56 |
+
* - **: any request option
|
57 |
+
*
|
58 |
+
* @param array $config Client configuration settings.
|
59 |
+
*
|
60 |
+
* @see \GuzzleHttp\RequestOptions for a list of available request options.
|
61 |
+
*/
|
62 |
+
public function __construct(array $config = [])
|
63 |
+
{
|
64 |
+
if (!isset($config['handler'])) {
|
65 |
+
$config['handler'] = HandlerStack::create();
|
66 |
+
}
|
67 |
+
|
68 |
+
// Convert the base_uri to a UriInterface
|
69 |
+
if (isset($config['base_uri'])) {
|
70 |
+
$config['base_uri'] = Psr7\uri_for($config['base_uri']);
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->configureDefaults($config);
|
74 |
+
}
|
75 |
+
|
76 |
+
public function __call($method, $args)
|
77 |
+
{
|
78 |
+
if (count($args) < 1) {
|
79 |
+
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
80 |
+
}
|
81 |
+
|
82 |
+
$uri = $args[0];
|
83 |
+
$opts = isset($args[1]) ? $args[1] : [];
|
84 |
+
|
85 |
+
return substr($method, -5) === 'Async'
|
86 |
+
? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
|
87 |
+
: $this->request($method, $uri, $opts);
|
88 |
+
}
|
89 |
+
|
90 |
+
public function sendAsync(RequestInterface $request, array $options = [])
|
91 |
+
{
|
92 |
+
// Merge the base URI into the request URI if needed.
|
93 |
+
$options = $this->prepareDefaults($options);
|
94 |
+
|
95 |
+
return $this->transfer(
|
96 |
+
$request->withUri($this->buildUri($request->getUri(), $options)),
|
97 |
+
$options
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
public function send(RequestInterface $request, array $options = [])
|
102 |
+
{
|
103 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
104 |
+
return $this->sendAsync($request, $options)->wait();
|
105 |
+
}
|
106 |
+
|
107 |
+
public function requestAsync($method, $uri = null, array $options = [])
|
108 |
+
{
|
109 |
+
$options = $this->prepareDefaults($options);
|
110 |
+
// Remove request modifying parameter because it can be done up-front.
|
111 |
+
$headers = isset($options['headers']) ? $options['headers'] : [];
|
112 |
+
$body = isset($options['body']) ? $options['body'] : null;
|
113 |
+
$version = isset($options['version']) ? $options['version'] : '1.1';
|
114 |
+
// Merge the URI into the base URI.
|
115 |
+
$uri = $this->buildUri($uri, $options);
|
116 |
+
if (is_array($body)) {
|
117 |
+
$this->invalidBody();
|
118 |
+
}
|
119 |
+
$request = new Psr7\Request($method, $uri, $headers, $body, $version);
|
120 |
+
// Remove the option so that they are not doubly-applied.
|
121 |
+
unset($options['headers'], $options['body'], $options['version']);
|
122 |
+
|
123 |
+
return $this->transfer($request, $options);
|
124 |
+
}
|
125 |
+
|
126 |
+
public function request($method, $uri = null, array $options = [])
|
127 |
+
{
|
128 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
129 |
+
return $this->requestAsync($method, $uri, $options)->wait();
|
130 |
+
}
|
131 |
+
|
132 |
+
public function getConfig($option = null)
|
133 |
+
{
|
134 |
+
return $option === null
|
135 |
+
? $this->config
|
136 |
+
: (isset($this->config[$option]) ? $this->config[$option] : null);
|
137 |
+
}
|
138 |
+
|
139 |
+
private function buildUri($uri, array $config)
|
140 |
+
{
|
141 |
+
if (!isset($config['base_uri'])) {
|
142 |
+
return $uri instanceof UriInterface ? $uri : new Psr7\Uri($uri);
|
143 |
+
}
|
144 |
+
|
145 |
+
return Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Configures the default options for a client.
|
150 |
+
*
|
151 |
+
* @param array $config
|
152 |
+
*/
|
153 |
+
private function configureDefaults(array $config)
|
154 |
+
{
|
155 |
+
$defaults = [
|
156 |
+
'allow_redirects' => RedirectMiddleware::$defaultSettings,
|
157 |
+
'http_errors' => true,
|
158 |
+
'decode_content' => true,
|
159 |
+
'verify' => true,
|
160 |
+
'cookies' => false
|
161 |
+
];
|
162 |
+
|
163 |
+
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
|
164 |
+
if ($proxy = getenv('HTTP_PROXY')) {
|
165 |
+
$defaults['proxy']['http'] = $proxy;
|
166 |
+
}
|
167 |
+
|
168 |
+
if ($proxy = getenv('HTTPS_PROXY')) {
|
169 |
+
$defaults['proxy']['https'] = $proxy;
|
170 |
+
}
|
171 |
+
|
172 |
+
if ($noProxy = getenv('NO_PROXY')) {
|
173 |
+
$cleanedNoProxy = str_replace(' ', '', $noProxy);
|
174 |
+
$defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
|
175 |
+
}
|
176 |
+
|
177 |
+
$this->config = $config + $defaults;
|
178 |
+
|
179 |
+
if (!empty($config['cookies']) && $config['cookies'] === true) {
|
180 |
+
$this->config['cookies'] = new CookieJar();
|
181 |
+
}
|
182 |
+
|
183 |
+
// Add the default user-agent header.
|
184 |
+
if (!isset($this->config['headers'])) {
|
185 |
+
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
186 |
+
} else {
|
187 |
+
// Add the User-Agent header if one was not already set.
|
188 |
+
foreach (array_keys($this->config['headers']) as $name) {
|
189 |
+
if (strtolower($name) === 'user-agent') {
|
190 |
+
return;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
$this->config['headers']['User-Agent'] = default_user_agent();
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Merges default options into the array.
|
199 |
+
*
|
200 |
+
* @param array $options Options to modify by reference
|
201 |
+
*
|
202 |
+
* @return array
|
203 |
+
*/
|
204 |
+
private function prepareDefaults($options)
|
205 |
+
{
|
206 |
+
$defaults = $this->config;
|
207 |
+
|
208 |
+
if (!empty($defaults['headers'])) {
|
209 |
+
// Default headers are only added if they are not present.
|
210 |
+
$defaults['_conditional'] = $defaults['headers'];
|
211 |
+
unset($defaults['headers']);
|
212 |
+
}
|
213 |
+
|
214 |
+
// Special handling for headers is required as they are added as
|
215 |
+
// conditional headers and as headers passed to a request ctor.
|
216 |
+
if (array_key_exists('headers', $options)) {
|
217 |
+
// Allows default headers to be unset.
|
218 |
+
if ($options['headers'] === null) {
|
219 |
+
$defaults['_conditional'] = null;
|
220 |
+
unset($options['headers']);
|
221 |
+
} elseif (!is_array($options['headers'])) {
|
222 |
+
throw new \InvalidArgumentException('headers must be an array');
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
// Shallow merge defaults underneath options.
|
227 |
+
$result = $options + $defaults;
|
228 |
+
|
229 |
+
// Remove null values.
|
230 |
+
foreach ($result as $k => $v) {
|
231 |
+
if ($v === null) {
|
232 |
+
unset($result[$k]);
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
return $result;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Transfers the given request and applies request options.
|
241 |
+
*
|
242 |
+
* The URI of the request is not modified and the request options are used
|
243 |
+
* as-is without merging in default options.
|
244 |
+
*
|
245 |
+
* @param RequestInterface $request
|
246 |
+
* @param array $options
|
247 |
+
*
|
248 |
+
* @return Promise\PromiseInterface
|
249 |
+
*/
|
250 |
+
private function transfer(RequestInterface $request, array $options)
|
251 |
+
{
|
252 |
+
// save_to -> sink
|
253 |
+
if (isset($options['save_to'])) {
|
254 |
+
$options['sink'] = $options['save_to'];
|
255 |
+
unset($options['save_to']);
|
256 |
+
}
|
257 |
+
|
258 |
+
// exceptions -> http_error
|
259 |
+
if (isset($options['exceptions'])) {
|
260 |
+
$options['http_errors'] = $options['exceptions'];
|
261 |
+
unset($options['exceptions']);
|
262 |
+
}
|
263 |
+
|
264 |
+
$request = $this->applyOptions($request, $options);
|
265 |
+
$handler = $options['handler'];
|
266 |
+
|
267 |
+
try {
|
268 |
+
return Promise\promise_for($handler($request, $options));
|
269 |
+
} catch (\Exception $e) {
|
270 |
+
return Promise\rejection_for($e);
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Applies the array of request options to a request.
|
276 |
+
*
|
277 |
+
* @param RequestInterface $request
|
278 |
+
* @param array $options
|
279 |
+
*
|
280 |
+
* @return RequestInterface
|
281 |
+
*/
|
282 |
+
private function applyOptions(RequestInterface $request, array &$options)
|
283 |
+
{
|
284 |
+
$modify = [];
|
285 |
+
|
286 |
+
if (isset($options['form_params'])) {
|
287 |
+
if (isset($options['multipart'])) {
|
288 |
+
throw new \InvalidArgumentException('You cannot use '
|
289 |
+
. 'form_params and multipart at the same time. Use the '
|
290 |
+
. 'form_params option if you want to send application/'
|
291 |
+
. 'x-www-form-urlencoded requests, and the multipart '
|
292 |
+
. 'option to send multipart/form-data requests.');
|
293 |
+
}
|
294 |
+
$options['body'] = http_build_query($options['form_params'], null, '&');
|
295 |
+
unset($options['form_params']);
|
296 |
+
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
297 |
+
}
|
298 |
+
|
299 |
+
if (isset($options['multipart'])) {
|
300 |
+
$elements = $options['multipart'];
|
301 |
+
unset($options['multipart']);
|
302 |
+
$options['body'] = new Psr7\MultipartStream($elements);
|
303 |
+
}
|
304 |
+
|
305 |
+
if (!empty($options['decode_content'])
|
306 |
+
&& $options['decode_content'] !== true
|
307 |
+
) {
|
308 |
+
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
309 |
+
}
|
310 |
+
|
311 |
+
if (isset($options['headers'])) {
|
312 |
+
if (isset($modify['set_headers'])) {
|
313 |
+
$modify['set_headers'] = $options['headers'] + $modify['set_headers'];
|
314 |
+
} else {
|
315 |
+
$modify['set_headers'] = $options['headers'];
|
316 |
+
}
|
317 |
+
unset($options['headers']);
|
318 |
+
}
|
319 |
+
|
320 |
+
if (isset($options['body'])) {
|
321 |
+
if (is_array($options['body'])) {
|
322 |
+
$this->invalidBody();
|
323 |
+
}
|
324 |
+
$modify['body'] = Psr7\stream_for($options['body']);
|
325 |
+
unset($options['body']);
|
326 |
+
}
|
327 |
+
|
328 |
+
if (!empty($options['auth'])) {
|
329 |
+
$value = $options['auth'];
|
330 |
+
$type = is_array($value)
|
331 |
+
? (isset($value[2]) ? strtolower($value[2]) : 'basic')
|
332 |
+
: $value;
|
333 |
+
$config['auth'] = $value;
|
334 |
+
switch (strtolower($type)) {
|
335 |
+
case 'basic':
|
336 |
+
$modify['set_headers']['Authorization'] = 'Basic '
|
337 |
+
. base64_encode("$value[0]:$value[1]");
|
338 |
+
break;
|
339 |
+
case 'digest':
|
340 |
+
// @todo: Do not rely on curl
|
341 |
+
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
342 |
+
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
343 |
+
break;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
if (isset($options['query'])) {
|
348 |
+
$value = $options['query'];
|
349 |
+
if (is_array($value)) {
|
350 |
+
$value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
|
351 |
+
}
|
352 |
+
if (!is_string($value)) {
|
353 |
+
throw new \InvalidArgumentException('query must be a string or array');
|
354 |
+
}
|
355 |
+
$modify['query'] = $value;
|
356 |
+
unset($options['query']);
|
357 |
+
}
|
358 |
+
|
359 |
+
if (isset($options['json'])) {
|
360 |
+
$modify['body'] = Psr7\stream_for(json_encode($options['json']));
|
361 |
+
$options['_conditional']['Content-Type'] = 'application/json';
|
362 |
+
unset($options['json']);
|
363 |
+
}
|
364 |
+
|
365 |
+
$request = Psr7\modify_request($request, $modify);
|
366 |
+
if ($request->getBody() instanceof Psr7\MultipartStream) {
|
367 |
+
// Use a multipart/form-data POST if a Content-Type is not set.
|
368 |
+
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
369 |
+
. $request->getBody()->getBoundary();
|
370 |
+
}
|
371 |
+
|
372 |
+
// Merge in conditional headers if they are not present.
|
373 |
+
if (isset($options['_conditional'])) {
|
374 |
+
// Build up the changes so it's in a single clone of the message.
|
375 |
+
$modify = [];
|
376 |
+
foreach ($options['_conditional'] as $k => $v) {
|
377 |
+
if (!$request->hasHeader($k)) {
|
378 |
+
$modify['set_headers'][$k] = $v;
|
379 |
+
}
|
380 |
+
}
|
381 |
+
$request = Psr7\modify_request($request, $modify);
|
382 |
+
// Don't pass this internal value along to middleware/handlers.
|
383 |
+
unset($options['_conditional']);
|
384 |
+
}
|
385 |
+
|
386 |
+
return $request;
|
387 |
+
}
|
388 |
+
|
389 |
+
private function invalidBody()
|
390 |
+
{
|
391 |
+
throw new \InvalidArgumentException('Passing in the "body" request '
|
392 |
+
. 'option as an array to send a POST request has been deprecated. '
|
393 |
+
. 'Please use the "form_params" request option to send a '
|
394 |
+
. 'application/x-www-form-urlencoded request, or a the "multipart" '
|
395 |
+
. 'request option to send a multipart/form-data request.');
|
396 |
+
}
|
397 |
+
}
|
includes/aws/GuzzleHttp/ClientInterface.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Exception\GuzzleException;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
use Psr\Http\Message\UriInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Client interface for sending HTTP requests.
|
12 |
+
*/
|
13 |
+
interface ClientInterface
|
14 |
+
{
|
15 |
+
const VERSION = '6.1.1';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Send an HTTP request.
|
19 |
+
*
|
20 |
+
* @param RequestInterface $request Request to send
|
21 |
+
* @param array $options Request options to apply to the given
|
22 |
+
* request and to the transfer.
|
23 |
+
*
|
24 |
+
* @return ResponseInterface
|
25 |
+
* @throws GuzzleException
|
26 |
+
*/
|
27 |
+
public function send(RequestInterface $request, array $options = []);
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Asynchronously send an HTTP request.
|
31 |
+
*
|
32 |
+
* @param RequestInterface $request Request to send
|
33 |
+
* @param array $options Request options to apply to the given
|
34 |
+
* request and to the transfer.
|
35 |
+
*
|
36 |
+
* @return PromiseInterface
|
37 |
+
*/
|
38 |
+
public function sendAsync(RequestInterface $request, array $options = []);
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Create and send an HTTP request.
|
42 |
+
*
|
43 |
+
* Use an absolute path to override the base path of the client, or a
|
44 |
+
* relative path to append to the base path of the client. The URL can
|
45 |
+
* contain the query string as well.
|
46 |
+
*
|
47 |
+
* @param string $method HTTP method
|
48 |
+
* @param string|UriInterface $uri URI object or string.
|
49 |
+
* @param array $options Request options to apply.
|
50 |
+
*
|
51 |
+
* @return ResponseInterface
|
52 |
+
* @throws GuzzleException
|
53 |
+
*/
|
54 |
+
public function request($method, $uri, array $options = []);
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Create and send an asynchronous HTTP request.
|
58 |
+
*
|
59 |
+
* Use an absolute path to override the base path of the client, or a
|
60 |
+
* relative path to append to the base path of the client. The URL can
|
61 |
+
* contain the query string as well. Use an array to provide a URL
|
62 |
+
* template and additional variables to use in the URL template expansion.
|
63 |
+
*
|
64 |
+
* @param string $method HTTP method
|
65 |
+
* @param string|UriInterface $uri URI object or string.
|
66 |
+
* @param array $options Request options to apply.
|
67 |
+
*
|
68 |
+
* @return PromiseInterface
|
69 |
+
*/
|
70 |
+
public function requestAsync($method, $uri, array $options = []);
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get a client configuration option.
|
74 |
+
*
|
75 |
+
* These options include default request options of the client, a "handler"
|
76 |
+
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
77 |
+
* the concrete client.
|
78 |
+
*
|
79 |
+
* @param string|null $option The config option to retrieve.
|
80 |
+
*
|
81 |
+
* @return mixed
|
82 |
+
*/
|
83 |
+
public function getConfig($option = null);
|
84 |
+
}
|
includes/aws/GuzzleHttp/Cookie/CookieJar.php
ADDED
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Cookie jar that stores cookies an an array
|
9 |
+
*/
|
10 |
+
class CookieJar implements CookieJarInterface
|
11 |
+
{
|
12 |
+
/** @var SetCookie[] Loaded cookie data */
|
13 |
+
private $cookies = [];
|
14 |
+
|
15 |
+
/** @var bool */
|
16 |
+
private $strictMode;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param bool $strictMode Set to true to throw exceptions when invalid
|
20 |
+
* cookies are added to the cookie jar.
|
21 |
+
* @param array $cookieArray Array of SetCookie objects or a hash of
|
22 |
+
* arrays that can be used with the SetCookie
|
23 |
+
* constructor
|
24 |
+
*/
|
25 |
+
public function __construct($strictMode = false, $cookieArray = [])
|
26 |
+
{
|
27 |
+
$this->strictMode = $strictMode;
|
28 |
+
|
29 |
+
foreach ($cookieArray as $cookie) {
|
30 |
+
if (!($cookie instanceof SetCookie)) {
|
31 |
+
$cookie = new SetCookie($cookie);
|
32 |
+
}
|
33 |
+
$this->setCookie($cookie);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Create a new Cookie jar from an associative array and domain.
|
39 |
+
*
|
40 |
+
* @param array $cookies Cookies to create the jar from
|
41 |
+
* @param string $domain Domain to set the cookies to
|
42 |
+
*
|
43 |
+
* @return self
|
44 |
+
*/
|
45 |
+
public static function fromArray(array $cookies, $domain)
|
46 |
+
{
|
47 |
+
$cookieJar = new self();
|
48 |
+
foreach ($cookies as $name => $value) {
|
49 |
+
$cookieJar->setCookie(new SetCookie([
|
50 |
+
'Domain' => $domain,
|
51 |
+
'Name' => $name,
|
52 |
+
'Value' => $value,
|
53 |
+
'Discard' => true
|
54 |
+
]));
|
55 |
+
}
|
56 |
+
|
57 |
+
return $cookieJar;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Quote the cookie value if it is not already quoted and it contains
|
62 |
+
* problematic characters.
|
63 |
+
*
|
64 |
+
* @param string $value Value that may or may not need to be quoted
|
65 |
+
*
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
+
public static function getCookieValue($value)
|
69 |
+
{
|
70 |
+
if (substr($value, 0, 1) !== '"' &&
|
71 |
+
substr($value, -1, 1) !== '"' &&
|
72 |
+
strpbrk($value, ';,=')
|
73 |
+
) {
|
74 |
+
$value = '"' . $value . '"';
|
75 |
+
}
|
76 |
+
|
77 |
+
return $value;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Evaluate if this cookie should be persisted to storage
|
82 |
+
* that survives between requests.
|
83 |
+
*
|
84 |
+
* @param SetCookie $cookie Being evaluated.
|
85 |
+
* @param bool $allowSessionCookies If we should persist session cookies
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
+
public static function shouldPersist(
|
89 |
+
SetCookie $cookie,
|
90 |
+
$allowSessionCookies = false
|
91 |
+
) {
|
92 |
+
if ($cookie->getExpires() || $allowSessionCookies) {
|
93 |
+
if (!$cookie->getDiscard()) {
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
|
101 |
+
public function toArray()
|
102 |
+
{
|
103 |
+
return array_map(function (SetCookie $cookie) {
|
104 |
+
return $cookie->toArray();
|
105 |
+
}, $this->getIterator()->getArrayCopy());
|
106 |
+
}
|
107 |
+
|
108 |
+
public function clear($domain = null, $path = null, $name = null)
|
109 |
+
{
|
110 |
+
if (!$domain) {
|
111 |
+
$this->cookies = [];
|
112 |
+
return;
|
113 |
+
} elseif (!$path) {
|
114 |
+
$this->cookies = array_filter(
|
115 |
+
$this->cookies,
|
116 |
+
function (SetCookie $cookie) use ($path, $domain) {
|
117 |
+
return !$cookie->matchesDomain($domain);
|
118 |
+
}
|
119 |
+
);
|
120 |
+
} elseif (!$name) {
|
121 |
+
$this->cookies = array_filter(
|
122 |
+
$this->cookies,
|
123 |
+
function (SetCookie $cookie) use ($path, $domain) {
|
124 |
+
return !($cookie->matchesPath($path) &&
|
125 |
+
$cookie->matchesDomain($domain));
|
126 |
+
}
|
127 |
+
);
|
128 |
+
} else {
|
129 |
+
$this->cookies = array_filter(
|
130 |
+
$this->cookies,
|
131 |
+
function (SetCookie $cookie) use ($path, $domain, $name) {
|
132 |
+
return !($cookie->getName() == $name &&
|
133 |
+
$cookie->matchesPath($path) &&
|
134 |
+
$cookie->matchesDomain($domain));
|
135 |
+
}
|
136 |
+
);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
public function clearSessionCookies()
|
141 |
+
{
|
142 |
+
$this->cookies = array_filter(
|
143 |
+
$this->cookies,
|
144 |
+
function (SetCookie $cookie) {
|
145 |
+
return !$cookie->getDiscard() && $cookie->getExpires();
|
146 |
+
}
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
+
public function setCookie(SetCookie $cookie)
|
151 |
+
{
|
152 |
+
// If the name string is empty (but not 0), ignore the set-cookie
|
153 |
+
// string entirely.
|
154 |
+
$name = $cookie->getName();
|
155 |
+
if (!$name && $name !== '0') {
|
156 |
+
return false;
|
157 |
+
}
|
158 |
+
|
159 |
+
// Only allow cookies with set and valid domain, name, value
|
160 |
+
$result = $cookie->validate();
|
161 |
+
if ($result !== true) {
|
162 |
+
if ($this->strictMode) {
|
163 |
+
throw new \RuntimeException('Invalid cookie: ' . $result);
|
164 |
+
} else {
|
165 |
+
$this->removeCookieIfEmpty($cookie);
|
166 |
+
return false;
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
// Resolve conflicts with previously set cookies
|
171 |
+
foreach ($this->cookies as $i => $c) {
|
172 |
+
|
173 |
+
// Two cookies are identical, when their path, and domain are
|
174 |
+
// identical.
|
175 |
+
if ($c->getPath() != $cookie->getPath() ||
|
176 |
+
$c->getDomain() != $cookie->getDomain() ||
|
177 |
+
$c->getName() != $cookie->getName()
|
178 |
+
) {
|
179 |
+
continue;
|
180 |
+
}
|
181 |
+
|
182 |
+
// The previously set cookie is a discard cookie and this one is
|
183 |
+
// not so allow the new cookie to be set
|
184 |
+
if (!$cookie->getDiscard() && $c->getDiscard()) {
|
185 |
+
unset($this->cookies[$i]);
|
186 |
+
continue;
|
187 |
+
}
|
188 |
+
|
189 |
+
// If the new cookie's expiration is further into the future, then
|
190 |
+
// replace the old cookie
|
191 |
+
if ($cookie->getExpires() > $c->getExpires()) {
|
192 |
+
unset($this->cookies[$i]);
|
193 |
+
continue;
|
194 |
+
}
|
195 |
+
|
196 |
+
// If the value has changed, we better change it
|
197 |
+
if ($cookie->getValue() !== $c->getValue()) {
|
198 |
+
unset($this->cookies[$i]);
|
199 |
+
continue;
|
200 |
+
}
|
201 |
+
|
202 |
+
// The cookie exists, so no need to continue
|
203 |
+
return false;
|
204 |
+
}
|
205 |
+
|
206 |
+
$this->cookies[] = $cookie;
|
207 |
+
|
208 |
+
return true;
|
209 |
+
}
|
210 |
+
|
211 |
+
public function count()
|
212 |
+
{
|
213 |
+
return count($this->cookies);
|
214 |
+
}
|
215 |
+
|
216 |
+
public function getIterator()
|
217 |
+
{
|
218 |
+
return new \ArrayIterator(array_values($this->cookies));
|
219 |
+
}
|
220 |
+
|
221 |
+
public function extractCookies(
|
222 |
+
RequestInterface $request,
|
223 |
+
ResponseInterface $response
|
224 |
+
) {
|
225 |
+
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
226 |
+
foreach ($cookieHeader as $cookie) {
|
227 |
+
$sc = SetCookie::fromString($cookie);
|
228 |
+
if (!$sc->getDomain()) {
|
229 |
+
$sc->setDomain($request->getUri()->getHost());
|
230 |
+
}
|
231 |
+
$this->setCookie($sc);
|
232 |
+
}
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
public function withCookieHeader(RequestInterface $request)
|
237 |
+
{
|
238 |
+
$values = [];
|
239 |
+
$uri = $request->getUri();
|
240 |
+
$scheme = $uri->getScheme();
|
241 |
+
$host = $uri->getHost();
|
242 |
+
$path = $uri->getPath() ?: '/';
|
243 |
+
|
244 |
+
foreach ($this->cookies as $cookie) {
|
245 |
+
if ($cookie->matchesPath($path) &&
|
246 |
+
$cookie->matchesDomain($host) &&
|
247 |
+
!$cookie->isExpired() &&
|
248 |
+
(!$cookie->getSecure() || $scheme == 'https')
|
249 |
+
) {
|
250 |
+
$values[] = $cookie->getName() . '='
|
251 |
+
. self::getCookieValue($cookie->getValue());
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
return $values
|
256 |
+
? $request->withHeader('Cookie', implode('; ', $values))
|
257 |
+
: $request;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* If a cookie already exists and the server asks to set it again with a
|
262 |
+
* null value, the cookie must be deleted.
|
263 |
+
*
|
264 |
+
* @param SetCookie $cookie
|
265 |
+
*/
|
266 |
+
private function removeCookieIfEmpty(SetCookie $cookie)
|
267 |
+
{
|
268 |
+
$cookieValue = $cookie->getValue();
|
269 |
+
if ($cookieValue === null || $cookieValue === '') {
|
270 |
+
$this->clear(
|
271 |
+
$cookie->getDomain(),
|
272 |
+
$cookie->getPath(),
|
273 |
+
$cookie->getName()
|
274 |
+
);
|
275 |
+
}
|
276 |
+
}
|
277 |
+
}
|
includes/aws/GuzzleHttp/Cookie/CookieJarInterface.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Stores HTTP cookies.
|
9 |
+
*
|
10 |
+
* It extracts cookies from HTTP requests, and returns them in HTTP responses.
|
11 |
+
* CookieJarInterface instances automatically expire contained cookies when
|
12 |
+
* necessary. Subclasses are also responsible for storing and retrieving
|
13 |
+
* cookies from a file, database, etc.
|
14 |
+
*
|
15 |
+
* @link http://docs.python.org/2/library/cookielib.html Inspiration
|
16 |
+
*/
|
17 |
+
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Create a request with added cookie headers.
|
21 |
+
*
|
22 |
+
* If no matching cookies are found in the cookie jar, then no Cookie
|
23 |
+
* header is added to the request and the same request is returned.
|
24 |
+
*
|
25 |
+
* @param RequestInterface $request Request object to modify.
|
26 |
+
*
|
27 |
+
* @return RequestInterface returns the modified request.
|
28 |
+
*/
|
29 |
+
public function withCookieHeader(RequestInterface $request);
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Extract cookies from an HTTP response and store them in the CookieJar.
|
33 |
+
*
|
34 |
+
* @param RequestInterface $request Request that was sent
|
35 |
+
* @param ResponseInterface $response Response that was received
|
36 |
+
*/
|
37 |
+
public function extractCookies(
|
38 |
+
RequestInterface $request,
|
39 |
+
ResponseInterface $response
|
40 |
+
);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Sets a cookie in the cookie jar.
|
44 |
+
*
|
45 |
+
* @param SetCookie $cookie Cookie to set.
|
46 |
+
*
|
47 |
+
* @return bool Returns true on success or false on failure
|
48 |
+
*/
|
49 |
+
public function setCookie(SetCookie $cookie);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Remove cookies currently held in the cookie jar.
|
53 |
+
*
|
54 |
+
* Invoking this method without arguments will empty the whole cookie jar.
|
55 |
+
* If given a $domain argument only cookies belonging to that domain will
|
56 |
+
* be removed. If given a $domain and $path argument, cookies belonging to
|
57 |
+
* the specified path within that domain are removed. If given all three
|
58 |
+
* arguments, then the cookie with the specified name, path and domain is
|
59 |
+
* removed.
|
60 |
+
*
|
61 |
+
* @param string $domain Clears cookies matching a domain
|
62 |
+
* @param string $path Clears cookies matching a domain and path
|
63 |
+
* @param string $name Clears cookies matching a domain, path, and name
|
64 |
+
*
|
65 |
+
* @return CookieJarInterface
|
66 |
+
*/
|
67 |
+
public function clear($domain = null, $path = null, $name = null);
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Discard all sessions cookies.
|
71 |
+
*
|
72 |
+
* Removes cookies that don't have an expire field or a have a discard
|
73 |
+
* field set to true. To be called when the user agent shuts down according
|
74 |
+
* to RFC 2965.
|
75 |
+
*/
|
76 |
+
public function clearSessionCookies();
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Converts the cookie jar to an array.
|
80 |
+
*
|
81 |
+
* @return array
|
82 |
+
*/
|
83 |
+
public function toArray();
|
84 |
+
}
|
includes/aws/GuzzleHttp/Cookie/FileCookieJar.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Persists non-session cookies using a JSON formatted file
|
6 |
+
*/
|
7 |
+
class FileCookieJar extends CookieJar
|
8 |
+
{
|
9 |
+
/** @var string filename */
|
10 |
+
private $filename;
|
11 |
+
|
12 |
+
/** @var bool Control whether to persist session cookies or not. */
|
13 |
+
private $storeSessionCookies;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Create a new FileCookieJar object
|
17 |
+
*
|
18 |
+
* @param string $cookieFile File to store the cookie data
|
19 |
+
* @param bool $storeSessionCookies Set to true to store session cookies
|
20 |
+
* in the cookie jar.
|
21 |
+
*
|
22 |
+
* @throws \RuntimeException if the file cannot be found or created
|
23 |
+
*/
|
24 |
+
public function __construct($cookieFile, $storeSessionCookies = false)
|
25 |
+
{
|
26 |
+
$this->filename = $cookieFile;
|
27 |
+
$this->storeSessionCookies = $storeSessionCookies;
|
28 |
+
|
29 |
+
if (file_exists($cookieFile)) {
|
30 |
+
$this->load($cookieFile);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Saves the file when shutting down
|
36 |
+
*/
|
37 |
+
public function __destruct()
|
38 |
+
{
|
39 |
+
$this->save($this->filename);
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Saves the cookies to a file.
|
44 |
+
*
|
45 |
+
* @param string $filename File to save
|
46 |
+
* @throws \RuntimeException if the file cannot be found or created
|
47 |
+
*/
|
48 |
+
public function save($filename)
|
49 |
+
{
|
50 |
+
$json = [];
|
51 |
+
foreach ($this as $cookie) {
|
52 |
+
/** @var SetCookie $cookie */
|
53 |
+
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
54 |
+
$json[] = $cookie->toArray();
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
if (false === file_put_contents($filename, json_encode($json))) {
|
59 |
+
throw new \RuntimeException("Unable to save file {$filename}");
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Load cookies from a JSON formatted file.
|
65 |
+
*
|
66 |
+
* Old cookies are kept unless overwritten by newly loaded ones.
|
67 |
+
*
|
68 |
+
* @param string $filename Cookie file to load.
|
69 |
+
* @throws \RuntimeException if the file cannot be loaded.
|
70 |
+
*/
|
71 |
+
public function load($filename)
|
72 |
+
{
|
73 |
+
$json = file_get_contents($filename);
|
74 |
+
if (false === $json) {
|
75 |
+
throw new \RuntimeException("Unable to load file {$filename}");
|
76 |
+
}
|
77 |
+
|
78 |
+
$data = json_decode($json, true);
|
79 |
+
if (is_array($data)) {
|
80 |
+
foreach (json_decode($json, true) as $cookie) {
|
81 |
+
$this->setCookie(new SetCookie($cookie));
|
82 |
+
}
|
83 |
+
} elseif (strlen($data)) {
|
84 |
+
throw new \RuntimeException("Invalid cookie file: {$filename}");
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
includes/aws/GuzzleHttp/Cookie/SessionCookieJar.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Persists cookies in the client session
|
6 |
+
*/
|
7 |
+
class SessionCookieJar extends CookieJar
|
8 |
+
{
|
9 |
+
/** @var string session key */
|
10 |
+
private $sessionKey;
|
11 |
+
|
12 |
+
/** @var bool Control whether to persist session cookies or not. */
|
13 |
+
private $storeSessionCookies;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Create a new SessionCookieJar object
|
17 |
+
*
|
18 |
+
* @param string $sessionKey Session key name to store the cookie
|
19 |
+
* data in session
|
20 |
+
* @param bool $storeSessionCookies Set to true to store session cookies
|
21 |
+
* in the cookie jar.
|
22 |
+
*/
|
23 |
+
public function __construct($sessionKey, $storeSessionCookies = false)
|
24 |
+
{
|
25 |
+
$this->sessionKey = $sessionKey;
|
26 |
+
$this->storeSessionCookies = $storeSessionCookies;
|
27 |
+
$this->load();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Saves cookies to session when shutting down
|
32 |
+
*/
|
33 |
+
public function __destruct()
|
34 |
+
{
|
35 |
+
$this->save();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Save cookies to the client session
|
40 |
+
*/
|
41 |
+
public function save()
|
42 |
+
{
|
43 |
+
$json = [];
|
44 |
+
foreach ($this as $cookie) {
|
45 |
+
/** @var SetCookie $cookie */
|
46 |
+
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
47 |
+
$json[] = $cookie->toArray();
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
$_SESSION[$this->sessionKey] = json_encode($json);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Load the contents of the client session into the data array
|
56 |
+
*/
|
57 |
+
protected function load()
|
58 |
+
{
|
59 |
+
$cookieJar = isset($_SESSION[$this->sessionKey])
|
60 |
+
? $_SESSION[$this->sessionKey]
|
61 |
+
: null;
|
62 |
+
|
63 |
+
$data = json_decode($cookieJar, true);
|
64 |
+
if (is_array($data)) {
|
65 |
+
foreach ($data as $cookie) {
|
66 |
+
$this->setCookie(new SetCookie($cookie));
|
67 |
+
}
|
68 |
+
} elseif (strlen($data)) {
|
69 |
+
throw new \RuntimeException("Invalid cookie data");
|
70 |
+
}
|
71 |
+
}
|
72 |
+
}
|
includes/aws/GuzzleHttp/Cookie/SetCookie.php
ADDED
@@ -0,0 +1,404 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Set-Cookie object
|
6 |
+
*/
|
7 |
+
class SetCookie
|
8 |
+
{
|
9 |
+
/** @var array */
|
10 |
+
private static $defaults = [
|
11 |
+
'Name' => null,
|
12 |
+
'Value' => null,
|
13 |
+
'Domain' => null,
|
14 |
+
'Path' => '/',
|
15 |
+
'Max-Age' => null,
|
16 |
+
'Expires' => null,
|
17 |
+
'Secure' => false,
|
18 |
+
'Discard' => false,
|
19 |
+
'HttpOnly' => false
|
20 |
+
];
|
21 |
+
|
22 |
+
/** @var array Cookie data */
|
23 |
+
private $data;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Create a new SetCookie object from a string
|
27 |
+
*
|
28 |
+
* @param string $cookie Set-Cookie header string
|
29 |
+
*
|
30 |
+
* @return self
|
31 |
+
*/
|
32 |
+
public static function fromString($cookie)
|
33 |
+
{
|
34 |
+
// Create the default return array
|
35 |
+
$data = self::$defaults;
|
36 |
+
// Explode the cookie string using a series of semicolons
|
37 |
+
$pieces = array_filter(array_map('trim', explode(';', $cookie)));
|
38 |
+
// The name of the cookie (first kvp) must include an equal sign.
|
39 |
+
if (empty($pieces) || !strpos($pieces[0], '=')) {
|
40 |
+
return new self($data);
|
41 |
+
}
|
42 |
+
|
43 |
+
// Add the cookie pieces into the parsed data array
|
44 |
+
foreach ($pieces as $part) {
|
45 |
+
|
46 |
+
$cookieParts = explode('=', $part, 2);
|
47 |
+
$key = trim($cookieParts[0]);
|
48 |
+
$value = isset($cookieParts[1])
|
49 |
+
? trim($cookieParts[1], " \n\r\t\0\x0B")
|
50 |
+
: true;
|
51 |
+
|
52 |
+
// Only check for non-cookies when cookies have been found
|
53 |
+
if (empty($data['Name'])) {
|
54 |
+
$data['Name'] = $key;
|
55 |
+
$data['Value'] = $value;
|
56 |
+
} else {
|
57 |
+
foreach (array_keys(self::$defaults) as $search) {
|
58 |
+
if (!strcasecmp($search, $key)) {
|
59 |
+
$data[$search] = $value;
|
60 |
+
continue 2;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
$data[$key] = $value;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
return new self($data);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @param array $data Array of cookie data provided by a Cookie parser
|
72 |
+
*/
|
73 |
+
public function __construct(array $data = [])
|
74 |
+
{
|
75 |
+
$this->data = array_replace(self::$defaults, $data);
|
76 |
+
// Extract the Expires value and turn it into a UNIX timestamp if needed
|
77 |
+
if (!$this->getExpires() && $this->getMaxAge()) {
|
78 |
+
// Calculate the Expires date
|
79 |
+
$this->setExpires(time() + $this->getMaxAge());
|
80 |
+
} elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
|
81 |
+
$this->setExpires($this->getExpires());
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
public function __toString()
|
86 |
+
{
|
87 |
+
$str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
|
88 |
+
foreach ($this->data as $k => $v) {
|
89 |
+
if ($k != 'Name' && $k != 'Value' && $v !== null && $v !== false) {
|
90 |
+
if ($k == 'Expires') {
|
91 |
+
$str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
|
92 |
+
} else {
|
93 |
+
$str .= ($v === true ? $k : "{$k}={$v}") . '; ';
|
94 |
+
}
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
return rtrim($str, '; ');
|
99 |
+
}
|
100 |
+
|
101 |
+
public function toArray()
|
102 |
+
{
|
103 |
+
return $this->data;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Get the cookie name
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
public function getName()
|
112 |
+
{
|
113 |
+
return $this->data['Name'];
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Set the cookie name
|
118 |
+
*
|
119 |
+
* @param string $name Cookie name
|
120 |
+
*/
|
121 |
+
public function setName($name)
|
122 |
+
{
|
123 |
+
$this->data['Name'] = $name;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get the cookie value
|
128 |
+
*
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
public function getValue()
|
132 |
+
{
|
133 |
+
return $this->data['Value'];
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Set the cookie value
|
138 |
+
*
|
139 |
+
* @param string $value Cookie value
|
140 |
+
*/
|
141 |
+
public function setValue($value)
|
142 |
+
{
|
143 |
+
$this->data['Value'] = $value;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Get the domain
|
148 |
+
*
|
149 |
+
* @return string|null
|
150 |
+
*/
|
151 |
+
public function getDomain()
|
152 |
+
{
|
153 |
+
return $this->data['Domain'];
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Set the domain of the cookie
|
158 |
+
*
|
159 |
+
* @param string $domain
|
160 |
+
*/
|
161 |
+
public function setDomain($domain)
|
162 |
+
{
|
163 |
+
$this->data['Domain'] = $domain;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Get the path
|
168 |
+
*
|
169 |
+
* @return string
|
170 |
+
*/
|
171 |
+
public function getPath()
|
172 |
+
{
|
173 |
+
return $this->data['Path'];
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Set the path of the cookie
|
178 |
+
*
|
179 |
+
* @param string $path Path of the cookie
|
180 |
+
*/
|
181 |
+
public function setPath($path)
|
182 |
+
{
|
183 |
+
$this->data['Path'] = $path;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Maximum lifetime of the cookie in seconds
|
188 |
+
*
|
189 |
+
* @return int|null
|
190 |
+
*/
|
191 |
+
public function getMaxAge()
|
192 |
+
{
|
193 |
+
return $this->data['Max-Age'];
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Set the max-age of the cookie
|
198 |
+
*
|
199 |
+
* @param int $maxAge Max age of the cookie in seconds
|
200 |
+
*/
|
201 |
+
public function setMaxAge($maxAge)
|
202 |
+
{
|
203 |
+
$this->data['Max-Age'] = $maxAge;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* The UNIX timestamp when the cookie Expires
|
208 |
+
*
|
209 |
+
* @return mixed
|
210 |
+
*/
|
211 |
+
public function getExpires()
|
212 |
+
{
|
213 |
+
return $this->data['Expires'];
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Set the unix timestamp for which the cookie will expire
|
218 |
+
*
|
219 |
+
* @param int $timestamp Unix timestamp
|
220 |
+
*/
|
221 |
+
public function setExpires($timestamp)
|
222 |
+
{
|
223 |
+
$this->data['Expires'] = is_numeric($timestamp)
|
224 |
+
? (int) $timestamp
|
225 |
+
: strtotime($timestamp);
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Get whether or not this is a secure cookie
|
230 |
+
*
|
231 |
+
* @return null|bool
|
232 |
+
*/
|
233 |
+
public function getSecure()
|
234 |
+
{
|
235 |
+
return $this->data['Secure'];
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Set whether or not the cookie is secure
|
240 |
+
*
|
241 |
+
* @param bool $secure Set to true or false if secure
|
242 |
+
*/
|
243 |
+
public function setSecure($secure)
|
244 |
+
{
|
245 |
+
$this->data['Secure'] = $secure;
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Get whether or not this is a session cookie
|
250 |
+
*
|
251 |
+
* @return null|bool
|
252 |
+
*/
|
253 |
+
public function getDiscard()
|
254 |
+
{
|
255 |
+
return $this->data['Discard'];
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Set whether or not this is a session cookie
|
260 |
+
*
|
261 |
+
* @param bool $discard Set to true or false if this is a session cookie
|
262 |
+
*/
|
263 |
+
public function setDiscard($discard)
|
264 |
+
{
|
265 |
+
$this->data['Discard'] = $discard;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Get whether or not this is an HTTP only cookie
|
270 |
+
*
|
271 |
+
* @return bool
|
272 |
+
*/
|
273 |
+
public function getHttpOnly()
|
274 |
+
{
|
275 |
+
return $this->data['HttpOnly'];
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Set whether or not this is an HTTP only cookie
|
280 |
+
*
|
281 |
+
* @param bool $httpOnly Set to true or false if this is HTTP only
|
282 |
+
*/
|
283 |
+
public function setHttpOnly($httpOnly)
|
284 |
+
{
|
285 |
+
$this->data['HttpOnly'] = $httpOnly;
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Check if the cookie matches a path value.
|
290 |
+
*
|
291 |
+
* A request-path path-matches a given cookie-path if at least one of
|
292 |
+
* the following conditions holds:
|
293 |
+
*
|
294 |
+
* - The cookie-path and the request-path are identical.
|
295 |
+
* - The cookie-path is a prefix of the request-path, and the last
|
296 |
+
* character of the cookie-path is %x2F ("/").
|
297 |
+
* - The cookie-path is a prefix of the request-path, and the first
|
298 |
+
* character of the request-path that is not included in the cookie-
|
299 |
+
* path is a %x2F ("/") character.
|
300 |
+
*
|
301 |
+
* @param string $requestPath Path to check against
|
302 |
+
*
|
303 |
+
* @return bool
|
304 |
+
*/
|
305 |
+
public function matchesPath($requestPath)
|
306 |
+
{
|
307 |
+
$cookiePath = $this->getPath();
|
308 |
+
|
309 |
+
// Match on exact matches or when path is the default empty "/"
|
310 |
+
if ($cookiePath == '/' || $cookiePath == $requestPath) {
|
311 |
+
return true;
|
312 |
+
}
|
313 |
+
|
314 |
+
// Ensure that the cookie-path is a prefix of the request path.
|
315 |
+
if (0 !== strpos($requestPath, $cookiePath)) {
|
316 |
+
return false;
|
317 |
+
}
|
318 |
+
|
319 |
+
// Match if the last character of the cookie-path is "/"
|
320 |
+
if (substr($cookiePath, -1, 1) == '/') {
|
321 |
+
return true;
|
322 |
+
}
|
323 |
+
|
324 |
+
// Match if the first character not included in cookie path is "/"
|
325 |
+
return substr($requestPath, strlen($cookiePath), 1) == '/';
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Check if the cookie matches a domain value
|
330 |
+
*
|
331 |
+
* @param string $domain Domain to check against
|
332 |
+
*
|
333 |
+
* @return bool
|
334 |
+
*/
|
335 |
+
public function matchesDomain($domain)
|
336 |
+
{
|
337 |
+
// Remove the leading '.' as per spec in RFC 6265.
|
338 |
+
// http://tools.ietf.org/html/rfc6265#section-5.2.3
|
339 |
+
$cookieDomain = ltrim($this->getDomain(), '.');
|
340 |
+
|
341 |
+
// Domain not set or exact match.
|
342 |
+
if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
|
343 |
+
return true;
|
344 |
+
}
|
345 |
+
|
346 |
+
// Matching the subdomain according to RFC 6265.
|
347 |
+
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
348 |
+
if (filter_var($domain, FILTER_VALIDATE_IP)) {
|
349 |
+
return false;
|
350 |
+
}
|
351 |
+
|
352 |
+
return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Check if the cookie is expired
|
357 |
+
*
|
358 |
+
* @return bool
|
359 |
+
*/
|
360 |
+
public function isExpired()
|
361 |
+
{
|
362 |
+
return $this->getExpires() && time() > $this->getExpires();
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Check if the cookie is valid according to RFC 6265
|
367 |
+
*
|
368 |
+
* @return bool|string Returns true if valid or an error message if invalid
|
369 |
+
*/
|
370 |
+
public function validate()
|
371 |
+
{
|
372 |
+
// Names must not be empty, but can be 0
|
373 |
+
$name = $this->getName();
|
374 |
+
if (empty($name) && !is_numeric($name)) {
|
375 |
+
return 'The cookie name must not be empty';
|
376 |
+
}
|
377 |
+
|
378 |
+
// Check if any of the invalid characters are present in the cookie name
|
379 |
+
if (preg_match(
|
380 |
+
'/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
|
381 |
+
$name)
|
382 |
+
) {
|
383 |
+
return 'Cookie name must not contain invalid characters: ASCII '
|
384 |
+
. 'Control characters (0-31;127), space, tab and the '
|
385 |
+
. 'following characters: ()<>@,;:\"/?={}';
|
386 |
+
}
|
387 |
+
|
388 |
+
// Value must not be empty, but can be 0
|
389 |
+
$value = $this->getValue();
|
390 |
+
if (empty($value) && !is_numeric($value)) {
|
391 |
+
return 'The cookie value must not be empty';
|
392 |
+
}
|
393 |
+
|
394 |
+
// Domains must not be empty, but can be 0
|
395 |
+
// A "0" is not a valid internet domain, but may be used as server name
|
396 |
+
// in a private network.
|
397 |
+
$domain = $this->getDomain();
|
398 |
+
if (empty($domain) && !is_numeric($domain)) {
|
399 |
+
return 'The cookie domain must not be empty';
|
400 |
+
}
|
401 |
+
|
402 |
+
return true;
|
403 |
+
}
|
404 |
+
}
|
includes/aws/GuzzleHttp/Exception/BadResponseException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Exception when an HTTP error occurs (4xx or 5xx error)
|
6 |
+
*/
|
7 |
+
class BadResponseException extends RequestException {}
|
includes/aws/GuzzleHttp/Exception/ClientException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Exception when a client error is encountered (4xx codes)
|
6 |
+
*/
|
7 |
+
class ClientException extends BadResponseException {}
|
includes/aws/GuzzleHttp/Exception/ConnectException.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Exception thrown when a connection cannot be established.
|
8 |
+
*
|
9 |
+
* Note that no response is present for a ConnectException
|
10 |
+
*/
|
11 |
+
class ConnectException extends RequestException
|
12 |
+
{
|
13 |
+
public function __construct(
|
14 |
+
$message,
|
15 |
+
RequestInterface $request,
|
16 |
+
\Exception $previous = null,
|
17 |
+
array $handlerContext = []
|
18 |
+
) {
|
19 |
+
parent::__construct($message, $request, null, $previous, $handlerContext);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @return null
|
24 |
+
*/
|
25 |
+
public function getResponse()
|
26 |
+
{
|
27 |
+
return null;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return bool
|
32 |
+
*/
|
33 |
+
public function hasResponse()
|
34 |
+
{
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
}
|
includes/aws/GuzzleHttp/Exception/GuzzleException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
interface GuzzleException {}
|
includes/aws/GuzzleHttp/Exception/RequestException.php
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* HTTP Request exception
|
10 |
+
*/
|
11 |
+
class RequestException extends TransferException
|
12 |
+
{
|
13 |
+
/** @var RequestInterface */
|
14 |
+
private $request;
|
15 |
+
|
16 |
+
/** @var ResponseInterface */
|
17 |
+
private $response;
|
18 |
+
|
19 |
+
/** @var array */
|
20 |
+
private $handlerContext;
|
21 |
+
|
22 |
+
public function __construct(
|
23 |
+
$message,
|
24 |
+
RequestInterface $request,
|
25 |
+
ResponseInterface $response = null,
|
26 |
+
\Exception $previous = null,
|
27 |
+
array $handlerContext = []
|
28 |
+
) {
|
29 |
+
// Set the code of the exception if the response is set and not future.
|
30 |
+
$code = $response && !($response instanceof PromiseInterface)
|
31 |
+
? $response->getStatusCode()
|
32 |
+
: 0;
|
33 |
+
parent::__construct($message, $code, $previous);
|
34 |
+
$this->request = $request;
|
35 |
+
$this->response = $response;
|
36 |
+
$this->handlerContext = $handlerContext;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Wrap non-RequestExceptions with a RequestException
|
41 |
+
*
|
42 |
+
* @param RequestInterface $request
|
43 |
+
* @param \Exception $e
|
44 |
+
*
|
45 |
+
* @return RequestException
|
46 |
+
*/
|
47 |
+
public static function wrapException(RequestInterface $request, \Exception $e)
|
48 |
+
{
|
49 |
+
return $e instanceof RequestException
|
50 |
+
? $e
|
51 |
+
: new RequestException($e->getMessage(), $request, null, $e);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Factory method to create a new exception with a normalized error message
|
56 |
+
*
|
57 |
+
* @param RequestInterface $request Request
|
58 |
+
* @param ResponseInterface $response Response received
|
59 |
+
* @param \Exception $previous Previous exception
|
60 |
+
* @param array $ctx Optional handler context.
|
61 |
+
*
|
62 |
+
* @return self
|
63 |
+
*/
|
64 |
+
public static function create(
|
65 |
+
RequestInterface $request,
|
66 |
+
ResponseInterface $response = null,
|
67 |
+
\Exception $previous = null,
|
68 |
+
array $ctx = []
|
69 |
+
) {
|
70 |
+
if (!$response) {
|
71 |
+
return new self(
|
72 |
+
'Error completing request',
|
73 |
+
$request,
|
74 |
+
null,
|
75 |
+
$previous,
|
76 |
+
$ctx
|
77 |
+
);
|
78 |
+
}
|
79 |
+
|
80 |
+
$level = floor($response->getStatusCode() / 100);
|
81 |
+
if ($level == '4') {
|
82 |
+
$label = 'Client error';
|
83 |
+
$className = __NAMESPACE__ . '\\ClientException';
|
84 |
+
} elseif ($level == '5') {
|
85 |
+
$label = 'Server error';
|
86 |
+
$className = __NAMESPACE__ . '\\ServerException';
|
87 |
+
} else {
|
88 |
+
$label = 'Unsuccessful request';
|
89 |
+
$className = __CLASS__;
|
90 |
+
}
|
91 |
+
|
92 |
+
// Server Error: `GET /` resulted in a `404 Not Found` response:
|
93 |
+
// <html> ... (truncated)
|
94 |
+
$message = sprintf(
|
95 |
+
'%s: `%s` resulted in a `%s` response',
|
96 |
+
$label,
|
97 |
+
$request->getMethod() . ' ' . $request->getUri(),
|
98 |
+
$response->getStatusCode() . ' ' . $response->getReasonPhrase()
|
99 |
+
);
|
100 |
+
|
101 |
+
$summary = static::getResponseBodySummary($response);
|
102 |
+
|
103 |
+
if ($summary !== null) {
|
104 |
+
$message .= ":\n{$summary}\n";
|
105 |
+
}
|
106 |
+
|
107 |
+
return new $className($message, $request, $response, $previous, $ctx);
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get a short summary of the response
|
112 |
+
*
|
113 |
+
* Will return `null` if the response is not printable.
|
114 |
+
*
|
115 |
+
* @param ResponseInterface $response
|
116 |
+
*
|
117 |
+
* @return string|null
|
118 |
+
*/
|
119 |
+
public static function getResponseBodySummary(ResponseInterface $response)
|
120 |
+
{
|
121 |
+
$body = $response->getBody();
|
122 |
+
|
123 |
+
if (!$body->isSeekable()) {
|
124 |
+
return null;
|
125 |
+
}
|
126 |
+
|
127 |
+
$size = $body->getSize();
|
128 |
+
$summary = $body->read(120);
|
129 |
+
$body->rewind();
|
130 |
+
|
131 |
+
if ($size > 120) {
|
132 |
+
$summary .= ' (truncated...)';
|
133 |
+
}
|
134 |
+
|
135 |
+
// Matches any printable character, including unicode characters:
|
136 |
+
// letters, marks, numbers, punctuation, spacing, and separators.
|
137 |
+
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
|
138 |
+
return null;
|
139 |
+
}
|
140 |
+
|
141 |
+
return $summary;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Get the request that caused the exception
|
146 |
+
*
|
147 |
+
* @return RequestInterface
|
148 |
+
*/
|
149 |
+
public function getRequest()
|
150 |
+
{
|
151 |
+
return $this->request;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Get the associated response
|
156 |
+
*
|
157 |
+
* @return ResponseInterface|null
|
158 |
+
*/
|
159 |
+
public function getResponse()
|
160 |
+
{
|
161 |
+
return $this->response;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Check if a response was received
|
166 |
+
*
|
167 |
+
* @return bool
|
168 |
+
*/
|
169 |
+
public function hasResponse()
|
170 |
+
{
|
171 |
+
return $this->response !== null;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Get contextual information about the error from the underlying handler.
|
176 |
+
*
|
177 |
+
* The contents of this array will vary depending on which handler you are
|
178 |
+
* using. It may also be just an empty array. Relying on this data will
|
179 |
+
* couple you to a specific handler, but can give more debug information
|
180 |
+
* when needed.
|
181 |
+
*
|
182 |
+
* @return array
|
183 |
+
*/
|
184 |
+
public function getHandlerContext()
|
185 |
+
{
|
186 |
+
return $this->handlerContext;
|
187 |
+
}
|
188 |
+
}
|
includes/aws/GuzzleHttp/Exception/SeekException.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
use Psr\Http\Message\StreamInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Exception thrown when a seek fails on a stream.
|
8 |
+
*/
|
9 |
+
class SeekException extends \RuntimeException implements GuzzleException
|
10 |
+
{
|
11 |
+
private $stream;
|
12 |
+
|
13 |
+
public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
|
14 |
+
{
|
15 |
+
$this->stream = $stream;
|
16 |
+
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
|
17 |
+
parent::__construct($msg);
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @return StreamInterface
|
22 |
+
*/
|
23 |
+
public function getStream()
|
24 |
+
{
|
25 |
+
return $this->stream;
|
26 |
+
}
|
27 |
+
}
|
includes/aws/GuzzleHttp/Exception/ServerException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Exception when a server error is encountered (5xx codes)
|
6 |
+
*/
|
7 |
+
class ServerException extends BadResponseException {}
|
includes/aws/GuzzleHttp/Exception/TooManyRedirectsException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
class TooManyRedirectsException extends RequestException {}
|
includes/aws/GuzzleHttp/Exception/TransferException.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
class TransferException extends \RuntimeException implements GuzzleException {}
|
includes/aws/GuzzleHttp/Handler/CurlFactory.php
ADDED
@@ -0,0 +1,531 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\Exception\ConnectException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\Psr7\LazyOpenStream;
|
10 |
+
use GuzzleHttp\TransferStats;
|
11 |
+
use Psr\Http\Message\RequestInterface;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Creates curl resources from a request
|
15 |
+
*/
|
16 |
+
class CurlFactory implements CurlFactoryInterface
|
17 |
+
{
|
18 |
+
/** @var array */
|
19 |
+
private $handles;
|
20 |
+
|
21 |
+
/** @var int Total number of idle handles to keep in cache */
|
22 |
+
private $maxHandles;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param int $maxHandles Maximum number of idle handles.
|
26 |
+
*/
|
27 |
+
public function __construct($maxHandles)
|
28 |
+
{
|
29 |
+
$this->maxHandles = $maxHandles;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function create(RequestInterface $request, array $options)
|
33 |
+
{
|
34 |
+
if (isset($options['curl']['body_as_string'])) {
|
35 |
+
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
36 |
+
unset($options['curl']['body_as_string']);
|
37 |
+
}
|
38 |
+
|
39 |
+
$easy = new EasyHandle;
|
40 |
+
$easy->request = $request;
|
41 |
+
$easy->options = $options;
|
42 |
+
$conf = $this->getDefaultConf($easy);
|
43 |
+
$this->applyMethod($easy, $conf);
|
44 |
+
$this->applyHandlerOptions($easy, $conf);
|
45 |
+
$this->applyHeaders($easy, $conf);
|
46 |
+
unset($conf['_headers']);
|
47 |
+
|
48 |
+
// Add handler options from the request configuration options
|
49 |
+
if (isset($options['curl'])) {
|
50 |
+
$conf = array_replace($conf, $options['curl']);
|
51 |
+
}
|
52 |
+
|
53 |
+
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
|
54 |
+
$easy->handle = $this->handles
|
55 |
+
? array_pop($this->handles)
|
56 |
+
: curl_init();
|
57 |
+
curl_setopt_array($easy->handle, $conf);
|
58 |
+
|
59 |
+
return $easy;
|
60 |
+
}
|
61 |
+
|
62 |
+
public function release(EasyHandle $easy)
|
63 |
+
{
|
64 |
+
$resource = $easy->handle;
|
65 |
+
unset($easy->handle);
|
66 |
+
|
67 |
+
if (count($this->handles) >= $this->maxHandles) {
|
68 |
+
curl_close($resource);
|
69 |
+
} else {
|
70 |
+
// Remove all callback functions as they can hold onto references
|
71 |
+
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
72 |
+
// does not work for some reason, so removing each one
|
73 |
+
// individually.
|
74 |
+
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
|
75 |
+
curl_setopt($resource, CURLOPT_READFUNCTION, null);
|
76 |
+
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
|
77 |
+
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
|
78 |
+
curl_reset($resource);
|
79 |
+
$this->handles[] = $resource;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Completes a cURL transaction, either returning a response promise or a
|
85 |
+
* rejected promise.
|
86 |
+
*
|
87 |
+
* @param callable $handler
|
88 |
+
* @param EasyHandle $easy
|
89 |
+
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
90 |
+
*
|
91 |
+
* @return \GuzzleHttp\Promise\PromiseInterface
|
92 |
+
*/
|
93 |
+
public static function finish(
|
94 |
+
callable $handler,
|
95 |
+
EasyHandle $easy,
|
96 |
+
CurlFactoryInterface $factory
|
97 |
+
) {
|
98 |
+
if (isset($easy->options['on_stats'])) {
|
99 |
+
self::invokeStats($easy);
|
100 |
+
}
|
101 |
+
|
102 |
+
if (!$easy->response || $easy->errno) {
|
103 |
+
return self::finishError($handler, $easy, $factory);
|
104 |
+
}
|
105 |
+
|
106 |
+
// Return the response if it is present and there is no error.
|
107 |
+
$factory->release($easy);
|
108 |
+
|
109 |
+
// Rewind the body of the response if possible.
|
110 |
+
$body = $easy->response->getBody();
|
111 |
+
if ($body->isSeekable()) {
|
112 |
+
$body->rewind();
|
113 |
+
}
|
114 |
+
|
115 |
+
return new FulfilledPromise($easy->response);
|
116 |
+
}
|
117 |
+
|
118 |
+
private static function invokeStats(EasyHandle $easy)
|
119 |
+
{
|
120 |
+
$curlStats = curl_getinfo($easy->handle);
|
121 |
+
$stats = new TransferStats(
|
122 |
+
$easy->request,
|
123 |
+
$easy->response,
|
124 |
+
$curlStats['total_time'],
|
125 |
+
$easy->errno,
|
126 |
+
$curlStats
|
127 |
+
);
|
128 |
+
call_user_func($easy->options['on_stats'], $stats);
|
129 |
+
}
|
130 |
+
|
131 |
+
private static function finishError(
|
132 |
+
callable $handler,
|
133 |
+
EasyHandle $easy,
|
134 |
+
CurlFactoryInterface $factory
|
135 |
+
) {
|
136 |
+
// Get error information and release the handle to the factory.
|
137 |
+
$ctx = [
|
138 |
+
'errno' => $easy->errno,
|
139 |
+
'error' => curl_error($easy->handle),
|
140 |
+
] + curl_getinfo($easy->handle);
|
141 |
+
$factory->release($easy);
|
142 |
+
|
143 |
+
// Retry when nothing is present or when curl failed to rewind.
|
144 |
+
if (empty($easy->options['_err_message'])
|
145 |
+
&& (!$easy->errno || $easy->errno == 65)
|
146 |
+
) {
|
147 |
+
return self::retryFailedRewind($handler, $easy, $ctx);
|
148 |
+
}
|
149 |
+
|
150 |
+
return self::createRejection($easy, $ctx);
|
151 |
+
}
|
152 |
+
|
153 |
+
private static function createRejection(EasyHandle $easy, array $ctx)
|
154 |
+
{
|
155 |
+
static $connectionErrors = [
|
156 |
+
CURLE_OPERATION_TIMEOUTED => true,
|
157 |
+
CURLE_COULDNT_RESOLVE_HOST => true,
|
158 |
+
CURLE_COULDNT_CONNECT => true,
|
159 |
+
CURLE_SSL_CONNECT_ERROR => true,
|
160 |
+
CURLE_GOT_NOTHING => true,
|
161 |
+
];
|
162 |
+
|
163 |
+
// If an exception was encountered during the onHeaders event, then
|
164 |
+
// return a rejected promise that wraps that exception.
|
165 |
+
if ($easy->onHeadersException) {
|
166 |
+
return new RejectedPromise(
|
167 |
+
new RequestException(
|
168 |
+
'An error was encountered during the on_headers event',
|
169 |
+
$easy->request,
|
170 |
+
$easy->response,
|
171 |
+
$easy->onHeadersException,
|
172 |
+
$ctx
|
173 |
+
)
|
174 |
+
);
|
175 |
+
}
|
176 |
+
|
177 |
+
$message = sprintf(
|
178 |
+
'cURL error %s: %s (%s)',
|
179 |
+
$ctx['errno'],
|
180 |
+
$ctx['error'],
|
181 |
+
'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
182 |
+
);
|
183 |
+
|
184 |
+
// Create a connection exception if it was a specific error code.
|
185 |
+
$error = isset($connectionErrors[$easy->errno])
|
186 |
+
? new ConnectException($message, $easy->request, null, $ctx)
|
187 |
+
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
188 |
+
|
189 |
+
return new RejectedPromise($error);
|
190 |
+
}
|
191 |
+
|
192 |
+
private function getDefaultConf(EasyHandle $easy)
|
193 |
+
{
|
194 |
+
$conf = [
|
195 |
+
'_headers' => $easy->request->getHeaders(),
|
196 |
+
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
197 |
+
CURLOPT_URL => (string) $easy->request->getUri(),
|
198 |
+
CURLOPT_RETURNTRANSFER => false,
|
199 |
+
CURLOPT_HEADER => false,
|
200 |
+
CURLOPT_CONNECTTIMEOUT => 150,
|
201 |
+
];
|
202 |
+
|
203 |
+
if (defined('CURLOPT_PROTOCOLS')) {
|
204 |
+
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
205 |
+
}
|
206 |
+
|
207 |
+
$version = $easy->request->getProtocolVersion();
|
208 |
+
if ($version == 1.1) {
|
209 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
210 |
+
} elseif ($version == 2.0) {
|
211 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
212 |
+
} else {
|
213 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
214 |
+
}
|
215 |
+
|
216 |
+
return $conf;
|
217 |
+
}
|
218 |
+
|
219 |
+
private function applyMethod(EasyHandle $easy, array &$conf)
|
220 |
+
{
|
221 |
+
$body = $easy->request->getBody();
|
222 |
+
$size = $body->getSize();
|
223 |
+
|
224 |
+
if ($size === null || $size > 0) {
|
225 |
+
$this->applyBody($easy->request, $easy->options, $conf);
|
226 |
+
return;
|
227 |
+
}
|
228 |
+
|
229 |
+
$method = $easy->request->getMethod();
|
230 |
+
if ($method === 'PUT' || $method === 'POST') {
|
231 |
+
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
232 |
+
if (!$easy->request->hasHeader('Content-Length')) {
|
233 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
234 |
+
}
|
235 |
+
} elseif ($method === 'HEAD') {
|
236 |
+
$conf[CURLOPT_NOBODY] = true;
|
237 |
+
unset(
|
238 |
+
$conf[CURLOPT_WRITEFUNCTION],
|
239 |
+
$conf[CURLOPT_READFUNCTION],
|
240 |
+
$conf[CURLOPT_FILE],
|
241 |
+
$conf[CURLOPT_INFILE]
|
242 |
+
);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
private function applyBody(RequestInterface $request, array $options, array &$conf)
|
247 |
+
{
|
248 |
+
$size = $request->hasHeader('Content-Length')
|
249 |
+
? (int) $request->getHeaderLine('Content-Length')
|
250 |
+
: null;
|
251 |
+
|
252 |
+
// Send the body as a string if the size is less than 1MB OR if the
|
253 |
+
// [curl][body_as_string] request value is set.
|
254 |
+
if (($size !== null && $size < 1000000) ||
|
255 |
+
!empty($options['_body_as_string'])
|
256 |
+
) {
|
257 |
+
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
258 |
+
// Don't duplicate the Content-Length header
|
259 |
+
$this->removeHeader('Content-Length', $conf);
|
260 |
+
$this->removeHeader('Transfer-Encoding', $conf);
|
261 |
+
} else {
|
262 |
+
$conf[CURLOPT_UPLOAD] = true;
|
263 |
+
if ($size !== null) {
|
264 |
+
$conf[CURLOPT_INFILESIZE] = $size;
|
265 |
+
$this->removeHeader('Content-Length', $conf);
|
266 |
+
}
|
267 |
+
$body = $request->getBody();
|
268 |
+
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
269 |
+
return $body->read($length);
|
270 |
+
};
|
271 |
+
}
|
272 |
+
|
273 |
+
// If the Expect header is not present, prevent curl from adding it
|
274 |
+
if (!$request->hasHeader('Expect')) {
|
275 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Expect:';
|
276 |
+
}
|
277 |
+
|
278 |
+
// cURL sometimes adds a content-type by default. Prevent this.
|
279 |
+
if (!$request->hasHeader('Content-Type')) {
|
280 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
private function applyHeaders(EasyHandle $easy, array &$conf)
|
285 |
+
{
|
286 |
+
foreach ($conf['_headers'] as $name => $values) {
|
287 |
+
foreach ($values as $value) {
|
288 |
+
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
289 |
+
}
|
290 |
+
}
|
291 |
+
|
292 |
+
// Remove the Accept header if one was not set
|
293 |
+
if (!$easy->request->hasHeader('Accept')) {
|
294 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept:';
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Remove a header from the options array.
|
300 |
+
*
|
301 |
+
* @param string $name Case-insensitive header to remove
|
302 |
+
* @param array $options Array of options to modify
|
303 |
+
*/
|
304 |
+
private function removeHeader($name, array &$options)
|
305 |
+
{
|
306 |
+
foreach (array_keys($options['_headers']) as $key) {
|
307 |
+
if (!strcasecmp($key, $name)) {
|
308 |
+
unset($options['_headers'][$key]);
|
309 |
+
return;
|
310 |
+
}
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
private function applyHandlerOptions(EasyHandle $easy, array &$conf)
|
315 |
+
{
|
316 |
+
$options = $easy->options;
|
317 |
+
if (isset($options['verify'])) {
|
318 |
+
if ($options['verify'] === false) {
|
319 |
+
unset($conf[CURLOPT_CAINFO]);
|
320 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
|
321 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = false;
|
322 |
+
} else {
|
323 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
324 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
325 |
+
if (is_string($options['verify'])) {
|
326 |
+
$conf[CURLOPT_CAINFO] = $options['verify'];
|
327 |
+
if (!file_exists($options['verify'])) {
|
328 |
+
throw new \InvalidArgumentException(
|
329 |
+
"SSL CA bundle not found: {$options['verify']}"
|
330 |
+
);
|
331 |
+
}
|
332 |
+
}
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
if (!empty($options['decode_content'])) {
|
337 |
+
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
338 |
+
if ($accept) {
|
339 |
+
$conf[CURLOPT_ENCODING] = $accept;
|
340 |
+
} else {
|
341 |
+
$conf[CURLOPT_ENCODING] = '';
|
342 |
+
// Don't let curl send the header over the wire
|
343 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
if (isset($options['sink'])) {
|
348 |
+
$sink = $options['sink'];
|
349 |
+
if (!is_string($sink)) {
|
350 |
+
$sink = \GuzzleHttp\Psr7\stream_for($sink);
|
351 |
+
} elseif (!is_dir(dirname($sink))) {
|
352 |
+
// Ensure that the directory exists before failing in curl.
|
353 |
+
throw new \RuntimeException(sprintf(
|
354 |
+
'Directory %s does not exist for sink value of %s',
|
355 |
+
dirname($sink),
|
356 |
+
$sink
|
357 |
+
));
|
358 |
+
} else {
|
359 |
+
$sink = new LazyOpenStream($sink, 'w+');
|
360 |
+
}
|
361 |
+
$easy->sink = $sink;
|
362 |
+
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
|
363 |
+
return $sink->write($write);
|
364 |
+
};
|
365 |
+
} else {
|
366 |
+
// Use a default temp stream if no sink was set.
|
367 |
+
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
368 |
+
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
369 |
+
}
|
370 |
+
|
371 |
+
if (isset($options['timeout'])) {
|
372 |
+
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
373 |
+
}
|
374 |
+
|
375 |
+
if (isset($options['connect_timeout'])) {
|
376 |
+
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
377 |
+
}
|
378 |
+
|
379 |
+
if (isset($options['proxy'])) {
|
380 |
+
if (!is_array($options['proxy'])) {
|
381 |
+
$conf[CURLOPT_PROXY] = $options['proxy'];
|
382 |
+
} else {
|
383 |
+
$scheme = $easy->request->getUri()->getScheme();
|
384 |
+
if (isset($options['proxy'][$scheme])) {
|
385 |
+
$host = $easy->request->getUri()->getHost();
|
386 |
+
if (!isset($options['proxy']['no']) ||
|
387 |
+
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
|
388 |
+
) {
|
389 |
+
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
}
|
394 |
+
|
395 |
+
if (isset($options['cert'])) {
|
396 |
+
$cert = $options['cert'];
|
397 |
+
if (is_array($cert)) {
|
398 |
+
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
399 |
+
$cert = $cert[0];
|
400 |
+
}
|
401 |
+
if (!file_exists($cert)) {
|
402 |
+
throw new \InvalidArgumentException(
|
403 |
+
"SSL certificate not found: {$cert}"
|
404 |
+
);
|
405 |
+
}
|
406 |
+
$conf[CURLOPT_SSLCERT] = $cert;
|
407 |
+
}
|
408 |
+
|
409 |
+
if (isset($options['ssl_key'])) {
|
410 |
+
$sslKey = $options['ssl_key'];
|
411 |
+
if (is_array($sslKey)) {
|
412 |
+
$conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
|
413 |
+
$sslKey = $sslKey[0];
|
414 |
+
}
|
415 |
+
if (!file_exists($sslKey)) {
|
416 |
+
throw new \InvalidArgumentException(
|
417 |
+
"SSL private key not found: {$sslKey}"
|
418 |
+
);
|
419 |
+
}
|
420 |
+
$conf[CURLOPT_SSLKEY] = $sslKey;
|
421 |
+
}
|
422 |
+
|
423 |
+
if (isset($options['progress'])) {
|
424 |
+
$progress = $options['progress'];
|
425 |
+
if (!is_callable($progress)) {
|
426 |
+
throw new \InvalidArgumentException(
|
427 |
+
'progress client option must be callable'
|
428 |
+
);
|
429 |
+
}
|
430 |
+
$conf[CURLOPT_NOPROGRESS] = false;
|
431 |
+
$conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
|
432 |
+
$args = func_get_args();
|
433 |
+
// PHP 5.5 pushed the handle onto the start of the args
|
434 |
+
if (is_resource($args[0])) {
|
435 |
+
array_shift($args);
|
436 |
+
}
|
437 |
+
call_user_func_array($progress, $args);
|
438 |
+
};
|
439 |
+
}
|
440 |
+
|
441 |
+
if (!empty($options['debug'])) {
|
442 |
+
$conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
|
443 |
+
$conf[CURLOPT_VERBOSE] = true;
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* This function ensures that a response was set on a transaction. If one
|
449 |
+
* was not set, then the request is retried if possible. This error
|
450 |
+
* typically means you are sending a payload, curl encountered a
|
451 |
+
* "Connection died, retrying a fresh connect" error, tried to rewind the
|
452 |
+
* stream, and then encountered a "necessary data rewind wasn't possible"
|
453 |
+
* error, causing the request to be sent through curl_multi_info_read()
|
454 |
+
* without an error status.
|
455 |
+
*/
|
456 |
+
private static function retryFailedRewind(
|
457 |
+
callable $handler,
|
458 |
+
EasyHandle $easy,
|
459 |
+
array $ctx
|
460 |
+
) {
|
461 |
+
try {
|
462 |
+
// Only rewind if the body has been read from.
|
463 |
+
$body = $easy->request->getBody();
|
464 |
+
if ($body->tell() > 0) {
|
465 |
+
$body->rewind();
|
466 |
+
}
|
467 |
+
} catch (\RuntimeException $e) {
|
468 |
+
$ctx['error'] = 'The connection unexpectedly failed without '
|
469 |
+
. 'providing an error. The request would have been retried, '
|
470 |
+
. 'but attempting to rewind the request body failed. '
|
471 |
+
. 'Exception: ' . $e;
|
472 |
+
return self::createRejection($easy, $ctx);
|
473 |
+
}
|
474 |
+
|
475 |
+
// Retry no more than 3 times before giving up.
|
476 |
+
if (!isset($easy->options['_curl_retries'])) {
|
477 |
+
$easy->options['_curl_retries'] = 1;
|
478 |
+
} elseif ($easy->options['_curl_retries'] == 2) {
|
479 |
+
$ctx['error'] = 'The cURL request was retried 3 times '
|
480 |
+
. 'and did not succeed. The most likely reason for the failure '
|
481 |
+
. 'is that cURL was unable to rewind the body of the request '
|
482 |
+
. 'and subsequent retries resulted in the same error. Turn on '
|
483 |
+
. 'the debug option to see what went wrong. See '
|
484 |
+
. 'https://bugs.php.net/bug.php?id=47204 for more information.';
|
485 |
+
return self::createRejection($easy, $ctx);
|
486 |
+
} else {
|
487 |
+
$easy->options['_curl_retries']++;
|
488 |
+
}
|
489 |
+
|
490 |
+
return $handler($easy->request, $easy->options);
|
491 |
+
}
|
492 |
+
|
493 |
+
private function createHeaderFn(EasyHandle $easy)
|
494 |
+
{
|
495 |
+
if (!isset($easy->options['on_headers'])) {
|
496 |
+
$onHeaders = null;
|
497 |
+
} elseif (!is_callable($easy->options['on_headers'])) {
|
498 |
+
throw new \InvalidArgumentException('on_headers must be callable');
|
499 |
+
} else {
|
500 |
+
$onHeaders = $easy->options['on_headers'];
|
501 |
+
}
|
502 |
+
|
503 |
+
return function ($ch, $h) use (
|
504 |
+
$onHeaders,
|
505 |
+
$easy,
|
506 |
+
&$startingResponse
|
507 |
+
) {
|
508 |
+
$value = trim($h);
|
509 |
+
if ($value === '') {
|
510 |
+
$startingResponse = true;
|
511 |
+
$easy->createResponse();
|
512 |
+
if ($onHeaders) {
|
513 |
+
try {
|
514 |
+
$onHeaders($easy->response);
|
515 |
+
} catch (\Exception $e) {
|
516 |
+
// Associate the exception with the handle and trigger
|
517 |
+
// a curl header write error by returning 0.
|
518 |
+
$easy->onHeadersException = $e;
|
519 |
+
return -1;
|
520 |
+
}
|
521 |
+
}
|
522 |
+
} elseif ($startingResponse) {
|
523 |
+
$startingResponse = false;
|
524 |
+
$easy->headers = [$value];
|
525 |
+
} else {
|
526 |
+
$easy->headers[] = $value;
|
527 |
+
}
|
528 |
+
return strlen($h);
|
529 |
+
};
|
530 |
+
}
|
531 |
+
}
|
includes/aws/GuzzleHttp/Handler/CurlFactoryInterface.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
|
6 |
+
interface CurlFactoryInterface
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Creates a cURL handle resource.
|
10 |
+
*
|
11 |
+
* @param RequestInterface $request Request
|
12 |
+
* @param array $options Transfer options
|
13 |
+
*
|
14 |
+
* @return EasyHandle
|
15 |
+
* @throws \RuntimeException when an option cannot be applied
|
16 |
+
*/
|
17 |
+
public function create(RequestInterface $request, array $options);
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Release an easy handle, allowing it to be reused or closed.
|
21 |
+
*
|
22 |
+
* This function must call unset on the easy handle's "handle" property.
|
23 |
+
*
|
24 |
+
* @param EasyHandle $easy
|
25 |
+
*/
|
26 |
+
public function release(EasyHandle $easy);
|
27 |
+
}
|
includes/aws/GuzzleHttp/Handler/CurlHandler.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Psr7;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* HTTP handler that uses cURL easy handles as a transport layer.
|
9 |
+
*
|
10 |
+
* When using the CurlHandler, custom curl options can be specified as an
|
11 |
+
* associative array of curl option constants mapping to values in the
|
12 |
+
* **curl** key of the "client" key of the request.
|
13 |
+
*/
|
14 |
+
class CurlHandler
|
15 |
+
{
|
16 |
+
/** @var CurlFactoryInterface */
|
17 |
+
private $factory;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Accepts an associative array of options:
|
21 |
+
*
|
22 |
+
* - factory: Optional curl factory used to create cURL handles.
|
23 |
+
*
|
24 |
+
* @param array $options Array of options to use with the handler
|
25 |
+
*/
|
26 |
+
public function __construct(array $options = [])
|
27 |
+
{
|
28 |
+
$this->factory = isset($options['handle_factory'])
|
29 |
+
? $options['handle_factory']
|
30 |
+
: new CurlFactory(3);
|
31 |
+
}
|
32 |
+
|
33 |
+
public function __invoke(RequestInterface $request, array $options)
|
34 |
+
{
|
35 |
+
if (isset($options['delay'])) {
|
36 |
+
usleep($options['delay'] * 1000);
|
37 |
+
}
|
38 |
+
|
39 |
+
$easy = $this->factory->create($request, $options);
|
40 |
+
curl_exec($easy->handle);
|
41 |
+
$easy->errno = curl_errno($easy->handle);
|
42 |
+
|
43 |
+
return CurlFactory::finish($this, $easy, $this->factory);
|
44 |
+
}
|
45 |
+
}
|
includes/aws/GuzzleHttp/Handler/CurlMultiHandler.php
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise as P;
|
5 |
+
use GuzzleHttp\Promise\Promise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Returns an asynchronous response using curl_multi_* functions.
|
11 |
+
*
|
12 |
+
* When using the CurlMultiHandler, custom curl options can be specified as an
|
13 |
+
* associative array of curl option constants mapping to values in the
|
14 |
+
* **curl** key of the provided request options.
|
15 |
+
*
|
16 |
+
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
17 |
+
*/
|
18 |
+
class CurlMultiHandler
|
19 |
+
{
|
20 |
+
/** @var CurlFactoryInterface */
|
21 |
+
private $factory;
|
22 |
+
private $selectTimeout;
|
23 |
+
private $active;
|
24 |
+
private $handles = [];
|
25 |
+
private $delays = [];
|
26 |
+
|
27 |
+
/**
|
28 |
+
* This handler accepts the following options:
|
29 |
+
*
|
30 |
+
* - handle_factory: An optional factory used to create curl handles
|
31 |
+
* - select_timeout: Optional timeout (in seconds) to block before timing
|
32 |
+
* out while selecting curl handles. Defaults to 1 second.
|
33 |
+
*
|
34 |
+
* @param array $options
|
35 |
+
*/
|
36 |
+
public function __construct(array $options = [])
|
37 |
+
{
|
38 |
+
$this->factory = isset($options['handle_factory'])
|
39 |
+
? $options['handle_factory'] : new CurlFactory(50);
|
40 |
+
$this->selectTimeout = isset($options['select_timeout'])
|
41 |
+
? $options['select_timeout'] : 1;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function __get($name)
|
45 |
+
{
|
46 |
+
if ($name === '_mh') {
|
47 |
+
return $this->_mh = curl_multi_init();
|
48 |
+
}
|
49 |
+
|
50 |
+
throw new \BadMethodCallException();
|
51 |
+
}
|
52 |
+
|
53 |
+
public function __destruct()
|
54 |
+
{
|
55 |
+
if (isset($this->_mh)) {
|
56 |
+
curl_multi_close($this->_mh);
|
57 |
+
unset($this->_mh);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function __invoke(RequestInterface $request, array $options)
|
62 |
+
{
|
63 |
+
$easy = $this->factory->create($request, $options);
|
64 |
+
$id = (int) $easy->handle;
|
65 |
+
|
66 |
+
$promise = new Promise(
|
67 |
+
[$this, 'execute'],
|
68 |
+
function () use ($id) { return $this->cancel($id); }
|
69 |
+
);
|
70 |
+
|
71 |
+
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
72 |
+
|
73 |
+
return $promise;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Ticks the curl event loop.
|
78 |
+
*/
|
79 |
+
public function tick()
|
80 |
+
{
|
81 |
+
// Add any delayed handles if needed.
|
82 |
+
if ($this->delays) {
|
83 |
+
$currentTime = microtime(true);
|
84 |
+
foreach ($this->delays as $id => $delay) {
|
85 |
+
if ($currentTime >= $delay) {
|
86 |
+
unset($this->delays[$id]);
|
87 |
+
curl_multi_add_handle(
|
88 |
+
$this->_mh,
|
89 |
+
$this->handles[$id]['easy']->handle
|
90 |
+
);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
// Step through the task queue which may add additional requests.
|
96 |
+
P\queue()->run();
|
97 |
+
|
98 |
+
if ($this->active &&
|
99 |
+
curl_multi_select($this->_mh, $this->selectTimeout) === -1
|
100 |
+
) {
|
101 |
+
// Perform a usleep if a select returns -1.
|
102 |
+
// See: https://bugs.php.net/bug.php?id=61141
|
103 |
+
usleep(250);
|
104 |
+
}
|
105 |
+
|
106 |
+
while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
|
107 |
+
|
108 |
+
$this->processMessages();
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Runs until all outstanding connections have completed.
|
113 |
+
*/
|
114 |
+
public function execute()
|
115 |
+
{
|
116 |
+
$queue = P\queue();
|
117 |
+
|
118 |
+
while ($this->handles || !$queue->isEmpty()) {
|
119 |
+
// If there are no transfers, then sleep for the next delay
|
120 |
+
if (!$this->active && $this->delays) {
|
121 |
+
usleep($this->timeToNext());
|
122 |
+
}
|
123 |
+
$this->tick();
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
private function addRequest(array $entry)
|
128 |
+
{
|
129 |
+
$easy = $entry['easy'];
|
130 |
+
$id = (int) $easy->handle;
|
131 |
+
$this->handles[$id] = $entry;
|
132 |
+
if (empty($easy->options['delay'])) {
|
133 |
+
curl_multi_add_handle($this->_mh, $easy->handle);
|
134 |
+
} else {
|
135 |
+
$this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Cancels a handle from sending and removes references to it.
|
141 |
+
*
|
142 |
+
* @param int $id Handle ID to cancel and remove.
|
143 |
+
*
|
144 |
+
* @return bool True on success, false on failure.
|
145 |
+
*/
|
146 |
+
private function cancel($id)
|
147 |
+
{
|
148 |
+
// Cannot cancel if it has been processed.
|
149 |
+
if (!isset($this->handles[$id])) {
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
$handle = $this->handles[$id]['easy']->handle;
|
154 |
+
unset($this->delays[$id], $this->handles[$id]);
|
155 |
+
curl_multi_remove_handle($this->_mh, $handle);
|
156 |
+
curl_close($handle);
|
157 |
+
|
158 |
+
return true;
|
159 |
+
}
|
160 |
+
|
161 |
+
private function processMessages()
|
162 |
+
{
|
163 |
+
while ($done = curl_multi_info_read($this->_mh)) {
|
164 |
+
$id = (int) $done['handle'];
|
165 |
+
curl_multi_remove_handle($this->_mh, $done['handle']);
|
166 |
+
|
167 |
+
if (!isset($this->handles[$id])) {
|
168 |
+
// Probably was cancelled.
|
169 |
+
continue;
|
170 |
+
}
|
171 |
+
|
172 |
+
$entry = $this->handles[$id];
|
173 |
+
unset($this->handles[$id], $this->delays[$id]);
|
174 |
+
$entry['easy']->errno = $done['result'];
|
175 |
+
$entry['deferred']->resolve(
|
176 |
+
CurlFactory::finish(
|
177 |
+
$this,
|
178 |
+
$entry['easy'],
|
179 |
+
$this->factory
|
180 |
+
)
|
181 |
+
);
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
private function timeToNext()
|
186 |
+
{
|
187 |
+
$currentTime = microtime(true);
|
188 |
+
$nextTime = PHP_INT_MAX;
|
189 |
+
foreach ($this->delays as $time) {
|
190 |
+
if ($time < $nextTime) {
|
191 |
+
$nextTime = $time;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
return max(0, $currentTime - $nextTime);
|
196 |
+
}
|
197 |
+
}
|
includes/aws/GuzzleHttp/Handler/EasyHandle.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Psr7\Response;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
use Psr\Http\Message\StreamInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Represents a cURL easy handle and the data it populates.
|
11 |
+
*
|
12 |
+
* @internal
|
13 |
+
*/
|
14 |
+
final class EasyHandle
|
15 |
+
{
|
16 |
+
/** @var resource cURL resource */
|
17 |
+
public $handle;
|
18 |
+
|
19 |
+
/** @var StreamInterface Where data is being written */
|
20 |
+
public $sink;
|
21 |
+
|
22 |
+
/** @var array Received HTTP headers so far */
|
23 |
+
public $headers = [];
|
24 |
+
|
25 |
+
/** @var ResponseInterface Received response (if any) */
|
26 |
+
public $response;
|
27 |
+
|
28 |
+
/** @var RequestInterface Request being sent */
|
29 |
+
public $request;
|
30 |
+
|
31 |
+
/** @var array Request options */
|
32 |
+
public $options = [];
|
33 |
+
|
34 |
+
/** @var int cURL error number (if any) */
|
35 |
+
public $errno = 0;
|
36 |
+
|
37 |
+
/** @var \Exception Exception during on_headers (if any) */
|
38 |
+
public $onHeadersException;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Attach a response to the easy handle based on the received headers.
|
42 |
+
*
|
43 |
+
* @throws \RuntimeException if no headers have been received.
|
44 |
+
*/
|
45 |
+
public function createResponse()
|
46 |
+
{
|
47 |
+
if (empty($this->headers)) {
|
48 |
+
throw new \RuntimeException('No headers have been received');
|
49 |
+
}
|
50 |
+
|
51 |
+
// HTTP-version SP status-code SP reason-phrase
|
52 |
+
$startLine = explode(' ', array_shift($this->headers), 3);
|
53 |
+
$headers = \GuzzleHttp\headers_from_lines($this->headers);
|
54 |
+
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
55 |
+
|
56 |
+
if (!empty($this->options['decode_content'])
|
57 |
+
&& isset($normalizedKeys['content-encoding'])
|
58 |
+
) {
|
59 |
+
unset($headers[$normalizedKeys['content-encoding']]);
|
60 |
+
if (isset($normalizedKeys['content-length'])) {
|
61 |
+
$bodyLength = (int) $this->sink->getSize();
|
62 |
+
if ($bodyLength) {
|
63 |
+
$headers[$normalizedKeys['content-length']] = $bodyLength;
|
64 |
+
} else {
|
65 |
+
unset($headers[$normalizedKeys['content-length']]);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
// Attach a response to the easy handle with the parsed headers.
|
71 |
+
$this->response = new Response(
|
72 |
+
$startLine[1],
|
73 |
+
$headers,
|
74 |
+
$this->sink,
|
75 |
+
substr($startLine[0], 5),
|
76 |
+
isset($startLine[2]) ? (string) $startLine[2] : null
|
77 |
+
);
|
78 |
+
}
|
79 |
+
|
80 |
+
public function __get($name)
|
81 |
+
{
|
82 |
+
$msg = $name === 'handle'
|
83 |
+
? 'The EasyHandle has been released'
|
84 |
+
: 'Invalid property: ' . $name;
|
85 |
+
throw new \BadMethodCallException($msg);
|
86 |
+
}
|
87 |
+
}
|
includes/aws/GuzzleHttp/Handler/MockHandler.php
ADDED
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\HandlerStack;
|
5 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
6 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
7 |
+
use GuzzleHttp\TransferStats;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Handler that returns responses or throw exceptions from a queue.
|
13 |
+
*/
|
14 |
+
class MockHandler implements \Countable
|
15 |
+
{
|
16 |
+
private $queue;
|
17 |
+
private $lastRequest;
|
18 |
+
private $lastOptions;
|
19 |
+
private $onFulfilled;
|
20 |
+
private $onRejected;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Creates a new MockHandler that uses the default handler stack list of
|
24 |
+
* middlewares.
|
25 |
+
*
|
26 |
+
* @param array $queue Array of responses, callables, or exceptions.
|
27 |
+
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
28 |
+
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
29 |
+
*
|
30 |
+
* @return MockHandler
|
31 |
+
*/
|
32 |
+
public static function createWithMiddleware(
|
33 |
+
array $queue = null,
|
34 |
+
callable $onFulfilled = null,
|
35 |
+
callable $onRejected = null
|
36 |
+
) {
|
37 |
+
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The passed in value must be an array of
|
42 |
+
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
43 |
+
* callables, or Promises.
|
44 |
+
*
|
45 |
+
* @param array $queue
|
46 |
+
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
47 |
+
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
48 |
+
*/
|
49 |
+
public function __construct(
|
50 |
+
array $queue = null,
|
51 |
+
callable $onFulfilled = null,
|
52 |
+
callable $onRejected = null
|
53 |
+
) {
|
54 |
+
$this->onFulfilled = $onFulfilled;
|
55 |
+
$this->onRejected = $onRejected;
|
56 |
+
|
57 |
+
if ($queue) {
|
58 |
+
call_user_func_array([$this, 'append'], $queue);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
public function __invoke(RequestInterface $request, array $options)
|
63 |
+
{
|
64 |
+
if (!$this->queue) {
|
65 |
+
throw new \OutOfBoundsException('Mock queue is empty');
|
66 |
+
}
|
67 |
+
|
68 |
+
if (isset($options['delay'])) {
|
69 |
+
usleep($options['delay'] * 1000);
|
70 |
+
}
|
71 |
+
|
72 |
+
$this->lastRequest = $request;
|
73 |
+
$this->lastOptions = $options;
|
74 |
+
$response = array_shift($this->queue);
|
75 |
+
|
76 |
+
if (is_callable($response)) {
|
77 |
+
$response = $response($request, $options);
|
78 |
+
}
|
79 |
+
|
80 |
+
$response = $response instanceof \Exception
|
81 |
+
? new RejectedPromise($response)
|
82 |
+
: \GuzzleHttp\Promise\promise_for($response);
|
83 |
+
|
84 |
+
return $response->then(
|
85 |
+
function ($value) use ($request, $options) {
|
86 |
+
$this->invokeStats($request, $options, $value);
|
87 |
+
if ($this->onFulfilled) {
|
88 |
+
call_user_func($this->onFulfilled, $value);
|
89 |
+
}
|
90 |
+
if (isset($options['sink'])) {
|
91 |
+
$contents = (string) $value->getBody();
|
92 |
+
$sink = $options['sink'];
|
93 |
+
|
94 |
+
if (is_resource($sink)) {
|
95 |
+
fwrite($sink, $contents);
|
96 |
+
} elseif (is_string($sink)) {
|
97 |
+
file_put_contents($sink, $contents);
|
98 |
+
} elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
99 |
+
$sink->write($contents);
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
return $value;
|
104 |
+
},
|
105 |
+
function ($reason) use ($request, $options) {
|
106 |
+
$this->invokeStats($request, $options, null, $reason);
|
107 |
+
if ($this->onRejected) {
|
108 |
+
call_user_func($this->onRejected, $reason);
|
109 |
+
}
|
110 |
+
return new RejectedPromise($reason);
|
111 |
+
}
|
112 |
+
);
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Adds one or more variadic requests, exceptions, callables, or promises
|
117 |
+
* to the queue.
|
118 |
+
*/
|
119 |
+
public function append()
|
120 |
+
{
|
121 |
+
foreach (func_get_args() as $value) {
|
122 |
+
if ($value instanceof ResponseInterface
|
123 |
+
|| $value instanceof \Exception
|
124 |
+
|| $value instanceof PromiseInterface
|
125 |
+
|| is_callable($value)
|
126 |
+
) {
|
127 |
+
$this->queue[] = $value;
|
128 |
+
} else {
|
129 |
+
throw new \InvalidArgumentException('Expected a response or '
|
130 |
+
. 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Get the last received request.
|
137 |
+
*
|
138 |
+
* @return RequestInterface
|
139 |
+
*/
|
140 |
+
public function getLastRequest()
|
141 |
+
{
|
142 |
+
return $this->lastRequest;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Get the last received request options.
|
147 |
+
*
|
148 |
+
* @return RequestInterface
|
149 |
+
*/
|
150 |
+
public function getLastOptions()
|
151 |
+
{
|
152 |
+
return $this->lastOptions;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Returns the number of remaining items in the queue.
|
157 |
+
*
|
158 |
+
* @return int
|
159 |
+
*/
|
160 |
+
public function count()
|
161 |
+
{
|
162 |
+
return count($this->queue);
|
163 |
+
}
|
164 |
+
|
165 |
+
private function invokeStats(
|
166 |
+
RequestInterface $request,
|
167 |
+
array $options,
|
168 |
+
ResponseInterface $response = null,
|
169 |
+
$reason = null
|
170 |
+
) {
|
171 |
+
if (isset($options['on_stats'])) {
|
172 |
+
$stats = new TransferStats($request, $response, 0, $reason);
|
173 |
+
call_user_func($options['on_stats'], $stats);
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
includes/aws/GuzzleHttp/Handler/Proxy.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\RequestOptions;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Provides basic proxies for handlers.
|
9 |
+
*/
|
10 |
+
class Proxy
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Sends synchronous requests to a specific handler while sending all other
|
14 |
+
* requests to another handler.
|
15 |
+
*
|
16 |
+
* @param callable $default Handler used for normal responses
|
17 |
+
* @param callable $sync Handler used for synchronous responses.
|
18 |
+
*
|
19 |
+
* @return callable Returns the composed handler.
|
20 |
+
*/
|
21 |
+
public static function wrapSync(
|
22 |
+
callable $default,
|
23 |
+
callable $sync
|
24 |
+
) {
|
25 |
+
return function (RequestInterface $request, array $options) use ($default, $sync) {
|
26 |
+
return empty($options[RequestOptions::SYNCHRONOUS])
|
27 |
+
? $default($request, $options)
|
28 |
+
: $sync($request, $options);
|
29 |
+
};
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Sends streaming requests to a streaming compatible handler while sending
|
34 |
+
* all other requests to a default handler.
|
35 |
+
*
|
36 |
+
* This, for example, could be useful for taking advantage of the
|
37 |
+
* performance benefits of curl while still supporting true streaming
|
38 |
+
* through the StreamHandler.
|
39 |
+
*
|
40 |
+
* @param callable $default Handler used for non-streaming responses
|
41 |
+
* @param callable $streaming Handler used for streaming responses
|
42 |
+
*
|
43 |
+
* @return callable Returns the composed handler.
|
44 |
+
*/
|
45 |
+
public static function wrapStreaming(
|
46 |
+
callable $default,
|
47 |
+
callable $streaming
|
48 |
+
) {
|
49 |
+
return function (RequestInterface $request, array $options) use ($default, $streaming) {
|
50 |
+
return empty($options['stream'])
|
51 |
+
? $default($request, $options)
|
52 |
+
: $streaming($request, $options);
|
53 |
+
};
|
54 |
+
}
|
55 |
+
}
|
includes/aws/GuzzleHttp/Handler/StreamHandler.php
ADDED
@@ -0,0 +1,458 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\Exception\ConnectException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
9 |
+
use GuzzleHttp\Psr7;
|
10 |
+
use GuzzleHttp\TransferStats;
|
11 |
+
use Psr\Http\Message\RequestInterface;
|
12 |
+
use Psr\Http\Message\ResponseInterface;
|
13 |
+
use Psr\Http\Message\StreamInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* HTTP handler that uses PHP's HTTP stream wrapper.
|
17 |
+
*/
|
18 |
+
class StreamHandler
|
19 |
+
{
|
20 |
+
private $lastHeaders = [];
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Sends an HTTP request.
|
24 |
+
*
|
25 |
+
* @param RequestInterface $request Request to send.
|
26 |
+
* @param array $options Request transfer options.
|
27 |
+
*
|
28 |
+
* @return PromiseInterface
|
29 |
+
*/
|
30 |
+
public function __invoke(RequestInterface $request, array $options)
|
31 |
+
{
|
32 |
+
// Sleep if there is a delay specified.
|
33 |
+
if (isset($options['delay'])) {
|
34 |
+
usleep($options['delay'] * 1000);
|
35 |
+
}
|
36 |
+
|
37 |
+
$startTime = isset($options['on_stats']) ? microtime(true) : null;
|
38 |
+
|
39 |
+
try {
|
40 |
+
// Does not support the expect header.
|
41 |
+
$request = $request->withoutHeader('Expect');
|
42 |
+
|
43 |
+
// Append a content-length header if body size is zero to match
|
44 |
+
// cURL's behavior.
|
45 |
+
if (0 === $request->getBody()->getSize()) {
|
46 |
+
$request = $request->withHeader('Content-Length', 0);
|
47 |
+
}
|
48 |
+
|
49 |
+
return $this->createResponse(
|
50 |
+
$request,
|
51 |
+
$options,
|
52 |
+
$this->createStream($request, $options),
|
53 |
+
$startTime
|
54 |
+
);
|
55 |
+
} catch (\InvalidArgumentException $e) {
|
56 |
+
throw $e;
|
57 |
+
} catch (\Exception $e) {
|
58 |
+
// Determine if the error was a networking error.
|
59 |
+
$message = $e->getMessage();
|
60 |
+
// This list can probably get more comprehensive.
|
61 |
+
if (strpos($message, 'getaddrinfo') // DNS lookup failed
|
62 |
+
|| strpos($message, 'Connection refused')
|
63 |
+
|| strpos($message, "couldn't connect to host") // error on HHVM
|
64 |
+
) {
|
65 |
+
$e = new ConnectException($e->getMessage(), $request, $e);
|
66 |
+
}
|
67 |
+
$e = RequestException::wrapException($request, $e);
|
68 |
+
$this->invokeStats($options, $request, $startTime, null, $e);
|
69 |
+
|
70 |
+
return new RejectedPromise($e);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
private function invokeStats(
|
75 |
+
array $options,
|
76 |
+
RequestInterface $request,
|
77 |
+
$startTime,
|
78 |
+
ResponseInterface $response = null,
|
79 |
+
$error = null
|
80 |
+
) {
|
81 |
+
if (isset($options['on_stats'])) {
|
82 |
+
$stats = new TransferStats(
|
83 |
+
$request,
|
84 |
+
$response,
|
85 |
+
microtime(true) - $startTime,
|
86 |
+
$error,
|
87 |
+
[]
|
88 |
+
);
|
89 |
+
call_user_func($options['on_stats'], $stats);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
private function createResponse(
|
94 |
+
RequestInterface $request,
|
95 |
+
array $options,
|
96 |
+
$stream,
|
97 |
+
$startTime
|
98 |
+
) {
|
99 |
+
$hdrs = $this->lastHeaders;
|
100 |
+
$this->lastHeaders = [];
|
101 |
+
$parts = explode(' ', array_shift($hdrs), 3);
|
102 |
+
$ver = explode('/', $parts[0])[1];
|
103 |
+
$status = $parts[1];
|
104 |
+
$reason = isset($parts[2]) ? $parts[2] : null;
|
105 |
+
$headers = \GuzzleHttp\headers_from_lines($hdrs);
|
106 |
+
list ($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
107 |
+
$stream = Psr7\stream_for($stream);
|
108 |
+
$sink = $this->createSink($stream, $options);
|
109 |
+
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
|
110 |
+
|
111 |
+
if (isset($options['on_headers'])) {
|
112 |
+
try {
|
113 |
+
$options['on_headers']($response);
|
114 |
+
} catch (\Exception $e) {
|
115 |
+
$msg = 'An error was encountered during the on_headers event';
|
116 |
+
$ex = new RequestException($msg, $request, $response, $e);
|
117 |
+
return new RejectedPromise($ex);
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
if ($sink !== $stream) {
|
122 |
+
$this->drain($stream, $sink);
|
123 |
+
}
|
124 |
+
|
125 |
+
$this->invokeStats($options, $request, $startTime, $response, null);
|
126 |
+
|
127 |
+
return new FulfilledPromise($response);
|
128 |
+
}
|
129 |
+
|
130 |
+
private function createSink(StreamInterface $stream, array $options)
|
131 |
+
{
|
132 |
+
if (!empty($options['stream'])) {
|
133 |
+
return $stream;
|
134 |
+
}
|
135 |
+
|
136 |
+
$sink = isset($options['sink'])
|
137 |
+
? $options['sink']
|
138 |
+
: fopen('php://temp', 'r+');
|
139 |
+
|
140 |
+
return is_string($sink)
|
141 |
+
? new Psr7\Stream(Psr7\try_fopen($sink, 'r+'))
|
142 |
+
: Psr7\stream_for($sink);
|
143 |
+
}
|
144 |
+
|
145 |
+
private function checkDecode(array $options, array $headers, $stream)
|
146 |
+
{
|
147 |
+
// Automatically decode responses when instructed.
|
148 |
+
if (!empty($options['decode_content'])) {
|
149 |
+
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
150 |
+
if (isset($normalizedKeys['content-encoding'])) {
|
151 |
+
$encoding = $headers[$normalizedKeys['content-encoding']];
|
152 |
+
if ($encoding[0] == 'gzip' || $encoding[0] == 'deflate') {
|
153 |
+
$stream = new Psr7\InflateStream(
|
154 |
+
Psr7\stream_for($stream)
|
155 |
+
);
|
156 |
+
// Remove content-encoding header
|
157 |
+
unset($headers[$normalizedKeys['content-encoding']]);
|
158 |
+
// Fix content-length header
|
159 |
+
if (isset($normalizedKeys['content-length'])) {
|
160 |
+
$length = (int) $stream->getSize();
|
161 |
+
if ($length == 0) {
|
162 |
+
unset($headers[$normalizedKeys['content-length']]);
|
163 |
+
} else {
|
164 |
+
$headers[$normalizedKeys['content-length']] = [$length];
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
return [$stream, $headers];
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Drains the source stream into the "sink" client option.
|
176 |
+
*
|
177 |
+
* @param StreamInterface $source
|
178 |
+
* @param StreamInterface $sink
|
179 |
+
*
|
180 |
+
* @return StreamInterface
|
181 |
+
* @throws \RuntimeException when the sink option is invalid.
|
182 |
+
*/
|
183 |
+
private function drain(StreamInterface $source, StreamInterface $sink)
|
184 |
+
{
|
185 |
+
Psr7\copy_to_stream($source, $sink);
|
186 |
+
$sink->seek(0);
|
187 |
+
$source->close();
|
188 |
+
|
189 |
+
return $sink;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Create a resource and check to ensure it was created successfully
|
194 |
+
*
|
195 |
+
* @param callable $callback Callable that returns stream resource
|
196 |
+
*
|
197 |
+
* @return resource
|
198 |
+
* @throws \RuntimeException on error
|
199 |
+
*/
|
200 |
+
private function createResource(callable $callback)
|
201 |
+
{
|
202 |
+
$errors = null;
|
203 |
+
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
|
204 |
+
$errors[] = [
|
205 |
+
'message' => $msg,
|
206 |
+
'file' => $file,
|
207 |
+
'line' => $line
|
208 |
+
];
|
209 |
+
return true;
|
210 |
+
});
|
211 |
+
|
212 |
+
$resource = $callback();
|
213 |
+
restore_error_handler();
|
214 |
+
|
215 |
+
if (!$resource) {
|
216 |
+
$message = 'Error creating resource: ';
|
217 |
+
foreach ($errors as $err) {
|
218 |
+
foreach ($err as $key => $value) {
|
219 |
+
$message .= "[$key] $value" . PHP_EOL;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
throw new \RuntimeException(trim($message));
|
223 |
+
}
|
224 |
+
|
225 |
+
return $resource;
|
226 |
+
}
|
227 |
+
|
228 |
+
private function createStream(RequestInterface $request, array $options)
|
229 |
+
{
|
230 |
+
static $methods;
|
231 |
+
if (!$methods) {
|
232 |
+
$methods = array_flip(get_class_methods(__CLASS__));
|
233 |
+
}
|
234 |
+
|
235 |
+
// HTTP/1.1 streams using the PHP stream wrapper require a
|
236 |
+
// Connection: close header
|
237 |
+
if ($request->getProtocolVersion() == '1.1'
|
238 |
+
&& !$request->hasHeader('Connection')
|
239 |
+
) {
|
240 |
+
$request = $request->withHeader('Connection', 'close');
|
241 |
+
}
|
242 |
+
|
243 |
+
// Ensure SSL is verified by default
|
244 |
+
if (!isset($options['verify'])) {
|
245 |
+
$options['verify'] = true;
|
246 |
+
}
|
247 |
+
|
248 |
+
$params = [];
|
249 |
+
$context = $this->getDefaultContext($request, $options);
|
250 |
+
|
251 |
+
if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
|
252 |
+
throw new \InvalidArgumentException('on_headers must be callable');
|
253 |
+
}
|
254 |
+
|
255 |
+
if (!empty($options)) {
|
256 |
+
foreach ($options as $key => $value) {
|
257 |
+
$method = "add_{$key}";
|
258 |
+
if (isset($methods[$method])) {
|
259 |
+
$this->{$method}($request, $context, $value, $params);
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
if (isset($options['stream_context'])) {
|
265 |
+
if (!is_array($options['stream_context'])) {
|
266 |
+
throw new \InvalidArgumentException('stream_context must be an array');
|
267 |
+
}
|
268 |
+
$context = array_replace_recursive(
|
269 |
+
$context,
|
270 |
+
$options['stream_context']
|
271 |
+
);
|
272 |
+
}
|
273 |
+
|
274 |
+
$context = $this->createResource(
|
275 |
+
function () use ($context, $params) {
|
276 |
+
return stream_context_create($context, $params);
|
277 |
+
}
|
278 |
+
);
|
279 |
+
|
280 |
+
return $this->createResource(
|
281 |
+
function () use ($request, &$http_response_header, $context) {
|
282 |
+
$resource = fopen($request->getUri(), 'r', null, $context);
|
283 |
+
$this->lastHeaders = $http_response_header;
|
284 |
+
return $resource;
|
285 |
+
}
|
286 |
+
);
|
287 |
+
}
|
288 |
+
|
289 |
+
private function getDefaultContext(RequestInterface $request)
|
290 |
+
{
|
291 |
+
$headers = '';
|
292 |
+
foreach ($request->getHeaders() as $name => $value) {
|
293 |
+
foreach ($value as $val) {
|
294 |
+
$headers .= "$name: $val\r\n";
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
$context = [
|
299 |
+
'http' => [
|
300 |
+
'method' => $request->getMethod(),
|
301 |
+
'header' => $headers,
|
302 |
+
'protocol_version' => $request->getProtocolVersion(),
|
303 |
+
'ignore_errors' => true,
|
304 |
+
'follow_location' => 0,
|
305 |
+
],
|
306 |
+
];
|
307 |
+
|
308 |
+
$body = (string) $request->getBody();
|
309 |
+
|
310 |
+
if (!empty($body)) {
|
311 |
+
$context['http']['content'] = $body;
|
312 |
+
// Prevent the HTTP handler from adding a Content-Type header.
|
313 |
+
if (!$request->hasHeader('Content-Type')) {
|
314 |
+
$context['http']['header'] .= "Content-Type:\r\n";
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
$context['http']['header'] = rtrim($context['http']['header']);
|
319 |
+
|
320 |
+
return $context;
|
321 |
+
}
|
322 |
+
|
323 |
+
private function add_proxy(RequestInterface $request, &$options, $value, &$params)
|
324 |
+
{
|
325 |
+
if (!is_array($value)) {
|
326 |
+
$options['http']['proxy'] = $value;
|
327 |
+
} else {
|
328 |
+
$scheme = $request->getUri()->getScheme();
|
329 |
+
if (isset($value[$scheme])) {
|
330 |
+
if (!isset($value['no'])
|
331 |
+
|| !\GuzzleHttp\is_host_in_noproxy(
|
332 |
+
$request->getUri()->getHost(),
|
333 |
+
$value['no']
|
334 |
+
)
|
335 |
+
) {
|
336 |
+
$options['http']['proxy'] = $value[$scheme];
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
343 |
+
{
|
344 |
+
$options['http']['timeout'] = $value;
|
345 |
+
}
|
346 |
+
|
347 |
+
private function add_verify(RequestInterface $request, &$options, $value, &$params)
|
348 |
+
{
|
349 |
+
if ($value === true) {
|
350 |
+
// PHP 5.6 or greater will find the system cert by default. When
|
351 |
+
// < 5.6, use the Guzzle bundled cacert.
|
352 |
+
if (PHP_VERSION_ID < 50600) {
|
353 |
+
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
|
354 |
+
}
|
355 |
+
} elseif (is_string($value)) {
|
356 |
+
$options['ssl']['cafile'] = $value;
|
357 |
+
if (!file_exists($value)) {
|
358 |
+
throw new \RuntimeException("SSL CA bundle not found: $value");
|
359 |
+
}
|
360 |
+
} elseif ($value === false) {
|
361 |
+
$options['ssl']['verify_peer'] = false;
|
362 |
+
$options['ssl']['verify_peer_name'] = false;
|
363 |
+
return;
|
364 |
+
} else {
|
365 |
+
throw new \InvalidArgumentException('Invalid verify request option');
|
366 |
+
}
|
367 |
+
|
368 |
+
$options['ssl']['verify_peer'] = true;
|
369 |
+
$options['ssl']['verify_peer_name'] = true;
|
370 |
+
$options['ssl']['allow_self_signed'] = false;
|
371 |
+
}
|
372 |
+
|
373 |
+
private function add_cert(RequestInterface $request, &$options, $value, &$params)
|
374 |
+
{
|
375 |
+
if (is_array($value)) {
|
376 |
+
$options['ssl']['passphrase'] = $value[1];
|
377 |
+
$value = $value[0];
|
378 |
+
}
|
379 |
+
|
380 |
+
if (!file_exists($value)) {
|
381 |
+
throw new \RuntimeException("SSL certificate not found: {$value}");
|
382 |
+
}
|
383 |
+
|
384 |
+
$options['ssl']['local_cert'] = $value;
|
385 |
+
}
|
386 |
+
|
387 |
+
private function add_progress(RequestInterface $request, &$options, $value, &$params)
|
388 |
+
{
|
389 |
+
$this->addNotification(
|
390 |
+
$params,
|
391 |
+
function ($code, $a, $b, $c, $transferred, $total) use ($value) {
|
392 |
+
if ($code == STREAM_NOTIFY_PROGRESS) {
|
393 |
+
$value($total, $transferred, null, null);
|
394 |
+
}
|
395 |
+
}
|
396 |
+
);
|
397 |
+
}
|
398 |
+
|
399 |
+
private function add_debug(RequestInterface $request, &$options, $value, &$params)
|
400 |
+
{
|
401 |
+
if ($value === false) {
|
402 |
+
return;
|
403 |
+
}
|
404 |
+
|
405 |
+
static $map = [
|
406 |
+
STREAM_NOTIFY_CONNECT => 'CONNECT',
|
407 |
+
STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
|
408 |
+
STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
|
409 |
+
STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
|
410 |
+
STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
|
411 |
+
STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
|
412 |
+
STREAM_NOTIFY_PROGRESS => 'PROGRESS',
|
413 |
+
STREAM_NOTIFY_FAILURE => 'FAILURE',
|
414 |
+
STREAM_NOTIFY_COMPLETED => 'COMPLETED',
|
415 |
+
STREAM_NOTIFY_RESOLVE => 'RESOLVE',
|
416 |
+
];
|
417 |
+
static $args = ['severity', 'message', 'message_code',
|
418 |
+
'bytes_transferred', 'bytes_max'];
|
419 |
+
|
420 |
+
$value = \GuzzleHttp\debug_resource($value);
|
421 |
+
$ident = $request->getMethod() . ' ' . $request->getUri();
|
422 |
+
$this->addNotification(
|
423 |
+
$params,
|
424 |
+
function () use ($ident, $value, $map, $args) {
|
425 |
+
$passed = func_get_args();
|
426 |
+
$code = array_shift($passed);
|
427 |
+
fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
428 |
+
foreach (array_filter($passed) as $i => $v) {
|
429 |
+
fwrite($value, $args[$i] . ': "' . $v . '" ');
|
430 |
+
}
|
431 |
+
fwrite($value, "\n");
|
432 |
+
}
|
433 |
+
);
|
434 |
+
}
|
435 |
+
|
436 |
+
private function addNotification(array &$params, callable $notify)
|
437 |
+
{
|
438 |
+
// Wrap the existing function if needed.
|
439 |
+
if (!isset($params['notification'])) {
|
440 |
+
$params['notification'] = $notify;
|
441 |
+
} else {
|
442 |
+
$params['notification'] = $this->callArray([
|
443 |
+
$params['notification'],
|
444 |
+
$notify
|
445 |
+
]);
|
446 |
+
}
|
447 |
+
}
|
448 |
+
|
449 |
+
private function callArray(array $functions)
|
450 |
+
{
|
451 |
+
return function () use ($functions) {
|
452 |
+
$args = func_get_args();
|
453 |
+
foreach ($functions as $fn) {
|
454 |
+
call_user_func_array($fn, $args);
|
455 |
+
}
|
456 |
+
};
|
457 |
+
}
|
458 |
+
}
|
includes/aws/GuzzleHttp/HandlerStack.php
ADDED
@@ -0,0 +1,273 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
8 |
+
* an HTTP handler function.
|
9 |
+
*/
|
10 |
+
class HandlerStack
|
11 |
+
{
|
12 |
+
/** @var callable */
|
13 |
+
private $handler;
|
14 |
+
|
15 |
+
/** @var array */
|
16 |
+
private $stack = [];
|
17 |
+
|
18 |
+
/** @var callable|null */
|
19 |
+
private $cached;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Creates a default handler stack that can be used by clients.
|
23 |
+
*
|
24 |
+
* The returned handler will wrap the provided handler or use the most
|
25 |
+
* appropriate default handler for you system. The returned HandlerStack has
|
26 |
+
* support for cookies, redirects, HTTP error exceptions, and preparing a body
|
27 |
+
* before sending.
|
28 |
+
*
|
29 |
+
* The returned handler stack can be passed to a client in the "handler"
|
30 |
+
* option.
|
31 |
+
*
|
32 |
+
* @param callable $handler HTTP handler function to use with the stack. If no
|
33 |
+
* handler is provided, the best handler for your
|
34 |
+
* system will be utilized.
|
35 |
+
*
|
36 |
+
* @return HandlerStack
|
37 |
+
*/
|
38 |
+
public static function create(callable $handler = null)
|
39 |
+
{
|
40 |
+
$stack = new self($handler ?: choose_handler());
|
41 |
+
$stack->push(Middleware::httpErrors(), 'http_errors');
|
42 |
+
$stack->push(Middleware::redirect(), 'allow_redirects');
|
43 |
+
$stack->push(Middleware::cookies(), 'cookies');
|
44 |
+
$stack->push(Middleware::prepareBody(), 'prepare_body');
|
45 |
+
|
46 |
+
return $stack;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param callable $handler Underlying HTTP handler.
|
51 |
+
*/
|
52 |
+
public function __construct(callable $handler = null)
|
53 |
+
{
|
54 |
+
$this->handler = $handler;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Invokes the handler stack as a composed handler
|
59 |
+
*
|
60 |
+
* @param RequestInterface $request
|
61 |
+
* @param array $options
|
62 |
+
*/
|
63 |
+
public function __invoke(RequestInterface $request, array $options)
|
64 |
+
{
|
65 |
+
$handler = $this->resolve();
|
66 |
+
|
67 |
+
return $handler($request, $options);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Dumps a string representation of the stack.
|
72 |
+
*
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function __toString()
|
76 |
+
{
|
77 |
+
$depth = 0;
|
78 |
+
$stack = [];
|
79 |
+
if ($this->handler) {
|
80 |
+
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
81 |
+
}
|
82 |
+
|
83 |
+
$result = '';
|
84 |
+
foreach (array_reverse($this->stack) as $tuple) {
|
85 |
+
$depth++;
|
86 |
+
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
87 |
+
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
88 |
+
$result = "> {$str}\n{$result}";
|
89 |
+
$stack[] = $str;
|
90 |
+
}
|
91 |
+
|
92 |
+
foreach (array_keys($stack) as $k) {
|
93 |
+
$result .= "< {$stack[$k]}\n";
|
94 |
+
}
|
95 |
+
|
96 |
+
return $result;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Set the HTTP handler that actually returns a promise.
|
101 |
+
*
|
102 |
+
* @param callable $handler Accepts a request and array of options and
|
103 |
+
* returns a Promise.
|
104 |
+
*/
|
105 |
+
public function setHandler(callable $handler)
|
106 |
+
{
|
107 |
+
$this->handler = $handler;
|
108 |
+
$this->cached = null;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Returns true if the builder has a handler.
|
113 |
+
*
|
114 |
+
* @return bool
|
115 |
+
*/
|
116 |
+
public function hasHandler()
|
117 |
+
{
|
118 |
+
return (bool) $this->handler;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Unshift a middleware to the bottom of the stack.
|
123 |
+
*
|
124 |
+
* @param callable $middleware Middleware function
|
125 |
+
* @param string $name Name to register for this middleware.
|
126 |
+
*/
|
127 |
+
public function unshift(callable $middleware, $name = null)
|
128 |
+
{
|
129 |
+
array_unshift($this->stack, [$middleware, $name]);
|
130 |
+
$this->cached = null;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Push a middleware to the top of the stack.
|
135 |
+
*
|
136 |
+
* @param callable $middleware Middleware function
|
137 |
+
* @param string $name Name to register for this middleware.
|
138 |
+
*/
|
139 |
+
public function push(callable $middleware, $name = '')
|
140 |
+
{
|
141 |
+
$this->stack[] = [$middleware, $name];
|
142 |
+
$this->cached = null;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Add a middleware before another middleware by name.
|
147 |
+
*
|
148 |
+
* @param string $findName Middleware to find
|
149 |
+
* @param callable $middleware Middleware function
|
150 |
+
* @param string $withName Name to register for this middleware.
|
151 |
+
*/
|
152 |
+
public function before($findName, callable $middleware, $withName = '')
|
153 |
+
{
|
154 |
+
$this->splice($findName, $withName, $middleware, true);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Add a middleware after another middleware by name.
|
159 |
+
*
|
160 |
+
* @param string $findName Middleware to find
|
161 |
+
* @param callable $middleware Middleware function
|
162 |
+
* @param string $withName Name to register for this middleware.
|
163 |
+
*/
|
164 |
+
public function after($findName, callable $middleware, $withName = '')
|
165 |
+
{
|
166 |
+
$this->splice($findName, $withName, $middleware, false);
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Remove a middleware by instance or name from the stack.
|
171 |
+
*
|
172 |
+
* @param callable|string $remove Middleware to remove by instance or name.
|
173 |
+
*/
|
174 |
+
public function remove($remove)
|
175 |
+
{
|
176 |
+
$this->cached = null;
|
177 |
+
$idx = is_callable($remove) ? 0 : 1;
|
178 |
+
$this->stack = array_values(array_filter(
|
179 |
+
$this->stack,
|
180 |
+
function ($tuple) use ($idx, $remove) {
|
181 |
+
return $tuple[$idx] !== $remove;
|
182 |
+
}
|
183 |
+
));
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Compose the middleware and handler into a single callable function.
|
188 |
+
*
|
189 |
+
* @return callable
|
190 |
+
*/
|
191 |
+
public function resolve()
|
192 |
+
{
|
193 |
+
if (!$this->cached) {
|
194 |
+
if (!($prev = $this->handler)) {
|
195 |
+
throw new \LogicException('No handler has been specified');
|
196 |
+
}
|
197 |
+
|
198 |
+
foreach (array_reverse($this->stack) as $fn) {
|
199 |
+
$prev = $fn[0]($prev);
|
200 |
+
}
|
201 |
+
|
202 |
+
$this->cached = $prev;
|
203 |
+
}
|
204 |
+
|
205 |
+
return $this->cached;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* @param $name
|
210 |
+
* @return int
|
211 |
+
*/
|
212 |
+
private function findByName($name)
|
213 |
+
{
|
214 |
+
foreach ($this->stack as $k => $v) {
|
215 |
+
if ($v[1] === $name) {
|
216 |
+
return $k;
|
217 |
+
}
|
218 |
+
}
|
219 |
+
|
220 |
+
throw new \InvalidArgumentException("Middleware not found: $name");
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Splices a function into the middleware list at a specific position.
|
225 |
+
*
|
226 |
+
* @param $findName
|
227 |
+
* @param $withName
|
228 |
+
* @param callable $middleware
|
229 |
+
* @param $before
|
230 |
+
*/
|
231 |
+
private function splice($findName, $withName, callable $middleware, $before)
|
232 |
+
{
|
233 |
+
$this->cached = null;
|
234 |
+
$idx = $this->findByName($findName);
|
235 |
+
$tuple = [$middleware, $withName];
|
236 |
+
|
237 |
+
if ($before) {
|
238 |
+
if ($idx === 0) {
|
239 |
+
array_unshift($this->stack, $tuple);
|
240 |
+
} else {
|
241 |
+
$replacement = [$tuple, $this->stack[$idx]];
|
242 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
243 |
+
}
|
244 |
+
} elseif ($idx === count($this->stack) - 1) {
|
245 |
+
$this->stack[] = $tuple;
|
246 |
+
} else {
|
247 |
+
$replacement = [$this->stack[$idx], $tuple];
|
248 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Provides a debug string for a given callable.
|
254 |
+
*
|
255 |
+
* @param array|callable $fn Function to write as a string.
|
256 |
+
*
|
257 |
+
* @return string
|
258 |
+
*/
|
259 |
+
private function debugCallable($fn)
|
260 |
+
{
|
261 |
+
if (is_string($fn)) {
|
262 |
+
return "callable({$fn})";
|
263 |
+
}
|
264 |
+
|
265 |
+
if (is_array($fn)) {
|
266 |
+
return is_string($fn[0])
|
267 |
+
? "callable({$fn[0]}::{$fn[1]})"
|
268 |
+
: "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
|
269 |
+
}
|
270 |
+
|
271 |
+
return 'callable(' . spl_object_hash($fn) . ')';
|
272 |
+
}
|
273 |
+
}
|
includes/aws/GuzzleHttp/MessageFormatter.php
ADDED
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use Psr\Http\Message\MessageInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Formats log messages using variable substitutions for requests, responses,
|
10 |
+
* and other transactional data.
|
11 |
+
*
|
12 |
+
* The following variable substitutions are supported:
|
13 |
+
*
|
14 |
+
* - {request}: Full HTTP request message
|
15 |
+
* - {response}: Full HTTP response message
|
16 |
+
* - {ts}: ISO 8601 date in GMT
|
17 |
+
* - {date_iso_8601} ISO 8601 date in GMT
|
18 |
+
* - {date_common_log} Apache common log date using the configured timezone.
|
19 |
+
* - {host}: Host of the request
|
20 |
+
* - {method}: Method of the request
|
21 |
+
* - {uri}: URI of the request
|
22 |
+
* - {host}: Host of the request
|
23 |
+
* - {version}: Protocol version
|
24 |
+
* - {target}: Request target of the request (path + query + fragment)
|
25 |
+
* - {hostname}: Hostname of the machine that sent the request
|
26 |
+
* - {code}: Status code of the response (if available)
|
27 |
+
* - {phrase}: Reason phrase of the response (if available)
|
28 |
+
* - {error}: Any error messages (if available)
|
29 |
+
* - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
|
30 |
+
* - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
|
31 |
+
* - {req_headers}: Request headers
|
32 |
+
* - {res_headers}: Response headers
|
33 |
+
* - {req_body}: Request body
|
34 |
+
* - {res_body}: Response body
|
35 |
+
*/
|
36 |
+
class MessageFormatter
|
37 |
+
{
|
38 |
+
/**
|
39 |
+
* Apache Common Log Format.
|
40 |
+
* @link http://httpd.apache.org/docs/2.4/logs.html#common
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
44 |
+
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
45 |
+
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
46 |
+
|
47 |
+
/** @var string Template used to format log messages */
|
48 |
+
private $template;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @param string $template Log message template
|
52 |
+
*/
|
53 |
+
public function __construct($template = self::CLF)
|
54 |
+
{
|
55 |
+
$this->template = $template ?: self::CLF;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Returns a formatted message string.
|
60 |
+
*
|
61 |
+
* @param RequestInterface $request Request that was sent
|
62 |
+
* @param ResponseInterface $response Response that was received
|
63 |
+
* @param \Exception $error Exception that was received
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
public function format(
|
68 |
+
RequestInterface $request,
|
69 |
+
ResponseInterface $response = null,
|
70 |
+
\Exception $error = null
|
71 |
+
) {
|
72 |
+
$cache = [];
|
73 |
+
|
74 |
+
return preg_replace_callback(
|
75 |
+
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
|
76 |
+
function (array $matches) use ($request, $response, $error, &$cache) {
|
77 |
+
|
78 |
+
if (isset($cache[$matches[1]])) {
|
79 |
+
return $cache[$matches[1]];
|
80 |
+
}
|
81 |
+
|
82 |
+
$result = '';
|
83 |
+
switch ($matches[1]) {
|
84 |
+
case 'request':
|
85 |
+
$result = Psr7\str($request);
|
86 |
+
break;
|
87 |
+
case 'response':
|
88 |
+
$result = $response ? Psr7\str($response) : '';
|
89 |
+
break;
|
90 |
+
case 'req_headers':
|
91 |
+
$result = trim($request->getMethod()
|
92 |
+
. ' ' . $request->getRequestTarget())
|
93 |
+
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
|
94 |
+
. $this->headers($request);
|
95 |
+
break;
|
96 |
+
case 'res_headers':
|
97 |
+
$result = $response ?
|
98 |
+
sprintf(
|
99 |
+
'HTTP/%s %d %s',
|
100 |
+
$response->getProtocolVersion(),
|
101 |
+
$response->getStatusCode(),
|
102 |
+
$response->getReasonPhrase()
|
103 |
+
) . "\r\n" . $this->headers($response)
|
104 |
+
: 'NULL';
|
105 |
+
break;
|
106 |
+
case 'req_body':
|
107 |
+
$result = $request->getBody();
|
108 |
+
break;
|
109 |
+
case 'res_body':
|
110 |
+
$result = $response ? $response->getBody() : 'NULL';
|
111 |
+
break;
|
112 |
+
case 'ts':
|
113 |
+
case 'date_iso_8601':
|
114 |
+
$result = gmdate('c');
|
115 |
+
break;
|
116 |
+
case 'date_common_log':
|
117 |
+
$result = date('d/M/Y:H:i:s O');
|
118 |
+
break;
|
119 |
+
case 'method':
|
120 |
+
$result = $request->getMethod();
|
121 |
+
break;
|
122 |
+
case 'version':
|
123 |
+
$result = $request->getProtocolVersion();
|
124 |
+
break;
|
125 |
+
case 'uri':
|
126 |
+
case 'url':
|
127 |
+
$result = $request->getUri();
|
128 |
+
break;
|
129 |
+
case 'target':
|
130 |
+
$result = $request->getRequestTarget();
|
131 |
+
break;
|
132 |
+
case 'req_version':
|
133 |
+
$result = $request->getProtocolVersion();
|
134 |
+
break;
|
135 |
+
case 'res_version':
|
136 |
+
$result = $response
|
137 |
+
? $response->getProtocolVersion()
|
138 |
+
: 'NULL';
|
139 |
+
break;
|
140 |
+
case 'host':
|
141 |
+
$result = $request->getHeaderLine('Host');
|
142 |
+
break;
|
143 |
+
case 'hostname':
|
144 |
+
$result = gethostname();
|
145 |
+
break;
|
146 |
+
case 'code':
|
147 |
+
$result = $response ? $response->getStatusCode() : 'NULL';
|
148 |
+
break;
|
149 |
+
case 'phrase':
|
150 |
+
$result = $response ? $response->getReasonPhrase() : 'NULL';
|
151 |
+
break;
|
152 |
+
case 'error':
|
153 |
+
$result = $error ? $error->getMessage() : 'NULL';
|
154 |
+
break;
|
155 |
+
default:
|
156 |
+
// handle prefixed dynamic headers
|
157 |
+
if (strpos($matches[1], 'req_header_') === 0) {
|
158 |
+
$result = $request->getHeaderLine(substr($matches[1], 11));
|
159 |
+
} elseif (strpos($matches[1], 'res_header_') === 0) {
|
160 |
+
$result = $response
|
161 |
+
? $response->getHeaderLine(substr($matches[1], 11))
|
162 |
+
: 'NULL';
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
$cache[$matches[1]] = $result;
|
167 |
+
return $result;
|
168 |
+
},
|
169 |
+
$this->template
|
170 |
+
);
|
171 |
+
}
|
172 |
+
|
173 |
+
private function headers(MessageInterface $message)
|
174 |
+
{
|
175 |
+
$result = '';
|
176 |
+
foreach ($message->getHeaders() as $name => $values) {
|
177 |
+
$result .= $name . ': ' . implode(', ', $values) . "\r\n";
|
178 |
+
}
|
179 |
+
|
180 |
+
return trim($result);
|
181 |
+
}
|
182 |
+
}
|
includes/aws/GuzzleHttp/Middleware.php
ADDED
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Cookie\CookieJarInterface;
|
5 |
+
use GuzzleHttp\Exception\RequestException;
|
6 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
use Psr\Log\LoggerInterface;
|
10 |
+
use Psr\Log\LogLevel;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Functions used to create and wrap handlers with handler middleware.
|
14 |
+
*/
|
15 |
+
final class Middleware
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Middleware that adds cookies to requests.
|
19 |
+
*
|
20 |
+
* The options array must be set to a CookieJarInterface in order to use
|
21 |
+
* cookies. This is typically handled for you by a client.
|
22 |
+
*
|
23 |
+
* @return callable Returns a function that accepts the next handler.
|
24 |
+
*/
|
25 |
+
public static function cookies()
|
26 |
+
{
|
27 |
+
return function (callable $handler) {
|
28 |
+
return function ($request, array $options) use ($handler) {
|
29 |
+
if (empty($options['cookies'])) {
|
30 |
+
return $handler($request, $options);
|
31 |
+
} elseif (!($options['cookies'] instanceof CookieJarInterface)) {
|
32 |
+
throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
|
33 |
+
}
|
34 |
+
$cookieJar = $options['cookies'];
|
35 |
+
$request = $cookieJar->withCookieHeader($request);
|
36 |
+
return $handler($request, $options)
|
37 |
+
->then(function ($response) use ($cookieJar, $request) {
|
38 |
+
$cookieJar->extractCookies($request, $response);
|
39 |
+
return $response;
|
40 |
+
}
|
41 |
+
);
|
42 |
+
};
|
43 |
+
};
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Middleware that throws exceptions for 4xx or 5xx responses when the
|
48 |
+
* "http_error" request option is set to true.
|
49 |
+
*
|
50 |
+
* @return callable Returns a function that accepts the next handler.
|
51 |
+
*/
|
52 |
+
public static function httpErrors()
|
53 |
+
{
|
54 |
+
return function (callable $handler) {
|
55 |
+
return function ($request, array $options) use ($handler) {
|
56 |
+
if (empty($options['http_errors'])) {
|
57 |
+
return $handler($request, $options);
|
58 |
+
}
|
59 |
+
return $handler($request, $options)->then(
|
60 |
+
function (ResponseInterface $response) use ($request, $handler) {
|
61 |
+
$code = $response->getStatusCode();
|
62 |
+
if ($code < 400) {
|
63 |
+
return $response;
|
64 |
+
}
|
65 |
+
throw RequestException::create($request, $response);
|
66 |
+
}
|
67 |
+
);
|
68 |
+
};
|
69 |
+
};
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Middleware that pushes history data to an ArrayAccess container.
|
74 |
+
*
|
75 |
+
* @param array $container Container to hold the history (by reference).
|
76 |
+
*
|
77 |
+
* @return callable Returns a function that accepts the next handler.
|
78 |
+
*/
|
79 |
+
public static function history(array &$container)
|
80 |
+
{
|
81 |
+
return function (callable $handler) use (&$container) {
|
82 |
+
return function ($request, array $options) use ($handler, &$container) {
|
83 |
+
return $handler($request, $options)->then(
|
84 |
+
function ($value) use ($request, &$container, $options) {
|
85 |
+
$container[] = [
|
86 |
+
'request' => $request,
|
87 |
+
'response' => $value,
|
88 |
+
'error' => null,
|
89 |
+
'options' => $options
|
90 |
+
];
|
91 |
+
return $value;
|
92 |
+
},
|
93 |
+
function ($reason) use ($request, &$container, $options) {
|
94 |
+
$container[] = [
|
95 |
+
'request' => $request,
|
96 |
+
'response' => null,
|
97 |
+
'error' => $reason,
|
98 |
+
'options' => $options
|
99 |
+
];
|
100 |
+
return new RejectedPromise($reason);
|
101 |
+
}
|
102 |
+
);
|
103 |
+
};
|
104 |
+
};
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Middleware that invokes a callback before and after sending a request.
|
109 |
+
*
|
110 |
+
* The provided listener cannot modify or alter the response. It simply
|
111 |
+
* "taps" into the chain to be notified before returning the promise. The
|
112 |
+
* before listener accepts a request and options array, and the after
|
113 |
+
* listener accepts a request, options array, and response promise.
|
114 |
+
*
|
115 |
+
* @param callable $before Function to invoke before forwarding the request.
|
116 |
+
* @param callable $after Function invoked after forwarding.
|
117 |
+
*
|
118 |
+
* @return callable Returns a function that accepts the next handler.
|
119 |
+
*/
|
120 |
+
public static function tap(callable $before = null, callable $after = null)
|
121 |
+
{
|
122 |
+
return function (callable $handler) use ($before, $after) {
|
123 |
+
return function ($request, array $options) use ($handler, $before, $after) {
|
124 |
+
if ($before) {
|
125 |
+
$before($request, $options);
|
126 |
+
}
|
127 |
+
$response = $handler($request, $options);
|
128 |
+
if ($after) {
|
129 |
+
$after($request, $options, $response);
|
130 |
+
}
|
131 |
+
return $response;
|
132 |
+
};
|
133 |
+
};
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Middleware that handles request redirects.
|
138 |
+
*
|
139 |
+
* @return callable Returns a function that accepts the next handler.
|
140 |
+
*/
|
141 |
+
public static function redirect()
|
142 |
+
{
|
143 |
+
return function (callable $handler) {
|
144 |
+
return new RedirectMiddleware($handler);
|
145 |
+
};
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Middleware that retries requests based on the boolean result of
|
150 |
+
* invoking the provided "decider" function.
|
151 |
+
*
|
152 |
+
* If no delay function is provided, a simple implementation of exponential
|
153 |
+
* backoff will be utilized.
|
154 |
+
*
|
155 |
+
* @param callable $decider Function that accepts the number of retries,
|
156 |
+
* a request, [response], and [exception] and
|
157 |
+
* returns true if the request is to be retried.
|
158 |
+
* @param callable $delay Function that accepts the number of retries and
|
159 |
+
* returns the number of milliseconds to delay.
|
160 |
+
*
|
161 |
+
* @return callable Returns a function that accepts the next handler.
|
162 |
+
*/
|
163 |
+
public static function retry(callable $decider, callable $delay = null)
|
164 |
+
{
|
165 |
+
return function (callable $handler) use ($decider, $delay) {
|
166 |
+
return new RetryMiddleware($decider, $handler, $delay);
|
167 |
+
};
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Middleware that logs requests, responses, and errors using a message
|
172 |
+
* formatter.
|
173 |
+
*
|
174 |
+
* @param LoggerInterface $logger Logs messages.
|
175 |
+
* @param MessageFormatter $formatter Formatter used to create message strings.
|
176 |
+
* @param string $logLevel Level at which to log requests.
|
177 |
+
*
|
178 |
+
* @return callable Returns a function that accepts the next handler.
|
179 |
+
*/
|
180 |
+
public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
|
181 |
+
{
|
182 |
+
return function (callable $handler) use ($logger, $formatter, $logLevel) {
|
183 |
+
return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
|
184 |
+
return $handler($request, $options)->then(
|
185 |
+
function ($response) use ($logger, $request, $formatter, $logLevel) {
|
186 |
+
$message = $formatter->format($request, $response);
|
187 |
+
$logger->log($logLevel, $message);
|
188 |
+
return $response;
|
189 |
+
},
|
190 |
+
function ($reason) use ($logger, $request, $formatter) {
|
191 |
+
$response = $reason instanceof RequestException
|
192 |
+
? $reason->getResponse()
|
193 |
+
: null;
|
194 |
+
$message = $formatter->format($request, $response, $reason);
|
195 |
+
$logger->notice($message);
|
196 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
197 |
+
}
|
198 |
+
);
|
199 |
+
};
|
200 |
+
};
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* This middleware adds a default content-type if possible, a default
|
205 |
+
* content-length or transfer-encoding header, and the expect header.
|
206 |
+
*
|
207 |
+
* @return callable
|
208 |
+
*/
|
209 |
+
public static function prepareBody()
|
210 |
+
{
|
211 |
+
return function (callable $handler) {
|
212 |
+
return new PrepareBodyMiddleware($handler);
|
213 |
+
};
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Middleware that applies a map function to the request before passing to
|
218 |
+
* the next handler.
|
219 |
+
*
|
220 |
+
* @param callable $fn Function that accepts a RequestInterface and returns
|
221 |
+
* a RequestInterface.
|
222 |
+
* @return callable
|
223 |
+
*/
|
224 |
+
public static function mapRequest(callable $fn)
|
225 |
+
{
|
226 |
+
return function (callable $handler) use ($fn) {
|
227 |
+
return function ($request, array $options) use ($handler, $fn) {
|
228 |
+
return $handler($fn($request), $options);
|
229 |
+
};
|
230 |
+
};
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Middleware that applies a map function to the resolved promise's
|
235 |
+
* response.
|
236 |
+
*
|
237 |
+
* @param callable $fn Function that accepts a ResponseInterface and
|
238 |
+
* returns a ResponseInterface.
|
239 |
+
* @return callable
|
240 |
+
*/
|
241 |
+
public static function mapResponse(callable $fn)
|
242 |
+
{
|
243 |
+
return function (callable $handler) use ($fn) {
|
244 |
+
return function ($request, array $options) use ($handler, $fn) {
|
245 |
+
return $handler($request, $options)->then($fn);
|
246 |
+
};
|
247 |
+
};
|
248 |
+
}
|
249 |
+
}
|
includes/aws/GuzzleHttp/Pool.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use GuzzleHttp\Promise\EachPromise;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Sends and iterator of requests concurrently using a capped pool size.
|
10 |
+
*
|
11 |
+
* The pool will read from an iterator until it is cancelled or until the
|
12 |
+
* iterator is consumed. When a request is yielded, the request is sent after
|
13 |
+
* applying the "request_options" request options (if provided in the ctor).
|
14 |
+
*
|
15 |
+
* When a function is yielded by the iterator, the function is provided the
|
16 |
+
* "request_options" array that should be merged on top of any existing
|
17 |
+
* options, and the function MUST then return a wait-able promise.
|
18 |
+
*/
|
19 |
+
class Pool implements PromisorInterface
|
20 |
+
{
|
21 |
+
/** @var EachPromise */
|
22 |
+
private $each;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param ClientInterface $client Client used to send the requests.
|
26 |
+
* @param array|\Iterator $requests Requests or functions that return
|
27 |
+
* requests to send concurrently.
|
28 |
+
* @param array $config Associative array of options
|
29 |
+
* - concurrency: (int) Maximum number of requests to send concurrently
|
30 |
+
* - options: Array of request options to apply to each request.
|
31 |
+
* - fulfilled: (callable) Function to invoke when a request completes.
|
32 |
+
* - rejected: (callable) Function to invoke when a request is rejected.
|
33 |
+
*/
|
34 |
+
public function __construct(
|
35 |
+
ClientInterface $client,
|
36 |
+
$requests,
|
37 |
+
array $config = []
|
38 |
+
) {
|
39 |
+
// Backwards compatibility.
|
40 |
+
if (isset($config['pool_size'])) {
|
41 |
+
$config['concurrency'] = $config['pool_size'];
|
42 |
+
} elseif (!isset($config['concurrency'])) {
|
43 |
+
$config['concurrency'] = 25;
|
44 |
+
}
|
45 |
+
|
46 |
+
if (isset($config['options'])) {
|
47 |
+
$opts = $config['options'];
|
48 |
+
unset($config['options']);
|
49 |
+
} else {
|
50 |
+
$opts = [];
|
51 |
+
}
|
52 |
+
|
53 |
+
$iterable = \GuzzleHttp\Promise\iter_for($requests);
|
54 |
+
$requests = function () use ($iterable, $client, $opts) {
|
55 |
+
foreach ($iterable as $key => $rfn) {
|
56 |
+
if ($rfn instanceof RequestInterface) {
|
57 |
+
yield $key => $client->sendAsync($rfn, $opts);
|
58 |
+
} elseif (is_callable($rfn)) {
|
59 |
+
yield $key => $rfn($opts);
|
60 |
+
} else {
|
61 |
+
throw new \InvalidArgumentException('Each value yielded by '
|
62 |
+
. 'the iterator must be a Psr7\Http\Message\RequestInterface '
|
63 |
+
. 'or a callable that returns a promise that fulfills '
|
64 |
+
. 'with a Psr7\Message\Http\ResponseInterface object.');
|
65 |
+
}
|
66 |
+
}
|
67 |
+
};
|
68 |
+
|
69 |
+
$this->each = new EachPromise($requests(), $config);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function promise()
|
73 |
+
{
|
74 |
+
return $this->each->promise();
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Sends multiple requests concurrently and returns an array of responses
|
79 |
+
* and exceptions that uses the same ordering as the provided requests.
|
80 |
+
*
|
81 |
+
* IMPORTANT: This method keeps every request and response in memory, and
|
82 |
+
* as such, is NOT recommended when sending a large number or an
|
83 |
+
* indeterminate number of requests concurrently.
|
84 |
+
*
|
85 |
+
* @param ClientInterface $client Client used to send the requests
|
86 |
+
* @param array|\Iterator $requests Requests to send concurrently.
|
87 |
+
* @param array $options Passes through the options available in
|
88 |
+
* {@see GuzzleHttp\Pool::__construct}
|
89 |
+
*
|
90 |
+
* @return array Returns an array containing the response or an exception
|
91 |
+
* in the same order that the requests were sent.
|
92 |
+
* @throws \InvalidArgumentException if the event format is incorrect.
|
93 |
+
*/
|
94 |
+
public static function batch(
|
95 |
+
ClientInterface $client,
|
96 |
+
$requests,
|
97 |
+
array $options = []
|
98 |
+
) {
|
99 |
+
$res = [];
|
100 |
+
self::cmpCallback($options, 'fulfilled', $res);
|
101 |
+
self::cmpCallback($options, 'rejected', $res);
|
102 |
+
$pool = new static($client, $requests, $options);
|
103 |
+
$pool->promise()->wait();
|
104 |
+
ksort($res);
|
105 |
+
|
106 |
+
return $res;
|
107 |
+
}
|
108 |
+
|
109 |
+
private static function cmpCallback(array &$options, $name, array &$results)
|
110 |
+
{
|
111 |
+
if (!isset($options[$name])) {
|
112 |
+
$options[$name] = function ($v, $k) use (&$results) {
|
113 |
+
$results[$k] = $v;
|
114 |
+
};
|
115 |
+
} else {
|
116 |
+
$currentFn = $options[$name];
|
117 |
+
$options[$name] = function ($v, $k) use (&$results, $currentFn) {
|
118 |
+
$currentFn($v, $k);
|
119 |
+
$results[$k] = $v;
|
120 |
+
};
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
includes/aws/GuzzleHttp/PrepareBodyMiddleware.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Psr7;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Prepares requests that contain a body, adding the Content-Length,
|
10 |
+
* Content-Type, and Expect headers.
|
11 |
+
*/
|
12 |
+
class PrepareBodyMiddleware
|
13 |
+
{
|
14 |
+
/** @var callable */
|
15 |
+
private $nextHandler;
|
16 |
+
|
17 |
+
/** @var array */
|
18 |
+
private static $skipMethods = ['GET' => true, 'HEAD' => true];
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param callable $nextHandler Next handler to invoke.
|
22 |
+
*/
|
23 |
+
public function __construct(callable $nextHandler)
|
24 |
+
{
|
25 |
+
$this->nextHandler = $nextHandler;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param RequestInterface $request
|
30 |
+
* @param array $options
|
31 |
+
*
|
32 |
+
* @return PromiseInterface
|
33 |
+
*/
|
34 |
+
public function __invoke(RequestInterface $request, array $options)
|
35 |
+
{
|
36 |
+
$fn = $this->nextHandler;
|
37 |
+
|
38 |
+
// Don't do anything if the request has no body.
|
39 |
+
if (isset(self::$skipMethods[$request->getMethod()])
|
40 |
+
|| $request->getBody()->getSize() === 0
|
41 |
+
) {
|
42 |
+
return $fn($request, $options);
|
43 |
+
}
|
44 |
+
|
45 |
+
$modify = [];
|
46 |
+
|
47 |
+
// Add a default content-type if possible.
|
48 |
+
if (!$request->hasHeader('Content-Type')) {
|
49 |
+
if ($uri = $request->getBody()->getMetadata('uri')) {
|
50 |
+
|