1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.http; 17 18 import static java.util.Collections.singletonList; 19 20 import java.net.URI; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Optional; 24 import java.util.function.Consumer; 25 import software.amazon.awssdk.annotations.Immutable; 26 import software.amazon.awssdk.annotations.SdkPublicApi; 27 import software.amazon.awssdk.utils.http.SdkHttpUtils; 28 29 /** 30 * An immutable HTTP request with a possible HTTP body. 31 * 32 * <p>All implementations of this interface MUST be immutable. Instead of implementing this interface, consider using 33 * {@link #builder()} to create an instance.</p> 34 */ 35 @SdkPublicApi 36 @Immutable 37 public interface SdkHttpFullRequest 38 extends SdkHttpRequest { 39 /** 40 * @return Builder instance to construct a {@link DefaultSdkHttpFullRequest}. 41 */ builder()42 static SdkHttpFullRequest.Builder builder() { 43 return new DefaultSdkHttpFullRequest.Builder(); 44 } 45 46 @Override toBuilder()47 SdkHttpFullRequest.Builder toBuilder(); 48 49 /** 50 * @return The optional {@link ContentStreamProvider} for this request. 51 */ contentStreamProvider()52 Optional<ContentStreamProvider> contentStreamProvider(); 53 54 /** 55 * A mutable builder for {@link SdkHttpFullRequest}. An instance of this can be created using 56 * {@link SdkHttpFullRequest#builder()}. 57 */ 58 interface Builder extends SdkHttpRequest.Builder { 59 /** 60 * Convenience method to set the {@link #protocol()}, {@link #host()}, {@link #port()}, 61 * {@link #encodedPath()} and extracts query parameters from a {@link URI} object. 62 * 63 * @param uri URI containing protocol, host, port and path. 64 * @return This builder for method chaining. 65 */ 66 @Override uri(URI uri)67 default Builder uri(URI uri) { 68 Builder builder = this.protocol(uri.getScheme()) 69 .host(uri.getHost()) 70 .port(uri.getPort()) 71 .encodedPath(SdkHttpUtils.appendUri(uri.getRawPath(), encodedPath())); 72 if (uri.getRawQuery() != null) { 73 builder.clearQueryParameters(); 74 SdkHttpUtils.uriParams(uri) 75 .forEach(this::putRawQueryParameter); 76 } 77 return builder; 78 } 79 80 /** 81 * The protocol, exactly as it was configured with {@link #protocol(String)}. 82 */ 83 @Override protocol()84 String protocol(); 85 86 /** 87 * Configure a {@link SdkHttpRequest#protocol()} to be used in the created HTTP request. This is not validated until the 88 * http request is created. 89 */ 90 @Override protocol(String protocol)91 Builder protocol(String protocol); 92 93 /** 94 * The host, exactly as it was configured with {@link #host(String)}. 95 */ 96 @Override host()97 String host(); 98 99 /** 100 * Configure a {@link SdkHttpRequest#host()} to be used in the created HTTP request. This is not validated until the 101 * http request is created. 102 */ 103 @Override host(String host)104 Builder host(String host); 105 106 /** 107 * The port, exactly as it was configured with {@link #port(Integer)}. 108 */ 109 @Override port()110 Integer port(); 111 112 /** 113 * Configure a {@link SdkHttpRequest#port()} to be used in the created HTTP request. This is not validated until the 114 * http request is created. In order to simplify mapping from a {@link URI}, "-1" will be treated as "null" when the http 115 * request is created. 116 */ 117 @Override port(Integer port)118 Builder port(Integer port); 119 120 /** 121 * The path, exactly as it was configured with {@link #encodedPath(String)}. 122 */ 123 @Override encodedPath()124 String encodedPath(); 125 126 /** 127 * Configure an {@link SdkHttpRequest#encodedPath()} to be used in the created HTTP request. This is not validated 128 * until the http request is created. This path MUST be URL encoded. 129 * 130 * <p>Justification of requirements: The path must be encoded when it is configured, because there is no way for the HTTP 131 * implementation to distinguish a "/" that is part of a resource name that should be encoded as "%2F" from a "/" that is 132 * part of the actual path.</p> 133 */ 134 @Override encodedPath(String path)135 Builder encodedPath(String path); 136 137 /** 138 * The query parameters, exactly as they were configured with {@link #rawQueryParameters(Map)}, 139 * {@link #putRawQueryParameter(String, String)} and {@link #putRawQueryParameter(String, List)}. 140 */ 141 @Override rawQueryParameters()142 Map<String, List<String>> rawQueryParameters(); 143 144 /** 145 * Add a single un-encoded query parameter to be included in the created HTTP request. 146 * 147 * <p>This completely <b>OVERRIDES</b> any values already configured with this parameter name in the builder.</p> 148 * 149 * @param paramName The name of the query parameter to add 150 * @param paramValue The un-encoded value for the query parameter. 151 */ 152 @Override putRawQueryParameter(String paramName, String paramValue)153 default Builder putRawQueryParameter(String paramName, String paramValue) { 154 return putRawQueryParameter(paramName, singletonList(paramValue)); 155 } 156 157 /** 158 * Add a single un-encoded query parameter to be included in the created HTTP request. 159 * 160 * <p>This will <b>ADD</b> the value to any existing values already configured with this parameter name in 161 * the builder.</p> 162 * 163 * @param paramName The name of the query parameter to add 164 * @param paramValue The un-encoded value for the query parameter. 165 */ 166 @Override appendRawQueryParameter(String paramName, String paramValue)167 Builder appendRawQueryParameter(String paramName, String paramValue); 168 169 /** 170 * Add a single un-encoded query parameter with multiple values to be included in the created HTTP request. 171 * 172 * <p>This completely <b>OVERRIDES</b> any values already configured with this parameter name in the builder.</p> 173 * 174 * @param paramName The name of the query parameter to add 175 * @param paramValues The un-encoded values for the query parameter. 176 */ 177 @Override putRawQueryParameter(String paramName, List<String> paramValues)178 Builder putRawQueryParameter(String paramName, List<String> paramValues); 179 180 /** 181 * Configure an {@link SdkHttpRequest#rawQueryParameters()} to be used in the created HTTP request. This is not validated 182 * until the http request is created. This overrides any values currently configured in the builder. The query parameters 183 * MUST NOT be URL encoded. 184 * 185 * <p>Justification of requirements: The query parameters must not be encoded when they are configured because some HTTP 186 * implementations perform this encoding automatically.</p> 187 */ 188 @Override rawQueryParameters(Map<String, List<String>> queryParameters)189 Builder rawQueryParameters(Map<String, List<String>> queryParameters); 190 191 /** 192 * Remove all values for the requested query parameter from this builder. 193 */ 194 @Override removeQueryParameter(String paramName)195 Builder removeQueryParameter(String paramName); 196 197 /** 198 * Removes all query parameters from this builder. 199 */ 200 @Override clearQueryParameters()201 Builder clearQueryParameters(); 202 203 /** 204 * The path, exactly as it was configured with {@link #method(SdkHttpMethod)}. 205 */ 206 @Override method()207 SdkHttpMethod method(); 208 209 /** 210 * Configure an {@link SdkHttpRequest#method()} to be used in the created HTTP request. This is not validated 211 * until the http request is created. 212 */ 213 @Override method(SdkHttpMethod httpMethod)214 Builder method(SdkHttpMethod httpMethod); 215 216 /** 217 * The query parameters, exactly as they were configured with {@link #headers(Map)}, 218 * {@link #putHeader(String, String)} and {@link #putHeader(String, List)}. 219 */ 220 @Override headers()221 Map<String, List<String>> headers(); 222 223 /** 224 * Add a single header to be included in the created HTTP request. 225 * 226 * <p>This completely <b>OVERRIDES</b> any values already configured with this header name in the builder.</p> 227 * 228 * @param headerName The name of the header to add (eg. "Host") 229 * @param headerValue The value for the header 230 */ 231 @Override putHeader(String headerName, String headerValue)232 default Builder putHeader(String headerName, String headerValue) { 233 return putHeader(headerName, singletonList(headerValue)); 234 } 235 236 /** 237 * Add a single header with multiple values to be included in the created HTTP request. 238 * 239 * <p>This completely <b>OVERRIDES</b> any values already configured with this header name in the builder.</p> 240 * 241 * @param headerName The name of the header to add 242 * @param headerValues The values for the header 243 */ 244 @Override putHeader(String headerName, List<String> headerValues)245 Builder putHeader(String headerName, List<String> headerValues); 246 247 /** 248 * Add a single header to be included in the created HTTP request. 249 * 250 * <p>This will <b>ADD</b> the value to any existing values already configured with this header name in 251 * the builder.</p> 252 * 253 * @param headerName The name of the header to add 254 * @param headerValue The value for the header 255 */ 256 @Override appendHeader(String headerName, String headerValue)257 Builder appendHeader(String headerName, String headerValue); 258 259 /** 260 * Configure an {@link SdkHttpRequest#headers()} to be used in the created HTTP request. This is not validated 261 * until the http request is created. This overrides any values currently configured in the builder. 262 */ 263 @Override headers(Map<String, List<String>> headers)264 Builder headers(Map<String, List<String>> headers); 265 266 /** 267 * Remove all values for the requested header from this builder. 268 */ 269 @Override removeHeader(String headerName)270 Builder removeHeader(String headerName); 271 272 /** 273 * Removes all headers from this builder. 274 */ 275 @Override clearHeaders()276 Builder clearHeaders(); 277 278 /** 279 * Set the {@link ContentStreamProvider} for this request. 280 * 281 * @param contentStreamProvider The ContentStreamProvider. 282 * @return This object for method chaining. 283 */ contentStreamProvider(ContentStreamProvider contentStreamProvider)284 Builder contentStreamProvider(ContentStreamProvider contentStreamProvider); 285 286 /** 287 * @return The {@link ContentStreamProvider} for this request. 288 */ contentStreamProvider()289 ContentStreamProvider contentStreamProvider(); 290 291 @Override copy()292 SdkHttpFullRequest.Builder copy(); 293 294 @Override applyMutation(Consumer<SdkHttpRequest.Builder> mutator)295 SdkHttpFullRequest.Builder applyMutation(Consumer<SdkHttpRequest.Builder> mutator); 296 297 @Override build()298 SdkHttpFullRequest build(); 299 } 300 301 } 302