diff --git a/core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/SigningUtils.java b/core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/SigningUtils.java index aa6bebf2e8ae..a6807bcad407 100644 --- a/core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/SigningUtils.java +++ b/core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/SigningUtils.java @@ -15,6 +15,16 @@ package software.amazon.awssdk.authcrt.signer.internal; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.AUTHORIZATION; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.HOST; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_ALGORITHM; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_CONTENT_SHA256; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_CREDENTIAL; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_DATE; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_EXPIRES; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_SIGNATURE; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_SIGNED_HEADERS; + import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; @@ -42,22 +52,11 @@ public class SigningUtils { */ public static final ExecutionAttribute SIGNING_CLOCK = new ExecutionAttribute<>("SigningClock"); - private static final String BODY_HASH_NAME = "x-amz-content-sha256"; - private static final String DATE_NAME = "X-Amz-Date"; - private static final String AUTHORIZATION_NAME = "Authorization"; private static final String REGION_SET_NAME = "X-amz-region-set"; - private static final String SIGNATURE_NAME = "X-Amz-Signature"; - private static final String CREDENTIAL_NAME = "X-Amz-Credential"; - private static final String ALGORITHM_NAME = "X-Amz-Algorithm"; - private static final String SIGNED_HEADERS_NAME = "X-Amz-SignedHeaders"; - private static final String EXPIRES_NAME = "X-Amz-Expires"; - private static final Set FORBIDDEN_HEADERS = buildForbiddenHeaderSet(); private static final Set FORBIDDEN_PARAMS = buildForbiddenQueryParamSet(); - private static final String HOST_HEADER = "Host"; - private SigningUtils() { } @@ -125,7 +124,7 @@ public static SdkHttpFullRequest sanitizeSdkRequestForCrtSigning(SdkHttpFullRequ String hostHeader = SdkHttpUtils.isUsingStandardPort(request.protocol(), request.port()) ? request.host() : request.host() + ":" + request.port(); - builder.putHeader(HOST_HEADER, hostHeader); + builder.putHeader(HOST, hostHeader); builder.clearQueryParameters(); @@ -142,9 +141,9 @@ public static SdkHttpFullRequest sanitizeSdkRequestForCrtSigning(SdkHttpFullRequ private static Set buildForbiddenHeaderSet() { Set forbiddenHeaders = new TreeSet(String.CASE_INSENSITIVE_ORDER); - forbiddenHeaders.add(BODY_HASH_NAME); - forbiddenHeaders.add(DATE_NAME); - forbiddenHeaders.add(AUTHORIZATION_NAME); + forbiddenHeaders.add(X_AMZ_CONTENT_SHA256); + forbiddenHeaders.add(X_AMZ_DATE); + forbiddenHeaders.add(AUTHORIZATION); forbiddenHeaders.add(REGION_SET_NAME); return forbiddenHeaders; @@ -153,13 +152,13 @@ private static Set buildForbiddenHeaderSet() { private static Set buildForbiddenQueryParamSet() { Set forbiddenParams = new TreeSet(String.CASE_INSENSITIVE_ORDER); - forbiddenParams.add(SIGNATURE_NAME); - forbiddenParams.add(DATE_NAME); - forbiddenParams.add(CREDENTIAL_NAME); - forbiddenParams.add(ALGORITHM_NAME); - forbiddenParams.add(SIGNED_HEADERS_NAME); + forbiddenParams.add(X_AMZ_SIGNATURE); + forbiddenParams.add(X_AMZ_DATE); + forbiddenParams.add(X_AMZ_CREDENTIAL); + forbiddenParams.add(X_AMZ_ALGORITHM); + forbiddenParams.add(X_AMZ_SIGNED_HEADERS); forbiddenParams.add(REGION_SET_NAME); - forbiddenParams.add(EXPIRES_NAME); + forbiddenParams.add(X_AMZ_EXPIRES); return forbiddenParams; } diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/crt/internal/util/CrtUtils.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/crt/internal/util/CrtUtils.java index e77960ffe76b..dd0118f4f405 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/crt/internal/util/CrtUtils.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/crt/internal/util/CrtUtils.java @@ -18,6 +18,7 @@ import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.AUTHORIZATION; import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.HOST; import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_ALGORITHM; +import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_CONTENT_SHA256; import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_CREDENTIAL; import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_DATE; import static software.amazon.awssdk.http.auth.aws.signer.SignerConstant.X_AMZ_EXPIRES; @@ -39,11 +40,10 @@ @SdkInternalApi public final class CrtUtils { - private static final String BODY_HASH_NAME = "x-amz-content-sha256"; private static final String REGION_SET_NAME = "X-amz-region-set"; private static final Set FORBIDDEN_HEADERS = - Stream.of(BODY_HASH_NAME, X_AMZ_DATE, AUTHORIZATION, REGION_SET_NAME) + Stream.of(X_AMZ_CONTENT_SHA256, X_AMZ_DATE, AUTHORIZATION, REGION_SET_NAME) .collect(Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))); private static final Set FORBIDDEN_PARAMS = Stream.of(X_AMZ_SIGNATURE, X_AMZ_DATE, X_AMZ_CREDENTIAL, X_AMZ_ALGORITHM, X_AMZ_SIGNED_HEADERS, REGION_SET_NAME, diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkInputStream.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkInputStream.java index a1638a5d725b..bfb062f22cf2 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkInputStream.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkInputStream.java @@ -18,7 +18,7 @@ import java.io.IOException; import java.io.InputStream; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.http.auth.aws.internal.signer.io.SdkLengthAwareInputStream; +import software.amazon.awssdk.utils.io.SdkLengthAwareInputStream; /** * A wrapped stream to represent a "chunk" of data diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/Releasable.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/Releasable.java deleted file mode 100644 index 147be9d9fc6d..000000000000 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/Releasable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.http.auth.aws.internal.signer.io; - -import static software.amazon.awssdk.utils.IoUtils.closeQuietly; - -import java.io.Closeable; -import org.slf4j.Logger; -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * Used for releasing a resource. - *

- * For example, the creation of a {@code ResettableInputStream} would entail physically opening a file. If the opened file is - * meant to be closed only (in a finally block) by the very same code block that created it, then it is necessary that the release - * method must not be called while the execution is made in other stack frames. - *

- * In such case, as other stack frames may inadvertently or indirectly call the close method of the stream, the creator of the - * stream would need to explicitly disable the accidental closing via {@code ResettableInputStream#disableClose()}, so that the - * release method becomes the only way to truly close the opened file. - */ -@SdkInternalApi -public interface Releasable { - /** - * Releases the given {@link Closeable} especially if it was an instance of {@link Releasable}. - *

- * For example, the creation of a {@code ResettableInputStream} would entail physically opening a file. If the opened file is - * meant to be closed only (in a finally block) by the very same code block that created it, then it is necessary that the - * release method must not be called while the execution is made in other stack frames. - *

- * In such case, as other stack frames may inadvertently or indirectly call the close method of the stream, the creator of the - * stream would need to explicitly disable the accidental closing via {@code ResettableInputStream#disableClose()}, so that - * the release method becomes the only way to truly close the opened file. - */ - static void release(Closeable is, Logger log) { - closeQuietly(is, log); - if (is instanceof Releasable) { - Releasable r = (Releasable) is; - r.release(); - } - } - - /** - * Releases the allocated resource. This method should not be called except by the caller who allocated the resource at the - * very top of the call stack. This allows, typically, a {@link Closeable} resource to be not unintentionally released owing - * to the calling of the {@link Closeable#close()} methods by implementation deep down in the call stack. - *

- * For example, the creation of a {@code ResettableInputStream} would entail physically opening a file. If the opened file is - * meant to be closed only (in a finally block) by the very same code block that created it, then it is necessary that the - * release method must not be called while the execution is made in other stack frames. - *

- * In such case, as other stack frames may inadvertently or indirectly call the close method of the stream, the creator of the - * stream would need to explicitly disable the accidental closing via {@code ResettableInputStream#disableClose()}, so that - * the release method becomes the only way to truly close the opened file. - */ - void release(); -} diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/SdkLengthAwareInputStream.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/SdkLengthAwareInputStream.java deleted file mode 100644 index b7ec9ad4442b..000000000000 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/SdkLengthAwareInputStream.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.http.auth.aws.internal.signer.io; - -import static software.amazon.awssdk.utils.NumericUtils.saturatedCast; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.Logger; -import software.amazon.awssdk.utils.Validate; - -/** - * An {@code InputStream} that is aware of its length. The main purpose of this class is to support truncating streams to a length - * that is shorter than the total length of the stream. - */ -@SdkInternalApi -public class SdkLengthAwareInputStream extends FilterInputStream { - private static final Logger LOG = Logger.loggerFor(SdkLengthAwareInputStream.class); - private long length; - private long remaining; - - public SdkLengthAwareInputStream(InputStream in, long length) { - super(in); - this.length = Validate.isNotNegative(length, "length"); - this.remaining = this.length; - } - - @Override - public int read() throws IOException { - if (!hasMoreBytes()) { - LOG.debug(() -> String.format("Specified InputStream length of %d has been reached. Returning EOF.", length)); - return -1; - } - - int read = super.read(); - if (read != -1) { - remaining--; - } - return read; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (!hasMoreBytes()) { - LOG.debug(() -> String.format("Specified InputStream length of %d has been reached. Returning EOF.", length)); - return -1; - } - - len = Math.min(len, saturatedCast(remaining)); - int read = super.read(b, off, len); - if (read > 0) { - remaining -= read; - } - - return read; - } - - @Override - public long skip(long requestedBytesToSkip) throws IOException { - requestedBytesToSkip = Math.min(requestedBytesToSkip, remaining); - long skippedActual = super.skip(requestedBytesToSkip); - remaining -= skippedActual; - return skippedActual; - } - - @Override - public int available() throws IOException { - int streamAvailable = super.available(); - return Math.min(streamAvailable, saturatedCast(remaining)); - } - - @Override - public void mark(int readlimit) { - super.mark(readlimit); - // mark() causes reset() to change the stream's position back to the current position. Therefore, when reset() is called, - // the new length of the stream will be equal to the current value of 'remaining'. - length = remaining; - } - - @Override - public void reset() throws IOException { - super.reset(); - remaining = length; - } - - public long remaining() { - return remaining; - } - - private boolean hasMoreBytes() { - return remaining > 0; - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.java index deb354d276dd..edf8a3fcae37 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.java @@ -25,11 +25,11 @@ import org.reactivestreams.Subscriber; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.exception.NonRetryableException; -import software.amazon.awssdk.core.internal.io.SdkLengthAwareInputStream; import software.amazon.awssdk.core.internal.util.Mimetype; import software.amazon.awssdk.core.internal.util.NoopSubscription; import software.amazon.awssdk.utils.Validate; import software.amazon.awssdk.utils.async.InputStreamConsumingPublisher; +import software.amazon.awssdk.utils.io.SdkLengthAwareInputStream; /** * An implementation of {@link AsyncRequestBody} that allows performing a blocking write of an input stream to a downstream diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java index 521155a0cd0c..0a7c4df51a02 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java @@ -37,7 +37,6 @@ import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute; -import software.amazon.awssdk.core.internal.io.SdkLengthAwareInputStream; import software.amazon.awssdk.core.internal.util.MetricUtils; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.signer.Signer; @@ -49,6 +48,7 @@ import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.StringUtils; +import software.amazon.awssdk.utils.io.SdkLengthAwareInputStream; @SdkInternalApi public abstract class BaseClientHandler { diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStage.java index 0655d62d3f27..7618657e2a5c 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStage.java @@ -26,7 +26,6 @@ import software.amazon.awssdk.core.internal.http.InterruptMonitor; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.io.SdkLengthAwareInputStream; import software.amazon.awssdk.core.internal.util.MetricUtils; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.http.ContentStreamProvider; @@ -39,6 +38,7 @@ import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Pair; +import software.amazon.awssdk.utils.io.SdkLengthAwareInputStream; /** * Delegate to the HTTP implementation to make an HTTP request and receive the response. diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStageTest.java index 7e0391389bcf..11ef4b034732 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeHttpRequestStageTest.java @@ -40,7 +40,7 @@ import software.amazon.awssdk.core.internal.http.HttpClientDependencies; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; import software.amazon.awssdk.core.internal.http.timers.TimeoutTracker; -import software.amazon.awssdk.core.internal.io.SdkLengthAwareInputStream; +import software.amazon.awssdk.utils.io.SdkLengthAwareInputStream; import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.SdkHttpClient; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStream.java b/utils/src/main/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStream.java similarity index 97% rename from core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStream.java rename to utils/src/main/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStream.java index f4ecdd2d7d23..210ced2e7afe 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStream.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStream.java @@ -13,14 +13,14 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.core.internal.io; +package software.amazon.awssdk.utils.io; import static software.amazon.awssdk.utils.NumericUtils.saturatedCast; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Validate; @@ -29,7 +29,7 @@ * the input length. If the wrapped stream has more bytes than the expected length, it will be truncated to length. If the stream * has less bytes (i.e. reaches EOF) before the expected length is reached, it will throw {@code IOException}. */ -@SdkInternalApi +@SdkProtectedApi public class SdkLengthAwareInputStream extends FilterInputStream { private static final Logger LOG = Logger.loggerFor(SdkLengthAwareInputStream.class); private final long length; diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStreamTest.java b/utils/src/test/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStreamTest.java similarity index 98% rename from core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStreamTest.java rename to utils/src/test/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStreamTest.java index 8f76213e54fc..634a3d48f43d 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStreamTest.java +++ b/utils/src/test/java/software/amazon/awssdk/utils/io/SdkLengthAwareInputStreamTest.java @@ -13,10 +13,9 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.core.internal.io; +package software.amazon.awssdk.utils.io; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -28,7 +27,6 @@ import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import software.amazon.awssdk.utils.IoUtils; class SdkLengthAwareInputStreamTest { private InputStream delegateStream;