• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.crt.internal.request;
17 
18 import java.net.URI;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Optional;
22 import software.amazon.awssdk.annotations.SdkInternalApi;
23 import software.amazon.awssdk.crt.http.HttpHeader;
24 import software.amazon.awssdk.crt.http.HttpRequest;
25 import software.amazon.awssdk.http.Header;
26 import software.amazon.awssdk.http.HttpExecuteRequest;
27 import software.amazon.awssdk.http.SdkHttpRequest;
28 import software.amazon.awssdk.http.async.AsyncExecuteRequest;
29 import software.amazon.awssdk.http.crt.internal.CrtAsyncRequestContext;
30 import software.amazon.awssdk.http.crt.internal.CrtRequestContext;
31 
32 @SdkInternalApi
33 public final class CrtRequestAdapter {
CrtRequestAdapter()34     private CrtRequestAdapter() {
35     }
36 
toAsyncCrtRequest(CrtAsyncRequestContext request)37     public static HttpRequest toAsyncCrtRequest(CrtAsyncRequestContext request) {
38         AsyncExecuteRequest sdkExecuteRequest = request.sdkRequest();
39         SdkHttpRequest sdkRequest = sdkExecuteRequest.request();
40 
41         String method = sdkRequest.method().name();
42         String encodedPath = sdkRequest.encodedPath();
43         if (encodedPath == null || encodedPath.isEmpty()) {
44             encodedPath = "/";
45         }
46 
47         String encodedQueryString = sdkRequest.encodedQueryParameters()
48                                               .map(value -> "?" + value)
49                                               .orElse("");
50 
51         HttpHeader[] crtHeaderArray = asArray(createAsyncHttpHeaderList(sdkRequest.getUri(), sdkExecuteRequest));
52 
53         return new HttpRequest(method,
54                                encodedPath + encodedQueryString,
55                                crtHeaderArray,
56                                new CrtRequestBodyAdapter(sdkExecuteRequest.requestContentPublisher(),
57                                                          request.readBufferSize()));
58     }
59 
toCrtRequest(CrtRequestContext request)60     public static HttpRequest toCrtRequest(CrtRequestContext request) {
61 
62         HttpExecuteRequest sdkExecuteRequest = request.sdkRequest();
63         SdkHttpRequest sdkRequest = sdkExecuteRequest.httpRequest();
64 
65         String method = sdkRequest.method().name();
66         String encodedPath = sdkRequest.encodedPath();
67         if (encodedPath == null || encodedPath.isEmpty()) {
68             encodedPath = "/";
69         }
70 
71         String encodedQueryString = sdkRequest.encodedQueryParameters()
72                                               .map(value -> "?" + value)
73                                               .orElse("");
74 
75         HttpHeader[] crtHeaderArray = asArray(createHttpHeaderList(sdkRequest.getUri(), sdkExecuteRequest));
76 
77         String finalEncodedPath = encodedPath + encodedQueryString;
78         return sdkExecuteRequest.contentStreamProvider()
79                                 .map(provider -> new HttpRequest(method,
80                                                                  finalEncodedPath,
81                                                                  crtHeaderArray,
82                                                                  new CrtRequestInputStreamAdapter(provider)))
83                                 .orElse(new HttpRequest(method,
84                                                         finalEncodedPath,
85                                                         crtHeaderArray, null));
86     }
87 
asArray(List<HttpHeader> crtHeaderList)88     private static HttpHeader[] asArray(List<HttpHeader> crtHeaderList) {
89         return crtHeaderList.toArray(new HttpHeader[0]);
90     }
91 
createAsyncHttpHeaderList(URI uri, AsyncExecuteRequest sdkExecuteRequest)92     private static List<HttpHeader> createAsyncHttpHeaderList(URI uri, AsyncExecuteRequest sdkExecuteRequest) {
93         SdkHttpRequest sdkRequest = sdkExecuteRequest.request();
94         // worst case we may add 3 more headers here
95         List<HttpHeader> crtHeaderList = new ArrayList<>(sdkRequest.numHeaders() + 3);
96 
97         // Set Host Header if needed
98         if (!sdkRequest.firstMatchingHeader(Header.HOST).isPresent()) {
99             crtHeaderList.add(new HttpHeader(Header.HOST, uri.getHost()));
100         }
101 
102         // Add Connection Keep Alive Header to reuse this Http Connection as long as possible
103         if (!sdkRequest.firstMatchingHeader(Header.CONNECTION).isPresent()) {
104             crtHeaderList.add(new HttpHeader(Header.CONNECTION, Header.KEEP_ALIVE_VALUE));
105         }
106 
107         // Set Content-Length if needed
108         Optional<Long> contentLength = sdkExecuteRequest.requestContentPublisher().contentLength();
109         if (!sdkRequest.firstMatchingHeader(Header.CONTENT_LENGTH).isPresent() && contentLength.isPresent()) {
110             crtHeaderList.add(new HttpHeader(Header.CONTENT_LENGTH, Long.toString(contentLength.get())));
111         }
112 
113         // Add the rest of the Headers
114         sdkRequest.forEachHeader((key, value) -> value.stream().map(val -> new HttpHeader(key, val)).forEach(crtHeaderList::add));
115 
116         return crtHeaderList;
117     }
118 
createHttpHeaderList(URI uri, HttpExecuteRequest sdkExecuteRequest)119     private static List<HttpHeader> createHttpHeaderList(URI uri, HttpExecuteRequest sdkExecuteRequest) {
120         SdkHttpRequest sdkRequest = sdkExecuteRequest.httpRequest();
121         // worst case we may add 3 more headers here
122         List<HttpHeader> crtHeaderList = new ArrayList<>(sdkRequest.numHeaders() + 3);
123 
124         // Set Host Header if needed
125         if (!sdkRequest.firstMatchingHeader(Header.HOST).isPresent()) {
126             crtHeaderList.add(new HttpHeader(Header.HOST, uri.getHost()));
127         }
128 
129         // Add Connection Keep Alive Header to reuse this Http Connection as long as possible
130         if (!sdkRequest.firstMatchingHeader(Header.CONNECTION).isPresent()) {
131             crtHeaderList.add(new HttpHeader(Header.CONNECTION, Header.KEEP_ALIVE_VALUE));
132         }
133 
134         // We assume content length was set by the caller if a stream was present, so don't set it here.
135 
136         // Add the rest of the Headers
137         sdkRequest.forEachHeader((key, value) -> value.stream().map(val -> new HttpHeader(key, val)).forEach(crtHeaderList::add));
138 
139         return crtHeaderList;
140     }
141 }
142