diff --git a/src/internal/event-bridge.ts b/src/internal/event-bridge.ts index aa8ab88..38b0bb7 100644 --- a/src/internal/event-bridge.ts +++ b/src/internal/event-bridge.ts @@ -70,18 +70,17 @@ export class EventBridgeClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(EventBridgeOperation.PutEvents, res) + this.handleError(res, EventBridgeOperation.PutEvents) } - _handle_error( - operation: EventBridgeOperation, - response: RefinedResponse - ) { - const errorCode = response.error_code - if (errorCode === 0) { - return + + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation); + if (!errored) { + return false } + const errorCode = response.error_code const error = response.json() as JSONObject if (errorCode >= 1400 && errorCode <= 1499) { // In the event of certain errors, the message is not set. @@ -95,16 +94,18 @@ export class EventBridgeClient extends AWSClient { } // Otherwise throw a standard service error - throw new EventBridgeServiceError(errorMessage, error.__type as string, operation) + throw new EventBridgeServiceError(errorMessage, error.__type as string, operation as EventBridgeOperation) } if (errorCode === 1500) { throw new EventBridgeServiceError( 'An error occured on the server side', 'InternalServiceError', - operation + operation as EventBridgeOperation ) } + + return true } } diff --git a/src/internal/kinesis.ts b/src/internal/kinesis.ts index f1f30d5..6cbc18c 100644 --- a/src/internal/kinesis.ts +++ b/src/internal/kinesis.ts @@ -281,23 +281,18 @@ export class KinesisClient extends AWSClient { headers: signedRequest.headers, }) - this._handle_error(action, res) + this.handleError(res, action) return res } - /** - * If the response is an error, throw an error - * - * @param {string} operation - The name of the operation that was called. - * @param response - RefinedResponse - * @returns The response is being returned. - */ - _handle_error(operation: string, response: RefinedResponse) { - const errorCode = response.error_code - if (errorCode === 0) { - return + + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation); + if (!errored) { + return false } + const errorCode = response.error_code const error = response.json() as JSONObject if (errorCode >= 1400 && errorCode <= 1499) { // In the event of certain errors, the message is not set. @@ -311,16 +306,18 @@ export class KinesisClient extends AWSClient { } // Otherwise throw a standard service error - throw new KinesisServiceError(errorMessage, error.__type as string, operation) + throw new KinesisServiceError(errorMessage, error.__type as string, operation || 'Unknown') } if (errorCode === 1500) { throw new KinesisServiceError( 'An error occured on the server side', 'InternalServiceError', - operation + operation || 'Unknown' ) } + + return true } } diff --git a/src/internal/kms.ts b/src/internal/kms.ts index 175b6ae..866bf1c 100644 --- a/src/internal/kms.ts +++ b/src/internal/kms.ts @@ -69,7 +69,7 @@ export class KMSClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(KMSOperation.ListKeys, res) + this.handleError(res, KMSOperation.ListKeys) const json: JSONArray = res.json('Keys') as JSONArray return json.map((k) => KMSKey.fromJSON(k as JSONObject)) @@ -114,17 +114,18 @@ export class KMSClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(KMSOperation.GenerateDataKey, res) + this.handleError(res, KMSOperation.GenerateDataKey) return KMSDataKey.fromJSON(res.json() as JSONObject) } - _handle_error(operation: KMSOperation, response: RefinedResponse) { - const errorCode = response.error_code - if (errorCode === 0) { - return + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation); + if (!errored) { + return false } + const errorCode = response.error_code const error = response.json() as JSONObject if (errorCode >= 1400 && errorCode <= 1499) { // In the event of certain errors, the message is not set. @@ -138,16 +139,18 @@ export class KMSClient extends AWSClient { } // Otherwise throw a standard service error - throw new KMSServiceError(errorMessage, error.__type as string, operation) + throw new KMSServiceError(errorMessage, error.__type as string, operation as KMSOperation) } if (errorCode === 1500) { throw new KMSServiceError( 'An error occured on the server side', 'InternalServiceError', - operation + operation as KMSOperation ) } + + return true } } diff --git a/src/internal/lambda.ts b/src/internal/lambda.ts index be44356..4a0639e 100644 --- a/src/internal/lambda.ts +++ b/src/internal/lambda.ts @@ -81,7 +81,7 @@ export class LambdaClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(res) + this.handleError(res) const logResult = res.headers['X-Amz-Log-Result'] const response = { @@ -99,12 +99,11 @@ export class LambdaClient extends AWSClient { } } - private _handle_error(response: RefinedResponse) { - const errorCode: number = response.error_code - const errorMessage: string = response.error - if (errorMessage == '' && errorCode === 0) { - return + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation); + if (!errored) { + return false; } const awsError = AWSError.parse(response) @@ -115,6 +114,8 @@ export class LambdaClient extends AWSClient { default: throw awsError } + + return true } } diff --git a/src/internal/s3.ts b/src/internal/s3.ts index f9debdf..8a32448 100644 --- a/src/internal/s3.ts +++ b/src/internal/s3.ts @@ -63,7 +63,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('ListBuckets', res) + this.handleError(res, 'ListBuckets') const buckets: Array = [] @@ -122,7 +122,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('ListObjectsV2', res) + this.handleError(res, 'ListObjectsV2') const objects: Array = [] @@ -185,7 +185,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, null, { headers: signedRequest.headers, }) - this._handle_error('GetObject', res) + this.handleError(res, 'GetObject') return new S3Object( objectKey, @@ -243,7 +243,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error('PutObject', res) + this.handleError(res, 'PutObject') } /** @@ -272,7 +272,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('DeleteObject', res) + this.handleError(res, 'DeleteObject') } /** @@ -312,7 +312,7 @@ export class S3Client extends AWSClient { headers: signedRequest.headers, }) - this._handle_error('CopyObject', res) + this.handleError(res, 'CopyObject') } /** @@ -345,7 +345,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('CreateMultipartUpload', res) + this.handleError(res, 'CreateMultipartUpload') return new S3MultipartUpload( objectKey, @@ -395,7 +395,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('UploadPart', res) + this.handleError(res, 'UploadPart') return new S3Part(partNumber, res.headers['Etag']) } @@ -445,8 +445,7 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - - this._handle_error('CompleteMultipartUpload', res) + this.handleError(res, 'CompleteMultipartUpload') } /** @@ -480,18 +479,15 @@ export class S3Client extends AWSClient { const res = await http.asyncRequest(method, signedRequest.url, signedRequest.body || null, { headers: signedRequest.headers, }) - this._handle_error('AbortMultipartUpload', res) + this.handleError(res, 'AbortMultipartUpload') } - _handle_error(operation: S3Operation, response: RefinedResponse) { - const status: number = response.status - const errorCode: number = response.error_code - const errorMessage: string = response.error - - // We consider codes 200-299 as success - if (status >= 200 && status < 300 && errorMessage == '' && errorCode === 0) { - return - } + handleError(response: RefinedResponse, operation?: string): boolean { + // As we are overriding the AWSClient method: call the parent class handleError method + const errored = super.handleError(response); + if (!errored) { + return false; + } // A 301 response is returned when the bucket is not found. // Generally meaning that either the bucket name is wrong or the @@ -499,8 +495,9 @@ export class S3Client extends AWSClient { // // See: https://github.com/grafana/k6/issues/2474 // See: https://github.com/golang/go/issues/49281 - if (status == 301 || (errorMessage && errorMessage.startsWith('301'))) { - throw new S3ServiceError('Resource not found', 'ResourceNotFound', operation) + const errorMessage: string = response.error + if (response.status == 301 || (errorMessage && errorMessage.startsWith('301'))) { + throw new S3ServiceError('Resource not found', 'ResourceNotFound', operation as S3Operation) } const awsError = AWSError.parseXML(response.body as string) @@ -508,7 +505,7 @@ export class S3Client extends AWSClient { case 'AuthorizationHeaderMalformed': throw new InvalidSignatureError(awsError.message, awsError.code) default: - throw new S3ServiceError(awsError.message, awsError.code || 'unknown', operation) + throw new S3ServiceError(awsError.message, awsError.code || 'unknown', operation as S3Operation) } } } diff --git a/src/internal/secrets-manager.ts b/src/internal/secrets-manager.ts index 150e07f..1377565 100644 --- a/src/internal/secrets-manager.ts +++ b/src/internal/secrets-manager.ts @@ -70,7 +70,7 @@ export class SecretsManagerClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(SecretsManagerOperation.ListSecrets, res) + this.handleError(res, SecretsManagerOperation.ListSecrets) const json: JSONArray = res.json('SecretList') as JSONArray return json.map((s) => Secret.fromJSON(s as JSONObject)) @@ -103,7 +103,7 @@ export class SecretsManagerClient extends AWSClient { headers: signedRequest.headers, }) - this._handle_error(SecretsManagerOperation.GetSecretValue, res) + this.handleError(res, SecretsManagerOperation.GetSecretValue) return Secret.fromJSON(res.json() as JSONObject) } @@ -162,7 +162,7 @@ export class SecretsManagerClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(SecretsManagerOperation.CreateSecret, res) + this.handleError(res, SecretsManagerOperation.CreateSecret) return Secret.fromJSON(res.json() as JSONObject) } @@ -202,7 +202,7 @@ export class SecretsManagerClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(SecretsManagerOperation.PutSecretValue, res) + this.handleError(res, SecretsManagerOperation.PutSecretValue) return Secret.fromJSON(res.json() as JSONObject) } @@ -251,18 +251,17 @@ export class SecretsManagerClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(SecretsManagerOperation.DeleteSecret, res) + this.handleError(res, SecretsManagerOperation.DeleteSecret) } - _handle_error( - operation: SecretsManagerOperation, - response: RefinedResponse - ) { - const errorCode = response.error_code - if (errorCode === 0) { - return + + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation) + if (!errored) { + return false } + const errorCode = response.error_code const error = response.json() as JSONObject if (errorCode >= 1400 && errorCode <= 1499) { // In the event of certain errors, the message is not set. @@ -276,16 +275,18 @@ export class SecretsManagerClient extends AWSClient { } // Otherwise throw a standard service error - throw new SecretsManagerServiceError(errorMessage, error.__type as string, operation) + throw new SecretsManagerServiceError(errorMessage, error.__type as string, operation as SecretsManagerOperation) } if (errorCode === 1500) { throw new SecretsManagerServiceError( 'An error occured on the server side', 'InternalServiceError', - operation + operation as SecretsManagerOperation ) } + + return true } } diff --git a/src/internal/signature.ts b/src/internal/signature.ts index 79407d3..847a722 100644 --- a/src/internal/signature.ts +++ b/src/internal/signature.ts @@ -231,7 +231,6 @@ export class SignatureV4 { if (this.credentials.sessionToken) { request.query[constants.AMZ_TOKEN_QUERY_PARAM] = this.credentials.sessionToken } - // Add base signing query parameters to the request, as described in the documentation // @see https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html request.query[constants.AMZ_ALGORITHM_QUERY_PARAM] = constants.SIGNING_ALGORITHM_IDENTIFIER @@ -270,7 +269,7 @@ export class SignatureV4 { ) // If a request path was provided, add it to the URL - let url = request.endpoint.href + let url = originalRequest.endpoint.href if (request.path) { // Ensure there is a trailing slash at the end of the URL // so that appending the path does not result in a malformed URL. diff --git a/src/internal/sqs.ts b/src/internal/sqs.ts index b65aef8..35c8f77 100644 --- a/src/internal/sqs.ts +++ b/src/internal/sqs.ts @@ -235,6 +235,40 @@ export class SQSClient extends AWSClient { default: throw new SQSServiceError(errorMessage, error.__type as string, operation) } + + return true + } + + protected handleError( + response: RefinedResponse, + operation?: string + ): boolean { + const errored = super.handleError(response) + if (!errored) { + return false + } + + const errorCode: number = response.error_code + + if (errorCode === 0) { + return false + } + + const error = response.json() as JSONObject + + const errorMessage: string = + (error.Message as string) || (error.message as string) || (error.__type as string) + + switch (error.__type) { + case 'InvalidSignatureException': + throw new InvalidSignatureError(errorMessage, error.__type) + default: + throw new SQSServiceError( + errorMessage, + error.__type as string, + operation as SQSOperation + ) + } } } diff --git a/src/internal/ssm.ts b/src/internal/ssm.ts index b9e8aeb..d866d21 100644 --- a/src/internal/ssm.ts +++ b/src/internal/ssm.ts @@ -73,20 +73,18 @@ export class SystemsManagerClient extends AWSClient { const res = await http.asyncRequest(this.method, signedRequest.url, signedRequest.body, { headers: signedRequest.headers, }) - this._handle_error(SystemsManagerOperation.GetParameter, res) + this.handleError(res, SystemsManagerOperation.GetParameter) return SystemsManagerParameter.fromJSON(res.json() as JSONObject) } - _handle_error( - operation: SystemsManagerOperation, - response: RefinedResponse - ) { - const errorCode = response.error_code - if (errorCode === 0) { - return + protected handleError(response: RefinedResponse, operation?: string): boolean { + const errored = super.handleError(response, operation); + if (!errored) { + return false } + const errorCode = response.error_code const error = response.json() as JSONObject if (errorCode >= 1400 && errorCode <= 1499) { // In the event of certain errors, the message is not set. @@ -100,16 +98,18 @@ export class SystemsManagerClient extends AWSClient { } // Otherwise throw a standard service error - throw new SystemsManagerServiceError(errorMessage, error.__type as string, operation) + throw new SystemsManagerServiceError(errorMessage, error.__type as string, operation as SystemsManagerOperation) } if (errorCode === 1500) { throw new SystemsManagerServiceError( 'An error occured on the server side', 'InternalServiceError', - operation + operation as SystemsManagerOperation ) } + + return true } }