EndpointProvider.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright 1999-2019 Alibaba Cloud 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. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <algorithm>
  17. #include <alibabacloud/core/EndpointProvider.h>
  18. #include <iomanip>
  19. #include <json/json.h>
  20. #include <sstream>
  21. #ifndef WIN32
  22. #include "LocalEndpoints.h"
  23. #include <alibabacloud/core/Utils.h>
  24. #else
  25. #include "LocalEndpointsForWindows.h"
  26. #endif
  27. namespace AlibabaCloud
  28. {
  29. namespace
  30. {
  31. #if defined(WIN32) && defined(_MSC_VER)
  32. #define strcasecmp _stricmp
  33. #define strncasecmp _strnicmp
  34. #else
  35. #include <strings.h>
  36. #endif
  37. bool local_endpoints_loaded = false;
  38. typedef std::string productType;
  39. typedef std::string regionType;
  40. typedef std::string endpointType;
  41. typedef std::string mappingType;
  42. typedef std::vector<regionType> regionsType;
  43. typedef std::map<productType, endpointType> regionalType;
  44. typedef struct
  45. {
  46. regionsType regions;
  47. regionalType regional;
  48. } productInfoType;
  49. static std::vector<regionType> allRegions;
  50. static std::vector<productType> allProductsInLocalEndpoints;
  51. static std::map<productType, productInfoType> allLocalEndpoints;
  52. static void LoadLocalEndpoints()
  53. {
  54. Json::Reader reader;
  55. Json::Value value;
  56. if (local_endpoints_loaded)
  57. {
  58. return;
  59. }
  60. #ifdef WIN32
  61. std::string LOCAL_ENDPOINTS_CONFIG = WIN_LOCAL_ENDPOINTS_CONFIG_1 +
  62. WIN_LOCAL_ENDPOINTS_CONFIG_2 +
  63. WIN_LOCAL_ENDPOINTS_CONFIG_3;
  64. #endif
  65. if (!reader.parse(LOCAL_ENDPOINTS_CONFIG, value))
  66. {
  67. return;
  68. }
  69. auto regions = value["regions"];
  70. for (const auto &region : regions)
  71. {
  72. allRegions.push_back(region.asString());
  73. }
  74. auto products = value["products"];
  75. for (const auto &product : products)
  76. {
  77. allProductsInLocalEndpoints.push_back(product.asString());
  78. }
  79. auto endpoints = value["endpoints"];
  80. for (auto &product : allProductsInLocalEndpoints)
  81. {
  82. auto endpoint_per_product = endpoints[product];
  83. productInfoType p;
  84. auto regions = endpoint_per_product["regions"];
  85. auto regional = endpoint_per_product["regional"];
  86. for (auto &r : regions)
  87. {
  88. const std::string region = r.asString();
  89. p.regions.push_back(region);
  90. p.regional[region] =
  91. endpoint_per_product["regional"][region].asString();
  92. }
  93. allLocalEndpoints[product] = p;
  94. }
  95. local_endpoints_loaded = true;
  96. }
  97. } // namespace
  98. EndpointProvider::EndpointProvider(
  99. const std::shared_ptr<Location::LocationClient> &locationClient,
  100. const std::string regionId, const std::string product,
  101. const std::string serviceCode, int durationSeconds)
  102. : LocationClient(locationClient), regionId_(regionId), product_(product),
  103. serviceCode_(serviceCode), durationSeconds_(durationSeconds),
  104. cachedMutex_(), cachedEndpoint_(), expiry_()
  105. {
  106. transform(product_.begin(), product_.end(), product_.begin(), ::tolower);
  107. loadLocalProductsInfo();
  108. }
  109. EndpointProvider::EndpointProvider(const Credentials &credentials,
  110. const ClientConfiguration &configuration,
  111. const std::string &regionId,
  112. const std::string &product,
  113. const std::string &serviceCode,
  114. int durationSeconds)
  115. : LocationClient(credentials, configuration), regionId_(regionId),
  116. product_(product), serviceCode_(serviceCode),
  117. durationSeconds_(durationSeconds), cachedMutex_(), cachedEndpoint_(),
  118. expiry_()
  119. {
  120. transform(product_.begin(), product_.end(), product_.begin(), ::tolower);
  121. loadLocalProductsInfo();
  122. }
  123. EndpointProvider::~EndpointProvider() {}
  124. bool EndpointProvider::loadLocalProductsInfo()
  125. {
  126. LoadLocalEndpoints();
  127. return true;
  128. }
  129. std::string EndpointProvider::localEndpoint(const std::string regionId,
  130. const std::string product)
  131. {
  132. if (!local_endpoints_loaded)
  133. {
  134. // impossible
  135. return std::string();
  136. }
  137. std::vector<regionType>::iterator allRegionsit;
  138. allRegionsit = std::find(allRegions.begin(), allRegions.end(), regionId);
  139. if (allRegionsit == allRegions.end())
  140. {
  141. return std::string();
  142. }
  143. std::vector<productType>::iterator allProductsInLocalEndpointsit;
  144. allProductsInLocalEndpointsit =
  145. std::find(allProductsInLocalEndpoints.begin(),
  146. allProductsInLocalEndpoints.end(), product);
  147. if (allProductsInLocalEndpointsit == allProductsInLocalEndpoints.end())
  148. {
  149. return std::string();
  150. }
  151. std::vector<regionType> vec = allLocalEndpoints[product].regions;
  152. std::vector<regionType>::iterator it;
  153. it = std::find(vec.begin(), vec.end(), regionId);
  154. if (it == vec.end())
  155. {
  156. return std::string();
  157. }
  158. return allLocalEndpoints[product].regional[regionId];
  159. }
  160. bool EndpointProvider::checkExpiry() const
  161. {
  162. auto now = std::chrono::system_clock::now();
  163. auto diff =
  164. std::chrono::duration_cast<std::chrono::seconds>(now - expiry_).count();
  165. return (diff > 0 - 60);
  166. }
  167. EndpointProvider::EndpointOutcome EndpointProvider::getEndpoint()
  168. {
  169. // 1st priority: user specified via configuration
  170. if (!configuration().endpoint().empty())
  171. {
  172. return EndpointOutcome(configuration().endpoint());
  173. }
  174. // 2nd priority: local configuration
  175. std::string endpoint = localEndpoint(regionId_, product_);
  176. if (!endpoint.empty())
  177. {
  178. return EndpointOutcome(endpoint);
  179. }
  180. // service code is mandatory for location service.
  181. if (serviceCode_.empty())
  182. {
  183. return EndpointOutcome(
  184. Error("InvalidRegionId", "Product[" + product_ + "] at region[" +
  185. regionId_ + "] does not exist."));
  186. }
  187. // 3rd priority: request from location service
  188. EndpointOutcome outcome = loadRemoteEndpoint();
  189. if (outcome.isSuccess())
  190. {
  191. return outcome;
  192. }
  193. if (outcome.error().errorCode() == "Illegal Parameter")
  194. {
  195. return EndpointOutcome(Error("InvalidProduct", "Prodcut[" + serviceCode_ +
  196. "] does not exist."));
  197. }
  198. return outcome;
  199. }
  200. EndpointProvider::EndpointOutcome EndpointProvider::loadRemoteEndpoint()
  201. {
  202. if (checkExpiry())
  203. {
  204. std::lock_guard<std::mutex> locker(cachedMutex_);
  205. if (checkExpiry())
  206. {
  207. Location::Model::DescribeEndpointsRequest request;
  208. request.setId(regionId_);
  209. request.setServiceCode(serviceCode_);
  210. request.setType("openAPI");
  211. auto outcome = describeEndpoints(request);
  212. if (!outcome.isSuccess())
  213. return EndpointOutcome(outcome.error());
  214. auto all = outcome.result().endpoints();
  215. if (all.size() > 0)
  216. cachedEndpoint_ = all.front().endpoint;
  217. std::time_t t = std::time(nullptr) + durationSeconds_;
  218. expiry_ = std::chrono::system_clock::from_time_t(t);
  219. }
  220. }
  221. return EndpointOutcome(cachedEndpoint_);
  222. }
  223. } // namespace AlibabaCloud