
software.amazon.awssdk.http.DefaultSdkHttpFullRequest Maven / Gradle / Ivy
/*
* 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;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Immutable;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.internal.http.LowCopyListMap;
import software.amazon.awssdk.utils.CollectionUtils;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.http.SdkHttpUtils;
/**
* Internal implementation of {@link SdkHttpFullRequest}, buildable via {@link SdkHttpFullRequest#builder()}. Provided to HTTP
* implementation to execute a request.
*/
@SdkInternalApi
@Immutable
final class DefaultSdkHttpFullRequest implements SdkHttpFullRequest {
private final String protocol;
private final String host;
private final Integer port;
private final String path;
private final LowCopyListMap.ForBuildable queryParameters;
private final LowCopyListMap.ForBuildable headers;
private final SdkHttpMethod httpMethod;
private final ContentStreamProvider contentStreamProvider;
private DefaultSdkHttpFullRequest(Builder builder) {
this.protocol = standardizeProtocol(builder.protocol);
this.host = Validate.paramNotNull(builder.host, "host");
this.port = standardizePort(builder.port);
this.path = standardizePath(builder.path);
this.httpMethod = Validate.paramNotNull(builder.httpMethod, "method");
this.contentStreamProvider = builder.contentStreamProvider;
this.queryParameters = builder.queryParameters.forBuildable();
this.headers = builder.headers.forBuildable();
}
private String standardizeProtocol(String protocol) {
Validate.paramNotNull(protocol, "protocol");
String standardizedProtocol = StringUtils.lowerCase(protocol);
Validate.isTrue(standardizedProtocol.equals("http") || standardizedProtocol.equals("https"),
"Protocol must be 'http' or 'https', but was %s", protocol);
return standardizedProtocol;
}
private String standardizePath(String path) {
if (StringUtils.isEmpty(path)) {
return "";
}
StringBuilder standardizedPath = new StringBuilder();
// Path must always start with '/'
if (!path.startsWith("/")) {
standardizedPath.append('/');
}
standardizedPath.append(path);
return standardizedPath.toString();
}
private Integer standardizePort(Integer port) {
Validate.isTrue(port == null || port >= -1,
"Port must be positive (or null/-1 to indicate no port), but was '%s'", port);
if (port != null && port == -1) {
return null;
}
return port;
}
@Override
public String protocol() {
return protocol;
}
@Override
public String host() {
return host;
}
@Override
public int port() {
return Optional.ofNullable(port).orElseGet(() -> SdkHttpUtils.standardPort(protocol()));
}
@Override
public Map> headers() {
return headers.forExternalRead();
}
@Override
public List matchingHeaders(String header) {
return unmodifiableList(headers.forInternalRead().getOrDefault(header, emptyList()));
}
@Override
public Optional firstMatchingHeader(String headerName) {
List headers = this.headers.forInternalRead().get(headerName);
if (headers == null || headers.isEmpty()) {
return Optional.empty();
}
String header = headers.get(0);
if (StringUtils.isEmpty(header)) {
return Optional.empty();
}
return Optional.of(header);
}
@Override
public Optional firstMatchingHeader(Collection headersToFind) {
for (String headerName : headersToFind) {
Optional header = firstMatchingHeader(headerName);
if (header.isPresent()) {
return header;
}
}
return Optional.empty();
}
@Override
public void forEachHeader(BiConsumer super String, ? super List> consumer) {
headers.forInternalRead().forEach((k, v) -> consumer.accept(k, Collections.unmodifiableList(v)));
}
@Override
public void forEachRawQueryParameter(BiConsumer super String, ? super List> consumer) {
queryParameters.forInternalRead().forEach((k, v) -> consumer.accept(k, Collections.unmodifiableList(v)));
}
@Override
public int numHeaders() {
return headers.forInternalRead().size();
}
@Override
public int numRawQueryParameters() {
return queryParameters.forInternalRead().size();
}
@Override
public Optional encodedQueryParameters() {
return SdkHttpUtils.encodeAndFlattenQueryParameters(queryParameters.forInternalRead());
}
@Override
public Optional encodedQueryParametersAsFormData() {
return SdkHttpUtils.encodeAndFlattenFormData(queryParameters.forInternalRead());
}
@Override
public String encodedPath() {
return path;
}
@Override
public Map> rawQueryParameters() {
return queryParameters.forExternalRead();
}
@Override
public Optional firstMatchingRawQueryParameter(String key) {
List values = queryParameters.forInternalRead().get(key);
return values == null ? Optional.empty() : values.stream().findFirst();
}
@Override
public Optional firstMatchingRawQueryParameter(Collection keys) {
for (String key : keys) {
Optional result = firstMatchingRawQueryParameter(key);
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}
@Override
public List firstMatchingRawQueryParameters(String key) {
List values = queryParameters.forInternalRead().get(key);
return values == null ? emptyList() : unmodifiableList(values);
}
@Override
public SdkHttpMethod method() {
return httpMethod;
}
@Override
public Optional contentStreamProvider() {
return Optional.ofNullable(contentStreamProvider);
}
@Override
public SdkHttpFullRequest.Builder toBuilder() {
return new Builder(this);
}
@Override
public String toString() {
return ToString.builder("DefaultSdkHttpFullRequest")
.add("httpMethod", httpMethod)
.add("protocol", protocol)
.add("host", host)
.add("port", port)
.add("encodedPath", path)
.add("headers", headers.forInternalRead().keySet())
.add("queryParameters", queryParameters.forInternalRead().keySet())
.build();
}
/**
* Builder for a {@link DefaultSdkHttpFullRequest}.
*/
static final class Builder implements SdkHttpFullRequest.Builder {
private String protocol;
private String host;
private Integer port;
private String path;
private LowCopyListMap.ForBuilder queryParameters;
private LowCopyListMap.ForBuilder headers;
private SdkHttpMethod httpMethod;
private ContentStreamProvider contentStreamProvider;
Builder() {
queryParameters = LowCopyListMap.emptyQueryParameters();
headers = LowCopyListMap.emptyHeaders();
}
Builder(DefaultSdkHttpFullRequest request) {
queryParameters = request.queryParameters.forBuilder();
headers = request.headers.forBuilder();
protocol = request.protocol;
host = request.host;
port = request.port;
path = request.path;
httpMethod = request.httpMethod;
contentStreamProvider = request.contentStreamProvider;
}
@Override
public String protocol() {
return protocol;
}
@Override
public SdkHttpFullRequest.Builder protocol(String protocol) {
this.protocol = protocol;
return this;
}
@Override
public String host() {
return host;
}
@Override
public SdkHttpFullRequest.Builder host(String host) {
this.host = host;
return this;
}
@Override
public Integer port() {
return port;
}
@Override
public SdkHttpFullRequest.Builder port(Integer port) {
this.port = port;
return this;
}
@Override
public DefaultSdkHttpFullRequest.Builder encodedPath(String path) {
this.path = path;
return this;
}
@Override
public String encodedPath() {
return path;
}
@Override
public DefaultSdkHttpFullRequest.Builder putRawQueryParameter(String paramName, List paramValues) {
this.queryParameters.forInternalWrite().put(paramName, new ArrayList<>(paramValues));
return this;
}
@Override
public SdkHttpFullRequest.Builder appendRawQueryParameter(String paramName, String paramValue) {
this.queryParameters.forInternalWrite().computeIfAbsent(paramName, k -> new ArrayList<>()).add(paramValue);
return this;
}
@Override
public DefaultSdkHttpFullRequest.Builder rawQueryParameters(Map> queryParameters) {
this.queryParameters.setFromExternal(queryParameters);
return this;
}
@Override
public Builder removeQueryParameter(String paramName) {
this.queryParameters.forInternalWrite().remove(paramName);
return this;
}
@Override
public Builder clearQueryParameters() {
this.queryParameters.forInternalWrite().clear();
return this;
}
@Override
public Map> rawQueryParameters() {
return CollectionUtils.unmodifiableMapOfLists(queryParameters.forInternalRead());
}
@Override
public DefaultSdkHttpFullRequest.Builder method(SdkHttpMethod httpMethod) {
this.httpMethod = httpMethod;
return this;
}
@Override
public SdkHttpMethod method() {
return httpMethod;
}
@Override
public DefaultSdkHttpFullRequest.Builder putHeader(String headerName, List headerValues) {
this.headers.forInternalWrite().put(headerName, new ArrayList<>(headerValues));
return this;
}
@Override
public SdkHttpFullRequest.Builder appendHeader(String headerName, String headerValue) {
this.headers.forInternalWrite().computeIfAbsent(headerName, k -> new ArrayList<>()).add(headerValue);
return this;
}
@Override
public DefaultSdkHttpFullRequest.Builder headers(Map> headers) {
this.headers.setFromExternal(headers);
return this;
}
@Override
public SdkHttpFullRequest.Builder removeHeader(String headerName) {
this.headers.forInternalWrite().remove(headerName);
return this;
}
@Override
public SdkHttpFullRequest.Builder clearHeaders() {
this.headers.clear();
return this;
}
@Override
public Map> headers() {
return CollectionUtils.unmodifiableMapOfLists(this.headers.forInternalRead());
}
@Override
public List matchingHeaders(String header) {
return unmodifiableList(headers.forInternalRead().getOrDefault(header, emptyList()));
}
@Override
public Optional firstMatchingHeader(String headerName) {
List headers = this.headers.forInternalRead().get(headerName);
if (headers == null || headers.isEmpty()) {
return Optional.empty();
}
String header = headers.get(0);
if (StringUtils.isEmpty(header)) {
return Optional.empty();
}
return Optional.of(header);
}
@Override
public Optional firstMatchingHeader(Collection headersToFind) {
for (String headerName : headersToFind) {
Optional header = firstMatchingHeader(headerName);
if (header.isPresent()) {
return header;
}
}
return Optional.empty();
}
@Override
public void forEachHeader(BiConsumer super String, ? super List> consumer) {
headers.forInternalRead().forEach((k, v) -> consumer.accept(k, unmodifiableList(v)));
}
@Override
public void forEachRawQueryParameter(BiConsumer super String, ? super List> consumer) {
queryParameters.forInternalRead().forEach((k, v) -> consumer.accept(k, unmodifiableList(v)));
}
@Override
public int numHeaders() {
return headers.forInternalRead().size();
}
@Override
public int numRawQueryParameters() {
return queryParameters.forInternalRead().size();
}
@Override
public Optional encodedQueryParameters() {
return SdkHttpUtils.encodeAndFlattenQueryParameters(queryParameters.forInternalRead());
}
@Override
public DefaultSdkHttpFullRequest.Builder contentStreamProvider(ContentStreamProvider contentStreamProvider) {
this.contentStreamProvider = contentStreamProvider;
return this;
}
@Override
public ContentStreamProvider contentStreamProvider() {
return contentStreamProvider;
}
@Override
public SdkHttpFullRequest.Builder copy() {
return build().toBuilder();
}
@Override
public SdkHttpFullRequest.Builder applyMutation(Consumer mutator) {
mutator.accept(this);
return this;
}
@Override
public DefaultSdkHttpFullRequest build() {
return new DefaultSdkHttpFullRequest(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy