diff --git a/source/javascripts/swagger-service.js b/source/javascripts/swagger-service.js index f99eba24..134ba41b 100644 --- a/source/javascripts/swagger-service.js +++ b/source/javascripts/swagger-service.js @@ -1,19 +1,17 @@ -function SwaggerService(baseUrl, _apiKey, statusCallback) { - if (!baseUrl) - throw new Error("baseUrl must be passed while creating SwaggerService"); +function SwaggerService(discoveryUrl, _apiKey, statusCallback) { + if (!discoveryUrl) + throw new Error("discoveryUrl must be passed while creating SwaggerService"); // constants - baseUrl = jQuery.trim(baseUrl); - if (baseUrl.length == 0) - throw new Error("baseUrl must be passed while creating SwaggerService"); + discoveryUrl = jQuery.trim(discoveryUrl); + if (discoveryUrl.length == 0) + throw new Error("discoveryUrl must be passed while creating SwaggerService"); - if (! (baseUrl.toLowerCase().indexOf("http:") == 0 || baseUrl.toLowerCase().indexOf("https:") == 0)) { - baseUrl = ("http://" + baseUrl); + if (! (discoveryUrl.toLowerCase().indexOf("http:") == 0 || discoveryUrl.toLowerCase().indexOf("https:") == 0)) { + discoveryUrl = ("http://" + discoveryUrl); } - var apiHost = baseUrl.substr(0, baseUrl.lastIndexOf("/")); - var discoParts = baseUrl.split("/"); - var rootResourcesApiName = discoParts[discoParts.length-1]; + var globalBasePath = null; var formatString = ".{format}"; var statusListener = statusCallback; var apiKey = _apiKey; @@ -37,13 +35,17 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { statusListener(status); } + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + // make some models public this.ApiResource = function() { return ApiResource; }; this.apiHost = function() { - return apiHost; + return globalBasePath; }; this.formatString = function() { @@ -60,7 +62,7 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { if (atts) this.load(atts); this.path_json = this.path.replace("{format}", "json"); this.path_xml = this.path.replace("{format}", "xml"); - this.baseUrl = apiHost; + this.baseUrl = globalBasePath; //execluded 9 letters to remove .{format} from name this.name = this.path.split("/"); this.name = this.name[this.name.length - 1]; @@ -90,7 +92,7 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { init: function(atts) { if (atts) this.load(atts); - this.baseUrl = apiHost; + this.baseUrl = globalBasePath; var secondPathSeperatorIndex = this.path.indexOf("/", 1); if (secondPathSeperatorIndex > 0) { @@ -157,7 +159,7 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { init: function(atts) { if (atts) this.load(atts); - this.baseUrl = apiHost; + this.baseUrl = globalBasePath; this.httpMethodLowercase = this.httpMethod.toLowerCase(); var value = this.parameters; @@ -355,6 +357,8 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { var ModelController = Spine.Controller.create({ countLoaded: 0, proxied: ["fetchResources", "loadResources", "apisLoaded", "modelsLoaded"], + discoveryUrlList: [], + discoveryUrlListCursor: 0, init: function() { // log("ModelController.init"); @@ -363,26 +367,57 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { }, fetchEndpoints: function() { - var controller = this; - updateStatus("Fetching API List..."); - var url = apiHost + "/" + rootResourcesApiName + apiKeySuffix; - $.getJSON(url, function(response) { - - // if (response.apis) { - ApiResource.createAll(response.apis); - // } - - // get rid of the root resource list api since we're not going to document that - var obj = ApiResource.findByAttribute("name", rootResourcesApiName); - if (obj) - obj.destroy(); - controller.fetchResources(); - }); + var baseDiscoveryUrl = endsWith(discoveryUrl, "/") ? discoveryUrl.substr(0, discoveryUrl.length - 1) : discoveryUrl; + if(endsWith(baseDiscoveryUrl, "/resources.json")) + baseDiscoveryUrl = baseDiscoveryUrl.substr(0, baseDiscoveryUrl.length - "/resources.json".length); + else if(endsWith(baseDiscoveryUrl, "/resources")) + baseDiscoveryUrl = baseDiscoveryUrl.substr(0, baseDiscoveryUrl.length - "/resources".length); + + this.discoveryUrlList.push(discoveryUrl); + this.discoveryUrlList.push(baseDiscoveryUrl); + this.discoveryUrlList.push(baseDiscoveryUrl + "/resources.json"); + this.discoveryUrlList.push(baseDiscoveryUrl + "/resources"); + + log("Will try the following urls to discover api endpoints:") + for(var i = 0; i < this.discoveryUrlList.length; i++) + log(" > " + this.discoveryUrlList[i]); + + this.fetchEndpointsSeq(); }, - fetchResources: function() { - //log("fetchResources"); + fetchEndpointsSeq: function() { + var controller = this; + + if(this.discoveryUrlListCursor < this.discoveryUrlList.length) { + var url = this.discoveryUrlList[this.discoveryUrlListCursor++] + updateStatus("Fetching API List from " + url); + log("Trying url " + url); + $.getJSON(url + apiKeySuffix, function(response) { + }) + .success(function(response) { + globalBasePath = url.substr(0, url.lastIndexOf("/")); + log("Setting globalBasePath to " + globalBasePath); + ApiResource.createAll(response.apis); + controller.fetchResources(response.basePath); + }) + .error(function(response) { + controller.fetchEndpointsSeq(); + }); + } else { + log ('Error with resource discovery. Exhaused all possible endpoint urls'); + + var urlsTried = ""; + for(var i = 0; i < this.discoveryUrlList.length; i++) { + urlsTried = urlsTried + "
" + this.discoveryUrlList[i]; + } + + updateStatus("Unable to fetch API Listing. Tried the following urls:" + urlsTried); + } + }, + + fetchResources: function(basePath) { + log("fetchResources: basePath = " + basePath); //ApiResource.logAll(); for (var i = 0; i < ApiResource.all().length; i++) { var apiResource = ApiResource.all()[i]; @@ -393,7 +428,7 @@ function SwaggerService(baseUrl, _apiKey, statusCallback) { fetchResource: function(apiResource) { var controller = this; updateStatus("Fetching " + apiResource.name + "..."); - var resourceUrl = apiHost + apiResource.path_json + apiKeySuffix; + var resourceUrl = globalBasePath + apiResource.path_json + apiKeySuffix; // log("resourceUrl: %o", resourceUrl); $.getJSON(resourceUrl, function(response) {