1
15
16 package software.amazon.awssdk.http.apache.internal.impl;
17
18 import static software.amazon.awssdk.utils.NumericUtils.saturatedCast;
19
20 import java.net.URI;
21 import java.util.Arrays;
22 import java.util.List;
23 import org.apache.http.HttpEntity;
24 import org.apache.http.HttpHeaders;
25 import org.apache.http.client.config.RequestConfig;
26 import org.apache.http.client.methods.HttpDelete;
27 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
28 import org.apache.http.client.methods.HttpGet;
29 import org.apache.http.client.methods.HttpHead;
30 import org.apache.http.client.methods.HttpOptions;
31 import org.apache.http.client.methods.HttpPatch;
32 import org.apache.http.client.methods.HttpPost;
33 import org.apache.http.client.methods.HttpPut;
34 import org.apache.http.client.methods.HttpRequestBase;
35 import software.amazon.awssdk.annotations.SdkInternalApi;
36 import software.amazon.awssdk.http.HttpExecuteRequest;
37 import software.amazon.awssdk.http.SdkHttpMethod;
38 import software.amazon.awssdk.http.SdkHttpRequest;
39 import software.amazon.awssdk.http.apache.internal.ApacheHttpRequestConfig;
40 import software.amazon.awssdk.http.apache.internal.RepeatableInputStreamRequestEntity;
41 import software.amazon.awssdk.http.apache.internal.utils.ApacheUtils;
42 import software.amazon.awssdk.utils.http.SdkHttpUtils;
43
44
47 @SdkInternalApi
48 public class ApacheHttpRequestFactory {
49
50 private static final String DEFAULT_ENCODING = "UTF-8";
51
52 private static final List<String> IGNORE_HEADERS = Arrays.asList(HttpHeaders.CONTENT_LENGTH, HttpHeaders.HOST);
53
54 public HttpRequestBase create(final HttpExecuteRequest request, final ApacheHttpRequestConfig requestConfig) {
55 URI uri = request.httpRequest().getUri();
56
57 HttpRequestBase base = createApacheRequest(request, sanitizeUri(uri));
58 addHeadersToRequest(base, request.httpRequest());
59 addRequestConfig(base, request.httpRequest(), requestConfig);
60
61 return base;
62 }
63
64
72 private String sanitizeUri(URI uri) {
73 String newPath = uri.getPath().replace(", "/%2F");
74 return uri.toString().replace(uri.getPath(), newPath);
75 }
76
77 private void addRequestConfig(final HttpRequestBase base,
78 final SdkHttpRequest request,
79 final ApacheHttpRequestConfig requestConfig) {
80 int connectTimeout = saturatedCast(requestConfig.connectionTimeout().toMillis());
81 int connectAcquireTimeout = saturatedCast(requestConfig.connectionAcquireTimeout().toMillis());
82 RequestConfig.Builder requestConfigBuilder = RequestConfig
83 .custom()
84 .setConnectionRequestTimeout(connectAcquireTimeout)
85 .setConnectTimeout(connectTimeout)
86 .setSocketTimeout(saturatedCast(requestConfig.socketTimeout().toMillis()))
87 .setLocalAddress(requestConfig.localAddress());
88
89 ApacheUtils.disableNormalizeUri(requestConfigBuilder);
90
91
98 if (SdkHttpMethod.PUT == request.method() && requestConfig.expectContinueEnabled()) {
99 requestConfigBuilder.setExpectContinueEnabled(true);
100 }
101
102 base.setConfig(requestConfigBuilder.build());
103 }
104
105
106 private HttpRequestBase createApacheRequest(HttpExecuteRequest request, String uri) {
107 switch (request.httpRequest().method()) {
108 case HEAD:
109 return new HttpHead(uri);
110 case GET:
111 return new HttpGet(uri);
112 case DELETE:
113 return new HttpDelete(uri);
114 case OPTIONS:
115 return new HttpOptions(uri);
116 case PATCH:
117 return wrapEntity(request, new HttpPatch(uri));
118 case POST:
119 return wrapEntity(request, new HttpPost(uri));
120 case PUT:
121 return wrapEntity(request, new HttpPut(uri));
122 default:
123 throw new RuntimeException("Unknown HTTP method name: " + request.httpRequest().method());
124 }
125 }
126
127 private HttpRequestBase wrapEntity(HttpExecuteRequest request,
128 HttpEntityEnclosingRequestBase entityEnclosingRequest) {
129
130
140 if (request.contentStreamProvider().isPresent()) {
141 HttpEntity entity = new RepeatableInputStreamRequestEntity(request);
142 if (request.httpRequest().headers().get(HttpHeaders.CONTENT_LENGTH) == null) {
143 entity = ApacheUtils.newBufferedHttpEntity(entity);
144 }
145 entityEnclosingRequest.setEntity(entity);
146 }
147
148 return entityEnclosingRequest;
149 }
150
151
154 private void addHeadersToRequest(HttpRequestBase httpRequest, SdkHttpRequest request) {
155
156 httpRequest.addHeader(HttpHeaders.HOST, getHostHeaderValue(request));
157
158
159
160 request.headers().entrySet().stream()
161
167 .filter(e -> !IGNORE_HEADERS.contains(e.getKey()))
168 .forEach(e -> e.getValue().forEach(h -> httpRequest.addHeader(e.getKey(), h)));
169 }
170
171 private String getHostHeaderValue(SdkHttpRequest request) {
172
173
174 return !SdkHttpUtils.isUsingStandardPort(request.protocol(), request.port())
175 ? request.host() + ":" + request.port()
176 : request.host();
177 }
178 }
179