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
39using namespace Aws::Client;
40using namespace Aws::Http;
41using namespace Aws::Utils::Logging;
42
43namespace 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