-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Describe the bug
Some operations on multiple service clients are not returning Aws\Result as expected.
They appear to be shadowed by public methods defined on Aws\AwsClient, same root cause as #1936.
Affected examples I found
- AppSyncClient::getApi() → returns Aws\Api\Service
- AmplifyBackendClient::getToken() → returns GuzzleHttp\Promise\Promise
- IoTDeviceAdvisorClient::getEndpoint() → returns GuzzleHttp\Psr7\Uri
- IotClient::getCommand() → returns Aws\Command
- RedshiftServerlessClient::getCredentials() → returns GuzzleHttp\Promise\FulfilledPromise
All of these seem to dispatch Aws\AwsClient methods instead of invoking the service operation and thus do not yield Aws\Result.
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
Each call above should invoke the service operation and return an Aws\Result (or a promise of it for *Async variants).
Current Behavior
The calls are resolved to Aws\AwsClient public methods with the same names, returning other types (Aws\Api\Service, GuzzleHttp\Promise\Promise, GuzzleHttp\Psr7\Uri, Aws\Command, GuzzleHttp\Promise\FulfilledPromise).
Reproduction Steps
<?php
use Aws\AmplifyBackend\AmplifyBackendClient;
use Aws\AppSync\AppSyncClient;
use Aws\Iot\IotClient;
use Aws\IoTDeviceAdvisor\IoTDeviceAdvisorClient;
use Aws\RedshiftServerless\RedshiftServerlessClient;
$result = new AppSyncClient([])->getApi();
var_dump(get_class($result)); // Aws\Api\Service
$result = new AmplifyBackendClient([])->getToken();
var_dump(get_class($result)); // GuzzleHttp\Promise\Promise
$result = new IoTDeviceAdvisorClient([])->getEndpoint();
var_dump(get_class($result)); // GuzzleHttp\Psr7\Uri
$result = new IotClient([])->getCommand(['commandId' => '...']);
// **This does not actually work.**
// PHP Fatal error: Uncaught TypeError: Cannot access offset of type array in isset or empty in ./vendor/aws/aws-sdk-php/src/AwsClient.php:331
// Stack trace:
// #0 ./bug.php(20): Aws\AwsClient->getCommand(Array)
// #1 {main}
// thrown in ./vendor/aws/aws-sdk-php/src/AwsClient.php on line 33
$result = new IotClient([])->getCommand('getCardinality');
var_dump(get_class($result)); // Aws\Command
$result = new RedshiftServerlessClient([])->getCredentials();
var_dump(get_class($result)); // GuzzleHttp\Promise\FulfilledPromisePossible Solution
Aws\AwsClient publicly exposes getApi, getCommand, getCredentials, getEndpoint, getToken, etc. (docs show these and their return types). When a service also has operations named GetApi, GetCommand, GetCredentials, GetEndpoint, or GetToken, the client method is picked instead of the dynamic operation method. This matches the historical ApiGatewayV2Client::getApi incident fixed by introducing an operation alias (GetApiResource) in PR #1944. 
Suggested fixes
Apply the same approach as PR #1944: introduce operation aliases for any service whose operation name collides with Aws\AwsClient public methods (e.g., GetApiResource, GetEndpointOperation, etc.). 
Additional Information/Context
References
- Prior incident: ApiGatewayV2Client->getApi returns Aws\Api\Service (ApiGatewayV2Client->getApi returns Aws\Api\Service #1936). 
- Fix: ApiGatewayV2 operation alias (PR ApiGatewayV2 operation alias #1944). 
Thanks for taking a look!
SDK version used
3.356.33
Environment details (Version of PHP (php -v)? OS name and version, etc.)
8.4.13