1 | /* |
2 | * Copyright 2010-2017 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 | #define AWS_DISABLE_DEPRECATION |
16 | #include <aws/core/http/HttpClientFactory.h> |
17 | |
18 | #if ENABLE_CURL_CLIENT |
19 | #include <aws/core/http/curl/CurlHttpClient.h> |
20 | #include <signal.h> |
21 | |
22 | #elif ENABLE_WINDOWS_CLIENT |
23 | #include <aws/core/client/ClientConfiguration.h> |
24 | #if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT |
25 | #include <aws/core/http/windows/IXmlHttpRequest2HttpClient.h> |
26 | #if BYPASS_DEFAULT_PROXY |
27 | #include <aws/core/http/windows/WinHttpSyncHttpClient.h> |
28 | #endif |
29 | #else |
30 | #include <aws/core/http/windows/WinINetSyncHttpClient.h> |
31 | #include <aws/core/http/windows/WinHttpSyncHttpClient.h> |
32 | #endif |
33 | #endif |
34 | |
35 | #include <aws/core/http/standard/StandardHttpRequest.h> |
36 | #include <aws/core/utils/logging/LogMacros.h> |
37 | #include <cassert> |
38 | |
39 | using namespace Aws::Client; |
40 | using namespace Aws::Http; |
41 | using namespace Aws::Utils::Logging; |
42 | |
43 | namespace Aws |
44 | { |
45 | namespace Http |
46 | { |
47 | static std::shared_ptr<HttpClientFactory> s_HttpClientFactory(nullptr); |
48 | static bool s_InitCleanupCurlFlag(false); |
49 | static bool s_InstallSigPipeHandler(false); |
50 | |
51 | static const char* HTTP_CLIENT_FACTORY_ALLOCATION_TAG = "HttpClientFactory" ; |
52 | |
53 | #if ENABLE_CURL_CLIENT && !defined(_WIN32) |
54 | static void LogAndSwallowHandler(int signal) |
55 | { |
56 | switch(signal) |
57 | { |
58 | case SIGPIPE: |
59 | AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Received a SIGPIPE error" ); |
60 | break; |
61 | default: |
62 | AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Unhandled system SIGNAL error" << signal); |
63 | } |
64 | } |
65 | #endif |
66 | |
67 | class DefaultHttpClientFactory : public HttpClientFactory |
68 | { |
69 | std::shared_ptr<HttpClient> CreateHttpClient(const ClientConfiguration& clientConfiguration) const override |
70 | { |
71 | // Figure out whether the selected option is available but fail gracefully and return a default of some type if not |
72 | // Windows clients: Http and Inet are always options, Curl MIGHT be an option if USE_CURL_CLIENT is on, and http is "default" |
73 | // Other clients: Curl is your default |
74 | #if ENABLE_WINDOWS_CLIENT |
75 | #if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT |
76 | #if BYPASS_DEFAULT_PROXY |
77 | switch (clientConfiguration.httpLibOverride) |
78 | { |
79 | case TransferLibType::WIN_HTTP_CLIENT: |
80 | AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating WinHTTP http client." ); |
81 | return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
82 | case TransferLibType::WIN_INET_CLIENT: |
83 | AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "WinINet http client is not supported with the current build configuration." ); |
84 | // fall-through |
85 | default: |
86 | AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating IXMLHttpRequest http client." ); |
87 | return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
88 | } |
89 | #else |
90 | return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
91 | #endif // BYPASS_DEFAULT_PROXY |
92 | #else |
93 | switch (clientConfiguration.httpLibOverride) |
94 | { |
95 | case TransferLibType::WIN_INET_CLIENT: |
96 | return Aws::MakeShared<WinINetSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
97 | |
98 | default: |
99 | return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
100 | } |
101 | #endif // ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT |
102 | #elif ENABLE_CURL_CLIENT |
103 | return Aws::MakeShared<CurlHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); |
104 | #else |
105 | // When neither of these clients is enabled, gcc gives a warning (converted |
106 | // to error by -Werror) about the unused clientConfiguration parameter. We |
107 | // prevent that warning with AWS_UNREFERENCED_PARAM. |
108 | AWS_UNREFERENCED_PARAM(clientConfiguration); |
109 | AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "SDK was built without an Http implementation, default http client factory can't create an Http client instance." ); |
110 | return nullptr; |
111 | #endif |
112 | } |
113 | |
114 | std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String &uri, HttpMethod method, |
115 | const Aws::IOStreamFactory &streamFactory) const override |
116 | { |
117 | return CreateHttpRequest(URI(uri), method, streamFactory); |
118 | } |
119 | |
120 | std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) const override |
121 | { |
122 | auto request = Aws::MakeShared<Standard::StandardHttpRequest>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, uri, method); |
123 | request->SetResponseStreamFactory(streamFactory); |
124 | |
125 | return request; |
126 | } |
127 | |
128 | void InitStaticState() override |
129 | { |
130 | #if ENABLE_CURL_CLIENT |
131 | if(s_InitCleanupCurlFlag) |
132 | { |
133 | CurlHttpClient::InitGlobalState(); |
134 | } |
135 | #if !defined (_WIN32) |
136 | if(s_InstallSigPipeHandler) |
137 | { |
138 | ::signal(SIGPIPE, LogAndSwallowHandler); |
139 | } |
140 | #endif |
141 | #elif ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT |
142 | IXmlHttpRequest2HttpClient::InitCOM(); |
143 | #endif |
144 | } |
145 | |
146 | virtual void CleanupStaticState() override |
147 | { |
148 | #if ENABLE_CURL_CLIENT |
149 | if(s_InitCleanupCurlFlag) |
150 | { |
151 | CurlHttpClient::CleanupGlobalState(); |
152 | } |
153 | #endif |
154 | } |
155 | }; |
156 | |
157 | void SetInitCleanupCurlFlag(bool initCleanupFlag) |
158 | { |
159 | s_InitCleanupCurlFlag = initCleanupFlag; |
160 | } |
161 | |
162 | void SetInstallSigPipeHandlerFlag(bool install) |
163 | { |
164 | s_InstallSigPipeHandler = install; |
165 | } |
166 | |
167 | void InitHttp() |
168 | { |
169 | if(!s_HttpClientFactory) |
170 | { |
171 | s_HttpClientFactory = Aws::MakeShared<DefaultHttpClientFactory>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG); |
172 | } |
173 | s_HttpClientFactory->InitStaticState(); |
174 | } |
175 | |
176 | void CleanupHttp() |
177 | { |
178 | if(s_HttpClientFactory) |
179 | { |
180 | s_HttpClientFactory->CleanupStaticState(); |
181 | s_HttpClientFactory = nullptr; |
182 | } |
183 | } |
184 | |
185 | void SetHttpClientFactory(const std::shared_ptr<HttpClientFactory>& factory) |
186 | { |
187 | CleanupHttp(); |
188 | s_HttpClientFactory = factory; |
189 | } |
190 | |
191 | std::shared_ptr<HttpClient> CreateHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration) |
192 | { |
193 | assert(s_HttpClientFactory); |
194 | return s_HttpClientFactory->CreateHttpClient(clientConfiguration); |
195 | } |
196 | |
197 | std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) |
198 | { |
199 | assert(s_HttpClientFactory); |
200 | return s_HttpClientFactory->CreateHttpRequest(uri, method, streamFactory); |
201 | } |
202 | |
203 | std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) |
204 | { |
205 | assert(s_HttpClientFactory); |
206 | return s_HttpClientFactory->CreateHttpRequest(uri, method, streamFactory); |
207 | } |
208 | } |
209 | } |
210 | |
211 | |
212 | |