rpRegistrationPolicy.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import * as tslib_1 from "tslib";
  2. import * as utils from "../util/utils";
  3. import { BaseRequestPolicy } from "./requestPolicy";
  4. export function rpRegistrationPolicy(retryTimeout) {
  5. if (retryTimeout === void 0) { retryTimeout = 30; }
  6. return {
  7. create: function (nextPolicy, options) {
  8. return new RPRegistrationPolicy(nextPolicy, options, retryTimeout);
  9. }
  10. };
  11. }
  12. var RPRegistrationPolicy = /** @class */ (function (_super) {
  13. tslib_1.__extends(RPRegistrationPolicy, _super);
  14. function RPRegistrationPolicy(nextPolicy, options, _retryTimeout) {
  15. if (_retryTimeout === void 0) { _retryTimeout = 30; }
  16. var _this = _super.call(this, nextPolicy, options) || this;
  17. _this._retryTimeout = _retryTimeout;
  18. return _this;
  19. }
  20. RPRegistrationPolicy.prototype.sendRequest = function (request) {
  21. var _this = this;
  22. return this._nextPolicy.sendRequest(request.clone())
  23. .then(function (response) { return registerIfNeeded(_this, request, response); });
  24. };
  25. return RPRegistrationPolicy;
  26. }(BaseRequestPolicy));
  27. export { RPRegistrationPolicy };
  28. function registerIfNeeded(policy, request, response) {
  29. if (response.status === 409) {
  30. var rpName = checkRPNotRegisteredError(response.bodyAsText);
  31. if (rpName) {
  32. var urlPrefix = extractSubscriptionUrl(request.url);
  33. return registerRP(policy, urlPrefix, rpName, request)
  34. // Autoregistration of ${provider} failed for some reason. We will not return this error
  35. // instead will return the initial response with 409 status code back to the user.
  36. // do nothing here as we are returning the original response at the end of this method.
  37. .catch(function () { return false; })
  38. .then(function (registrationStatus) {
  39. if (registrationStatus) {
  40. // Retry the original request. We have to change the x-ms-client-request-id
  41. // otherwise Azure endpoint will return the initial 409 (cached) response.
  42. request.headers.set("x-ms-client-request-id", utils.generateUuid());
  43. return policy._nextPolicy.sendRequest(request.clone());
  44. }
  45. return response;
  46. });
  47. }
  48. }
  49. return Promise.resolve(response);
  50. }
  51. /**
  52. * Reuses the headers of the original request and url (if specified).
  53. * @param {WebResource} originalRequest The original request
  54. * @param {boolean} reuseUrlToo Should the url from the original request be reused as well. Default false.
  55. * @returns {object} A new request object with desired headers.
  56. */
  57. function getRequestEssentials(originalRequest, reuseUrlToo) {
  58. if (reuseUrlToo === void 0) { reuseUrlToo = false; }
  59. var reqOptions = originalRequest.clone();
  60. if (reuseUrlToo) {
  61. reqOptions.url = originalRequest.url;
  62. }
  63. // We have to change the x-ms-client-request-id otherwise Azure endpoint
  64. // will return the initial 409 (cached) response.
  65. reqOptions.headers.set("x-ms-client-request-id", utils.generateUuid());
  66. // Set content-type to application/json
  67. reqOptions.headers.set("Content-Type", "application/json; charset=utf-8");
  68. return reqOptions;
  69. }
  70. /**
  71. * Validates the error code and message associated with 409 response status code. If it matches to that of
  72. * RP not registered then it returns the name of the RP else returns undefined.
  73. * @param {string} body The response body received after making the original request.
  74. * @returns {string} The name of the RP if condition is satisfied else undefined.
  75. */
  76. function checkRPNotRegisteredError(body) {
  77. var result, responseBody;
  78. if (body) {
  79. try {
  80. responseBody = JSON.parse(body);
  81. }
  82. catch (err) {
  83. // do nothing;
  84. }
  85. if (responseBody && responseBody.error && responseBody.error.message &&
  86. responseBody.error.code && responseBody.error.code === "MissingSubscriptionRegistration") {
  87. var matchRes = responseBody.error.message.match(/.*'(.*)'/i);
  88. if (matchRes) {
  89. result = matchRes.pop();
  90. }
  91. }
  92. }
  93. return result;
  94. }
  95. /**
  96. * Extracts the first part of the URL, just after subscription:
  97. * https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
  98. * @param {string} url The original request url
  99. * @returns {string} The url prefix as explained above.
  100. */
  101. function extractSubscriptionUrl(url) {
  102. var result;
  103. var matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//ig);
  104. if (matchRes && matchRes[0]) {
  105. result = matchRes[0];
  106. }
  107. else {
  108. throw new Error("Unable to extract subscriptionId from the given url - " + url + ".");
  109. }
  110. return result;
  111. }
  112. /**
  113. * Registers the given provider.
  114. * @param {RPRegistrationPolicy} policy The RPRegistrationPolicy this function is being called against.
  115. * @param {string} urlPrefix https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
  116. * @param {string} provider The provider name to be registered.
  117. * @param {WebResource} originalRequest The original request sent by the user that returned a 409 response
  118. * with a message that the provider is not registered.
  119. * @param {registrationCallback} callback The callback that handles the RP registration
  120. */
  121. function registerRP(policy, urlPrefix, provider, originalRequest) {
  122. var postUrl = urlPrefix + "providers/" + provider + "/register?api-version=2016-02-01";
  123. var getUrl = urlPrefix + "providers/" + provider + "?api-version=2016-02-01";
  124. var reqOptions = getRequestEssentials(originalRequest);
  125. reqOptions.method = "POST";
  126. reqOptions.url = postUrl;
  127. return policy._nextPolicy.sendRequest(reqOptions)
  128. .then(function (response) {
  129. if (response.status !== 200) {
  130. throw new Error("Autoregistration of " + provider + " failed. Please try registering manually.");
  131. }
  132. return getRegistrationStatus(policy, getUrl, originalRequest);
  133. });
  134. }
  135. /**
  136. * Polls the registration status of the provider that was registered. Polling happens at an interval of 30 seconds.
  137. * Polling will happen till the registrationState property of the response body is "Registered".
  138. * @param {RPRegistrationPolicy} policy The RPRegistrationPolicy this function is being called against.
  139. * @param {string} url The request url for polling
  140. * @param {WebResource} originalRequest The original request sent by the user that returned a 409 response
  141. * with a message that the provider is not registered.
  142. * @returns {Promise<boolean>} True if RP Registration is successful.
  143. */
  144. function getRegistrationStatus(policy, url, originalRequest) {
  145. var reqOptions = getRequestEssentials(originalRequest);
  146. reqOptions.url = url;
  147. reqOptions.method = "GET";
  148. return policy._nextPolicy.sendRequest(reqOptions).then(function (res) {
  149. var obj = res.parsedBody;
  150. if (res.parsedBody && obj.registrationState && obj.registrationState === "Registered") {
  151. return true;
  152. }
  153. else {
  154. return utils.delay(policy._retryTimeout * 1000).then(function () { return getRegistrationStatus(policy, url, originalRequest); });
  155. }
  156. });
  157. }
  158. //# sourceMappingURL=rpRegistrationPolicy.js.map