1
15
16 package software.amazon.awssdk.core.internal.http;
17
18 import software.amazon.awssdk.annotations.SdkInternalApi;
19 import software.amazon.awssdk.annotations.ThreadSafe;
20 import software.amazon.awssdk.core.Response;
21 import software.amazon.awssdk.core.SdkRequest;
22 import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
23 import software.amazon.awssdk.core.exception.SdkClientException;
24 import software.amazon.awssdk.core.http.ExecutionContext;
25 import software.amazon.awssdk.core.http.HttpResponseHandler;
26 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
27 import software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder;
28 import software.amazon.awssdk.core.internal.http.pipeline.stages.AfterExecutionInterceptorsStage;
29 import software.amazon.awssdk.core.internal.http.pipeline.stages.AfterTransmissionExecutionInterceptorsStage;
30 import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage;
31 import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage;
32 import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage;
33 import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyUserAgentStage;
34 import software.amazon.awssdk.core.internal.http.pipeline.stages.BeforeTransmissionExecutionInterceptorsStage;
35 import software.amazon.awssdk.core.internal.http.pipeline.stages.BeforeUnmarshallingExecutionInterceptorsStage;
36 import software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage;
37 import software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage;
38 import software.amazon.awssdk.core.internal.http.pipeline.stages.MakeHttpRequestStage;
39 import software.amazon.awssdk.core.internal.http.pipeline.stages.MakeRequestImmutableStage;
40 import software.amazon.awssdk.core.internal.http.pipeline.stages.MakeRequestMutableStage;
41 import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomHeadersStage;
42 import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomQueryParamsStage;
43 import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage;
44 import software.amazon.awssdk.core.internal.http.pipeline.stages.SigningStage;
45 import software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage;
46 import software.amazon.awssdk.core.internal.http.pipeline.stages.UnwrapResponseContainer;
47 import software.amazon.awssdk.http.SdkHttpFullRequest;
48 import software.amazon.awssdk.http.SdkHttpFullResponse;
49 import software.amazon.awssdk.utils.SdkAutoCloseable;
50
51 @ThreadSafe
52 @SdkInternalApi
53
54 public final class AmazonSyncHttpClient implements SdkAutoCloseable {
55 private final HttpClientDependencies httpClientDependencies;
56
57 public AmazonSyncHttpClient(SdkClientConfiguration clientConfiguration) {
58 this.httpClientDependencies = HttpClientDependencies.builder()
59 .clientConfiguration(clientConfiguration)
60 .build();
61 }
62
63
69 @Override
70 public void close() {
71 httpClientDependencies.close();
72 }
73
74
77 public RequestExecutionBuilder requestExecutionBuilder() {
78 return new RequestExecutionBuilderImpl();
79 }
80
81
84 public interface RequestExecutionBuilder {
85
86
92 RequestExecutionBuilder request(SdkHttpFullRequest request);
93
94 RequestExecutionBuilder originalRequest(SdkRequest originalRequest);
95
96
102 RequestExecutionBuilder executionContext(ExecutionContext executionContext);
103
104
112 <OutputT> OutputT execute(HttpResponseHandler<Response<OutputT>> combinedResponseHandler);
113 }
114
115 private static class NoOpResponseHandler<T> implements HttpResponseHandler<T> {
116 @Override
117 public T handle(SdkHttpFullResponse response, ExecutionAttributes executionAttributes) {
118 return null;
119 }
120
121 @Override
122 public boolean needsConnectionLeftOpen() {
123 return false;
124 }
125 }
126
127 private class RequestExecutionBuilderImpl implements RequestExecutionBuilder {
128
129 private SdkHttpFullRequest request;
130 private SdkRequest originalRequest;
131 private ExecutionContext executionContext;
132
133 @Override
134
135 public RequestExecutionBuilder request(SdkHttpFullRequest request) {
136 this.request = request;
137 return this;
138 }
139
140 @Override
141 public RequestExecutionBuilder originalRequest(SdkRequest originalRequest) {
142 this.originalRequest = originalRequest;
143 return this;
144 }
145
146 @Override
147 public RequestExecutionBuilder executionContext(ExecutionContext executionContext) {
148 this.executionContext = executionContext;
149 return this;
150 }
151
152 @Override
153 public <OutputT> OutputT execute(HttpResponseHandler<Response<OutputT>> responseHandler) {
154
155
156
157 if (request != null && executionContext != null) {
158 executionContext.interceptorContext(
159 executionContext.interceptorContext().copy(ib -> ib.httpRequest(request)));
160 }
161
162 try {
163 return RequestPipelineBuilder
164
165 .first(RequestPipelineBuilder
166 .first(MakeRequestMutableStage::new)
167 .then(ApplyTransactionIdStage::new)
168 .then(ApplyUserAgentStage::new)
169 .then(MergeCustomHeadersStage::new)
170 .then(MergeCustomQueryParamsStage::new)
171 .then(MakeRequestImmutableStage::new)
172
173 .then(RequestPipelineBuilder
174 .first(SigningStage::new)
175 .then(BeforeTransmissionExecutionInterceptorsStage::new)
176 .then(MakeHttpRequestStage::new)
177 .then(AfterTransmissionExecutionInterceptorsStage::new)
178 .then(BeforeUnmarshallingExecutionInterceptorsStage::new)
179 .then(() -> new HandleResponseStage<>(responseHandler))
180 .wrappedWith(ApiCallAttemptTimeoutTrackingStage::new)
181 .wrappedWith(TimeoutExceptionHandlingStage::new)
182 .wrappedWith(RetryableStage::new)::build)
183 .wrappedWith(StreamManagingStage::new)
184 .wrappedWith(ApiCallTimeoutTrackingStage::new)::build)
185 .then(() -> new UnwrapResponseContainer<>())
186 .then(() -> new AfterExecutionInterceptorsStage<>())
187 .wrappedWith(ExecutionFailureExceptionReportingStage::new)
188 .build(httpClientDependencies)
189 .execute(request, createRequestExecutionDependencies());
190 } catch (RuntimeException e) {
191 throw e;
192 } catch (Exception e) {
193 throw SdkClientException.builder().cause(e).build();
194 }
195 }
196
197 private RequestExecutionContext createRequestExecutionDependencies() {
198 return RequestExecutionContext.builder()
199 .originalRequest(originalRequest)
200 .executionContext(executionContext)
201 .build();
202 }
203
204 }
205
206 }
207