Compare commits

...
32 Commits
Author SHA1 Message Date
Tony Tam 264ba2910d updated client, version 2014-09-12 16:42:49 -07:00
Tony Tam 7b3b7066eb Merge pull request #543 from STRML/fixInlineEvents
Remove inline event handlers from resource template.
2014-09-12 13:51:55 -07:00
Samuel Reed 7a91117b6f Remove inline event handlers from resource template.
This allows us to use a strict CSP on explorer pages.
2014-09-12 14:30:42 -04:00
Tony Tam 9b0aa32941 rebuilt 2014-08-27 19:50:34 -07:00
Tony Tam b1964254c5 Merge pull request #540 from bezhermoso/throbber_img_reference
Moved reference to throbber.gif to CSS file.
2014-08-24 21:19:03 -07:00
Tony Tam 3a7b66d345 Merge pull request #541 from STRML/master
Fix self XSS in request url.
2014-08-24 11:04:36 -07:00
Samuel Reed 5da60bfa62 Fix potential self XSS in request url. 2014-08-24 11:02:54 -04:00
Bez Hermoso f8991bc7f5 Moved reference to throbber.gif to CSS file. 2014-08-21 13:20:45 -07:00
Tony Tam ec81d25cb0 Merge pull request #532 from Antek-drzewiecki/oauth_redirect_url_fix
Fixed oauth redirect url path. URL works with nested pathnames.
2014-08-14 08:30:27 -07:00
Antek Drzewiecki 2b08c0e209 Fixed oauth redirect url path. URL works with nested pathnames. 2014-08-14 17:01:18 +02:00
Tony Tam ee199633f6 fixes for https://github.com/wordnik/swagger-js/issues/107 2014-08-06 15:59:32 -07:00
Tony Tam 4ea20859c7 updated swagger-js 2014-08-02 15:24:51 -07:00
Tony Tam 0a52e344e7 updated swagger-js, added #507 to dist 2014-08-02 09:31:17 -07:00
Tony Tam e04b756521 Merge pull request #507 from jbryson3/master
Provide option highlightSizeThreshold
2014-08-01 19:44:25 -07:00
Tony Tam 9955bcc69f updated versions 2014-08-01 17:34:15 -07:00
Tony Tam c17cc1010f rebuilt 2014-08-01 17:15:42 -07:00
Tony Tam 2de104aac9 updated templates to support file as body or form params 2014-08-01 17:13:56 -07:00
Tony Tam fbe5278928 updated logger to avoid logging arrays 2014-08-01 17:13:30 -07:00
Tony Tam b09a8e91c9 updated key name 2014-08-01 17:12:08 -07:00
Tony Tam c3904c54c8 updated key name 2014-08-01 17:11:59 -07:00
Tony Tam 26db2ce375 updated swagger-js to 2.0.34 2014-08-01 17:11:36 -07:00
John Bryson 28c7597138 Provide option highlightSizeThreshold to allow conditional syntax highlighting based on response size 2014-07-31 11:56:13 -04:00
Tony Tam c948b40d34 Merge pull request #496 from chatch/master
sort routes alphabetically (254)
2014-07-28 07:45:31 -07:00
Chris Hatch 5d2bed7025 provide option sorter=[alpha|method] 2014-07-27 21:18:18 +08:00
Chris Hatch 6dc12f733e Merge branch 'master' of https://github.com/wordnik/swagger-ui 2014-07-27 20:24:01 +08:00
Tony Tam dfd5e937d4 Merge pull request #500 from 3scale/patch-2
Fixed undefined variable error
2014-07-24 12:01:46 -07:00
aurelian 9d0417e7f2 fixed undefined variable errors 2014-07-24 17:42:51 +02:00
Chris Hatch 8ad46f0813 remove console.info 2014-07-20 20:21:28 +08:00
Chris Hatch db6419414c #254 alphabetical sort of apis and operations under apis
new option sortAlphabetical=true|false
2014-07-20 20:18:19 +08:00
Tony Tam 9b9b5b4551 updated distro to include #493 2014-07-14 13:42:57 -06:00
Tony Tam 50ded295d9 Merge pull request #493 from vanderlee/patch-1
Fix for issue #492; HTML in response headers
2014-07-14 13:41:46 -06:00
Martijn van der Lee 525241fcd2 Fix for issue #492; HTML in response headers
Fix for issue #492 by escaping the response headers using Underscore
2014-07-14 20:39:54 +02:00
21 changed files with 712 additions and 458 deletions
+2
View File
@@ -59,8 +59,10 @@ To use swagger-ui you should take a look at the [source of swagger-ui html page]
* *dom_id parameter* is the the id of a dom element inside which SwaggerUi will put the user interface for swagger
* *booleanValues* SwaggerUI renders boolean data types as a dropdown. By default it provides a 'true' and 'false' string as the possible choices. You can use this parameter to change the values in dropdown to be something else, for example 0 and 1 by setting booleanValues to new Array(0, 1)
* *docExpansion* controls how the API listing is displayed. It can be set to 'none' (default), 'list' (shows operations for each resource), or 'full' (fully expanded: shows operations and their details)
* *sorter* apply a sort to the API list. It can be 'alpha' (sort paths alphanumerically) or 'method' (sort operations by HTTP method). Default is the order returned by the server unchanged.
* *onComplete* is a callback function parameter which can be passed to be notified of when SwaggerUI has completed rendering successfully.
* *onFailure* is a callback function parameter which can be passed to be notified of when SwaggerUI encountered a failure was unable to render.
* *highlightSizeThreshold* any size response below this threshold will be highlighted syntactically, attempting to highlight large responses can lead to browser hangs, not including a threshold will default to highlight all returned responses
* All other parameters are explained in greater detail below
+8 -5
View File
@@ -743,17 +743,20 @@
display: inline-block;
font-size: 0.9em;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header img {
display: block;
clear: none;
float: right;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit {
display: block;
clear: none;
float: left;
padding: 6px 8px;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber {
background-image: url('../images/throbber.gif');
width: 128px;
height: 16px;
display: block;
clear: none;
float: right;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error {
outline: 2px solid black;
outline-color: #cc0000;
+2 -1
View File
@@ -47,7 +47,8 @@
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none"
docExpansion: "none",
sorter : "alpha"
});
$('#input_apiKey').change(function() {
+48 -55
View File
@@ -48,72 +48,65 @@ function handleLogin() {
str += '</label></li>';
popup.append(str);
}
}
var $win = $(window),
dw = $win.width(),
dh = $win.height(),
st = $win.scrollTop(),
dlgWd = popupDialog.outerWidth(),
dlgHt = popupDialog.outerHeight(),
top = (dh -dlgHt)/2 + st,
left = (dw - dlgWd)/2;
var $win = $(window),
dw = $win.width(),
dh = $win.height(),
st = $win.scrollTop(),
dlgWd = popupDialog.outerWidth(),
dlgHt = popupDialog.outerHeight(),
top = (dh -dlgHt)/2 + st,
left = (dw - dlgWd)/2;
popupDialog.css({
top: (top < 0? 0 : top) + 'px',
left: (left < 0? 0 : left) + 'px'
});
popupDialog.css({
top: (top < 0? 0 : top) + 'px',
left: (left < 0? 0 : left) + 'px'
});
popupDialog.find('button.api-popup-cancel').click(function() {
popupMask.hide();
popupDialog.hide();
});
popupDialog.find('button.api-popup-authbtn').click(function() {
popupMask.hide();
popupDialog.hide();
popupDialog.find('button.api-popup-cancel').click(function() {
popupMask.hide();
popupDialog.hide();
});
popupDialog.find('button.api-popup-authbtn').click(function() {
popupMask.hide();
popupDialog.hide();
var authSchemes = window.swaggerUi.api.authSchemes;
var location = window.location;
var locationUrl = location.protocol + '//' + location.host + location.pathname;
var redirectUrl = locationUrl.replace("index.html","").concat("/o2c.html").replace("//o2c.html","/o2c.html");
var url = null;
var authSchemes = window.swaggerUi.api.authSchemes;
var host = window.location;
var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var redirectUrl = host.protocol + '//' + host.host + pathname + "/o2c.html";
var url = null;
var p = window.swaggerUi.api.authSchemes;
for (var key in p) {
if (p.hasOwnProperty(key)) {
var o = p[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
url = dets.loginEndpoint.url + "?response_type=token";
window.swaggerUi.tokenName = dets.tokenName;
}
for (var key in authSchemes) {
if (authSchemes.hasOwnProperty(key)) {
var o = authSchemes[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
url = dets.loginEndpoint.url + "?response_type=token";
window.swaggerUi.tokenName = dets.tokenName;
}
}
}
var scopes = [];
var scopeForUrl='';
var o = $('.api-popup-scopes').find('input:checked');
}
var scopes = []
var o = $('.api-popup-scopes').find('input:checked');
for(var k =0; k < o.length; k++) {
scopes.push($(o[k]).attr("scope"));
if(k > 0){
scopeForUrl+=' ';
}
scopeForUrl+=$(o[k]).attr("scope");
}
for(k =0; k < o.length; k++) {
scopes.push($(o[k]).attr("scope"));
}
window.enabledScopes=scopes;
window.enabledScopes=scopes;
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopeForUrl);
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopes);
window.open(url);
});
window.open(url);
});
}
popupMask.show();
popupDialog.show();
return;
@@ -211,7 +204,7 @@ function onOAuthComplete(token) {
}
});
window.authorizations.add("key", new ApiKeyAuthorization("Authorization", "Bearer " + b, "header"));
window.authorizations.add("oauth2", new ApiKeyAuthorization("Authorization", "Bearer " + b, "header"));
}
}
}
+220 -136
View File
@@ -1,5 +1,5 @@
// swagger.js
// version 2.0.31
// version 2.0.39
var __bind = function(fn, me){
return function(){
@@ -11,10 +11,20 @@ log = function(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
console.log( Array.prototype.slice.call(arguments)[0] );
}
};
// if you want to apply conditional formatting of parameter values
parameterMacro = function(value) {
return value;
}
// if you want to apply conditional formatting of model property values
modelPropertyMacro = function(value) {
return value;
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++) {
@@ -45,42 +55,42 @@ if (!('map' in Array.prototype)) {
}
Object.keys = Object.keys || (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
DontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
DontEnumsLength = DontEnums.length;
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
DontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
DontEnumsLength = DontEnums.length;
return function (o) {
if (typeof o != "object" && typeof o != "function" || o === null)
throw new TypeError("Object.keys called on a non-object");
return function (o) {
if (typeof o != "object" && typeof o != "function" || o === null)
throw new TypeError("Object.keys called on a non-object");
var result = [];
for (var name in o) {
if (hasOwnProperty.call(o, name))
result.push(name);
}
var result = [];
for (var name in o) {
if (hasOwnProperty.call(o, name))
result.push(name);
}
if (hasDontEnumBug) {
for (var i = 0; i < DontEnumsLength; i++) {
if (hasOwnProperty.call(o, DontEnums[i]))
result.push(DontEnums[i]);
}
}
if (hasDontEnumBug) {
for (var i = 0; i < DontEnumsLength; i++) {
if (hasOwnProperty.call(o, DontEnums[i]))
result.push(DontEnums[i]);
}
}
return result;
};
return result;
};
})();
var SwaggerApi = function(url, options) {
this.isBuilt = false;
this.url = null;
this.debug = false;
this.basePath = null;
@@ -88,6 +98,7 @@ var SwaggerApi = function(url, options) {
this.authorizationScheme = null;
this.info = null;
this.useJQuery = false;
this.modelsArray = [];
options = (options||{});
if (url)
@@ -109,11 +120,15 @@ var SwaggerApi = function(url, options) {
this.failure = options.failure != null ? options.failure : function() {};
this.progress = options.progress != null ? options.progress : function() {};
if (options.success != null)
if (options.success != null) {
this.build();
this.isBuilt = true;
}
}
SwaggerApi.prototype.build = function() {
if(this.isBuilt)
return this;
var _this = this;
this.progress('fetching resource list: ' + this.url);
var obj = {
@@ -121,7 +136,7 @@ SwaggerApi.prototype.build = function() {
url: this.url,
method: "get",
headers: {
accept: "application/json"
accept: "application/json,application/json;charset=\"utf-8\",*/*"
},
on: {
error: function(response) {
@@ -158,6 +173,7 @@ SwaggerApi.prototype.buildFromSpec = function(response) {
}
this.apis = {};
this.apisArray = [];
this.consumes = response.consumes;
this.produces = response.produces;
this.authSchemes = response.authorizations;
if (response.info != null) {
@@ -175,13 +191,13 @@ SwaggerApi.prototype.buildFromSpec = function(response) {
}
}
}
if (response.basePath) {
if (response.basePath)
this.basePath = response.basePath;
} else if (this.url.indexOf('?') > 0) {
else if (this.url.indexOf('?') > 0)
this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
} else {
else
this.basePath = this.url;
}
if (isApi) {
var newName = response.resourcePath.replace(/\//g, '');
this.resourcePath = response.resourcePath;
@@ -276,7 +292,6 @@ SwaggerApi.prototype.fail = function(message) {
SwaggerApi.prototype.setConsolidatedModels = function() {
var model, modelName, resource, resource_name, _i, _len, _ref, _ref1, _results;
this.modelsArray = [];
this.models = {};
_ref = this.apis;
for (resource_name in _ref) {
@@ -321,8 +336,8 @@ var SwaggerResource = function(resourceObj, api) {
var _this = this;
this.api = api;
this.api = this.api;
produces = [];
consumes = [];
consumes = (this.consumes | []);
produces = (this.produces | []);
this.path = this.api.resourcePath != null ? this.api.resourcePath : resourceObj.path;
this.description = resourceObj.description;
@@ -353,7 +368,7 @@ var SwaggerResource = function(resourceObj, api) {
method: "get",
useJQuery: this.useJQuery,
headers: {
accept: "application/json"
accept: "application/json,application/json;charset=\"utf-8\",*/*"
},
on: {
response: function(resp) {
@@ -378,20 +393,22 @@ SwaggerResource.prototype.getAbsoluteBasePath = function (relativeBasePath) {
pos = url.lastIndexOf(relativeBasePath);
var parts = url.split("/");
var rootUrl = parts[0] + "//" + parts[2];
//if the relative path is '/' return the root url
if (relativeBasePath === '/'){
return rootUrl
if(relativeBasePath.indexOf("http") === 0)
return relativeBasePath;
if(relativeBasePath === "/")
return rootUrl;
if(relativeBasePath.substring(0, 1) == "/") {
// use root + relative
return rootUrl + relativeBasePath;
}
//if the relative path is not in the base path
else if (pos === -1 ) {
if (relativeBasePath.indexOf("/") === 0) {
return url + relativeBasePath;
} else {
return url + "/" + relativeBasePath;
}
//If the relative path is in the base path
} else {
return url.substring(0, pos) + relativeBasePath;
else {
var pos = this.basePath.lastIndexOf("/");
var base = this.basePath.substring(0, pos);
if(base.substring(base.length - 1) == "/")
return base + relativeBasePath;
else
return base + "/" + relativeBasePath;
}
};
@@ -591,6 +608,7 @@ var SwaggerModelProperty = function(name, obj) {
this.isCollection = this.dataType && (this.dataType.toLowerCase() === 'array' || this.dataType.toLowerCase() === 'list' || this.dataType.toLowerCase() === 'set');
this.descr = obj.description;
this.required = obj.required;
this.defaultValue = modelPropertyMacro(obj.defaultValue);
if (obj.items != null) {
if (obj.items.type != null) {
this.refDataType = obj.items.type;
@@ -636,7 +654,9 @@ SwaggerModelProperty.prototype.getSampleValue = function(modelsToIgnore) {
SwaggerModelProperty.prototype.toSampleValue = function(value) {
var result;
if (value === "integer") {
if ((typeof this.defaultValue !== 'undefined') && this.defaultValue !== null) {
result = this.defaultValue;
} else if (value === "integer") {
result = 0;
} else if (value === "boolean") {
result = false;
@@ -766,6 +786,7 @@ var SwaggerOperation = function(nickname, path, method, parameters, summary, not
}
}
}
param.defaultValue = parameterMacro(param.defaultValue);
}
this.resource[this.nickname] = function(args, callback, error) {
return _this["do"](args, callback, error);
@@ -1097,98 +1118,59 @@ var SwaggerRequest = function(type, url, params, opts, successCallback, errorCal
this.type = this.type.toUpperCase();
var myHeaders = {};
// set request, response content type headers
var headers = this.setHeaders(params, this.operation);
var body = params.body;
var parent = params["parent"];
var requestContentType = "application/json";
var formParams = [];
var fileParams = [];
var params = this.operation.parameters;
for(var i = 0; i < params.length; i++) {
var param = params[i];
if(param.paramType === "form")
formParams.push(param);
else if(param.paramType === "file")
fileParams.push(param);
}
if (body && (this.type === "POST" || this.type === "PUT" || this.type === "PATCH")) {
if (this.opts.requestContentType) {
requestContentType = this.opts.requestContentType;
}
} else {
// if any form params, content type must be set
if(formParams.length > 0) {
if(fileParams.length > 0)
requestContentType = "multipart/form-data";
else
requestContentType = "application/x-www-form-urlencoded";
}
else if (this.type == "DELETE")
body = "{}";
else if (this.type != "DELETE")
requestContentType = null;
}
if (requestContentType && this.operation.consumes) {
if (this.operation.consumes[requestContentType] === 'undefined') {
log("server doesn't consume " + requestContentType + ", try " + JSON.stringify(this.operation.consumes));
if (this.requestContentType === null) {
requestContentType = this.operation.consumes[0];
}
}
}
var responseContentType = null;
if (this.opts.responseContentType) {
responseContentType = this.opts.responseContentType;
} else {
responseContentType = "application/json";
}
if (responseContentType && this.operation.produces) {
if (this.operation.produces[responseContentType] === 'undefined') {
log("server can't produce " + responseContentType);
}
}
if (requestContentType && requestContentType.indexOf("application/x-www-form-urlencoded") === 0) {
var fields = {};
var possibleParams = {};
// encode the body for form submits
if (headers["Content-Type"]) {
var values = {};
var key;
for(key in formParams){
var param = formParams[key];
values[param.name] = param;
var i;
var operationParams = this.operation.parameters;
for(i = 0; i < operationParams.length; i++) {
var param = operationParams[i];
if(param.paramType === "form")
values[param.name] = param;
}
var encoded = "";
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined'){
if(encoded !== "")
encoded += "&";
encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
if(headers["Content-Type"].indexOf("application/x-www-form-urlencoded") === 0) {
var encoded = "";
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined'){
if(encoded !== "")
encoded += "&";
encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
}
body = encoded;
}
else if (headers["Content-Type"].indexOf("multipart/form-data") === 0) {
// encode the body for form submits
var data = "";
var boundary = "----SwaggerFormBoundary" + Date.now();
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined') {
data += '--' + boundary + '\n';
data += 'Content-Disposition: form-data; name="' + key + '"';
data += '\n\n';
data += value + "\n";
}
}
data += "--" + boundary + "--\n";
headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
body = data;
}
body = encoded;
}
var name;
for (name in this.headers)
myHeaders[name] = this.headers[name];
if ((requestContentType && body !== "") || (requestContentType === "application/x-www-form-urlencoded"))
myHeaders["Content-Type"] = requestContentType;
if (responseContentType)
myHeaders["Accept"] = responseContentType;
if (!((this.headers != null) && (this.headers.mock != null))) {
obj = {
url: this.url,
method: this.type,
headers: myHeaders,
headers: headers,
body: body,
useJQuery: this.useJQuery,
on: {
@@ -1225,6 +1207,77 @@ var SwaggerRequest = function(type, url, params, opts, successCallback, errorCal
}
};
SwaggerRequest.prototype.setHeaders = function(params, operation) {
// default type
var accepts = "application/json";
var consumes = "application/json";
var allDefinedParams = this.operation.parameters;
var definedFormParams = [];
var definedFileParams = [];
var body = params.body;
var headers = {};
// get params from the operation and set them in definedFileParams, definedFormParams, headers
var i;
for(i = 0; i < allDefinedParams.length; i++) {
var param = allDefinedParams[i];
if(param.paramType === "form")
definedFormParams.push(param);
else if(param.paramType === "file")
definedFileParams.push(param);
else if(param.paramType === "header" && this.params.headers) {
var key = param.name;
var headerValue = this.params.headers[param.name];
if(typeof this.params.headers[param.name] !== 'undefined')
headers[key] = headerValue;
}
}
// if there's a body, need to set the accepts header via requestContentType
if (body && (this.type === "POST" || this.type === "PUT" || this.type === "PATCH" || this.type === "DELETE")) {
if (this.opts.requestContentType)
consumes = this.opts.requestContentType;
} else {
// if any form params, content type must be set
if(definedFormParams.length > 0) {
if(definedFileParams.length > 0)
consumes = "multipart/form-data";
else
consumes = "application/x-www-form-urlencoded";
}
else if (this.type === "DELETE")
body = "{}";
else if (this.type != "DELETE")
accepts = null;
}
if (consumes && this.operation.consumes) {
if (this.operation.consumes.indexOf(consumes) === -1) {
log("server doesn't consume " + consumes + ", try " + JSON.stringify(this.operation.consumes));
consumes = this.operation.consumes[0];
}
}
if (this.opts.responseContentType) {
accepts = this.opts.responseContentType;
} else {
accepts = "application/json";
}
if (accepts && this.operation.produces) {
if (this.operation.produces.indexOf(accepts) === -1) {
log("server can't produce " + accepts);
accepts = this.operation.produces[0];
}
}
if ((consumes && body !== "") || (consumes === "application/x-www-form-urlencoded"))
headers["Content-Type"] = consumes;
if (accepts)
headers["Accept"] = accepts;
return headers;
}
SwaggerRequest.prototype.asCurl = function() {
var results = [];
if(this.headers) {
@@ -1427,11 +1480,36 @@ ShredHttpClient.prototype.execute = function(obj) {
return out;
};
// Transform an error into a usable response-like object
var transformError = function(error) {
var out = {
// Default to a status of 0 - The client will treat this as a generic permissions sort of error
status: 0,
data: error.message || error
};
if(error.code) {
out.obj = error;
if(error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED' ) {
// We can tell the client that this should be treated as a missing resource and not as a permissions thing
out.status = 404;
}
}
return out;
};
res = {
error: function(response) {
if (obj)
return cb.error(transform(response));
},
// Catch the Shred error raised when the request errors as it is made (i.e. No Response is coming)
request_error: function(err) {
if(obj)
return cb.error(transformError(err));
},
redirect: function(response) {
if (obj)
return cb.redirect(transform(response));
@@ -1499,10 +1577,11 @@ SwaggerAuthorizations.prototype.apply = function(obj, authorizations) {
/**
* ApiKeyAuthorization allows a query param or header to be injected
*/
var ApiKeyAuthorization = function(name, value, type) {
var ApiKeyAuthorization = function(name, value, type, delimiter) {
this.name = name;
this.value = value;
this.type = type;
this.delimiter = delimiter;
};
ApiKeyAuthorization.prototype.apply = function(obj, authorizations) {
@@ -1513,7 +1592,12 @@ ApiKeyAuthorization.prototype.apply = function(obj, authorizations) {
obj.url = obj.url + "?" + this.name + "=" + this.value;
return true;
} else if (this.type === "header") {
obj.headers[this.name] = this.value;
if(typeof obj.headers[this.name] !== 'undefined') {
if(typeof this.delimiter !== 'undefined')
obj.headers[this.name] = obj.headers[this.name] + this.delimiter + this.value;
}
else
obj.headers[this.name] = this.value;
return true;
}
};
+83 -28
View File
@@ -1,5 +1,5 @@
// swagger-ui.js
// version 2.0.18
// version 2.0.23
$(function() {
// Helper function for vertically aligning DOM elements
@@ -68,7 +68,7 @@ log = function(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
console.log( Array.prototype.slice.call(arguments)[0] );
}
};
@@ -396,7 +396,7 @@ function program18(depth0,data) {
function program20(depth0,data) {
return "\n <div class='sandbox_header'>\n <input class='submit' name='commit' type='button' value='Try it out!' />\n <a href='#' class='response_hider' style='display:none'>Hide Response</a>\n <img alt='Throbber' class='response_throbber' src='images/throbber.gif' style='display:none' />\n </div>\n ";
return "\n <div class='sandbox_header'>\n <input class='submit' name='commit' type='button' value='Try it out!' />\n <a href='#' class='response_hider' style='display:none'>Hide Response</a>\n <span class='response_throbber' style='display:none'></span>\n </div>\n ";
}
buffer += "\n <ul class='operations' >\n <li class='";
@@ -562,7 +562,7 @@ function program9(depth0,data) {
var buffer = "", stack1;
buffer += "\n ";
stack1 = helpers['if'].call(depth0, depth0.defaultValue, {hash:{},inverse:self.program(12, program12, data),fn:self.program(10, program10, data),data:data});
stack1 = helpers['if'].call(depth0, depth0.isFile, {hash:{},inverse:self.program(10, program10, data),fn:self.program(2, program2, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n ";
return buffer;
@@ -570,7 +570,16 @@ function program9(depth0,data) {
function program10(depth0,data) {
var buffer = "", stack1;
buffer += "\n <input class='parameter' minlength='0' name='";
buffer += "\n ";
stack1 = helpers['if'].call(depth0, depth0.defaultValue, {hash:{},inverse:self.program(13, program13, data),fn:self.program(11, program11, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n ";
return buffer;
}
function program11(depth0,data) {
var buffer = "", stack1;
buffer += "\n <input class='parameter' minlength='0' name='";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
@@ -578,18 +587,18 @@ function program10(depth0,data) {
if (stack1 = helpers.defaultValue) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.defaultValue; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "'/>\n ";
+ "'/>\n ";
return buffer;
}
function program12(depth0,data) {
function program13(depth0,data) {
var buffer = "", stack1;
buffer += "\n <input class='parameter' minlength='0' name='";
buffer += "\n <input class='parameter' minlength='0' name='";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "' placeholder='' type='text' value=''/>\n ";
+ "' placeholder='' type='text' value=''/>\n ";
return buffer;
}
@@ -1072,11 +1081,11 @@ function program1(depth0,data) {
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "' onclick=\"Docs.toggleEndpointListForResource('";
+ "' class=\"toggleEndpointList\" data-id=\"";
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "');\">";
+ "\">";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
@@ -1097,19 +1106,19 @@ function program1(depth0,data) {
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "'\n onclick=\"Docs.toggleEndpointListForResource('";
+ "' class=\"toggleEndpointList\" data-id=\"";
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "');\">Show/Hide</a>\n </li>\n <li>\n <a href='#' onclick=\"Docs.collapseOperationsForResource('";
+ "\">Show/Hide</a>\n </li>\n <li>\n <a href='#' class=\"collapseResource\" data-id=\"";
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "'); return false;\">\n List Operations\n </a>\n </li>\n <li>\n <a href='#' onclick=\"Docs.expandOperationsForResource('";
+ "\">\n List Operations\n </a>\n </li>\n <li>\n <a href='#' class=\"expandResource\" data-id=";
if (stack1 = helpers.id) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "'); return false;\">\n Expand Operations\n </a>\n </li>\n <li>\n <a href='";
+ ">\n Expand Operations\n </a>\n </li>\n <li>\n <a href='";
if (stack1 = helpers.url) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.url; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
@@ -1289,7 +1298,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
this.showMessage('Finished Loading Resource Information. Rendering Swagger UI...');
this.mainView = new MainView({
model: this.api,
el: $('#' + this.dom_id)
el: $('#' + this.dom_id),
swaggerOptions: this.options
}).render();
this.showMessage();
switch (this.options.docExpansion) {
@@ -1422,6 +1432,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
})(Backbone.View);
MainView = (function(_super) {
var sorters;
__extends(MainView, _super);
function MainView() {
@@ -1429,7 +1441,33 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
return _ref2;
}
MainView.prototype.initialize = function() {};
sorters = {
'alpha': function(a, b) {
return a.path.localeCompare(b.path);
},
'method': function(a, b) {
return a.method.localeCompare(b.method);
}
};
MainView.prototype.initialize = function(opts) {
var route, sorter, sorterName, _i, _len, _ref3;
if (opts == null) {
opts = {};
}
if (opts.swaggerOptions.sorter) {
sorterName = opts.swaggerOptions.sorter;
sorter = sorters[sorterName];
_ref3 = this.model.apisArray;
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
route = _ref3[_i];
route.operationsArray.sort(sorter);
}
if (sorterName === "alpha") {
return this.model.apisArray.sort(sorter);
}
}
};
MainView.prototype.render = function() {
var counter, id, resource, resources, _i, _len, _ref3;
@@ -1457,7 +1495,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
model: resource,
tagName: 'li',
id: 'resource_' + resource.id,
className: 'resource'
className: 'resource',
swaggerOptions: this.options.swaggerOptions
});
return $('#resources').append(resourceView.render().el);
};
@@ -1498,6 +1537,9 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
operation.parentId = this.model.id;
this.addOperation(operation);
}
$('.toggleEndpointList', this.el).click(this.callDocs.bind(this, 'toggleEndpointListForResource'));
$('.collapseResource', this.el).click(this.callDocs.bind(this, 'collapseOperationsForResource'));
$('.expandResource', this.el).click(this.callDocs.bind(this, 'expandOperationsForResoruce'));
return this;
};
@@ -1507,12 +1549,18 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
operationView = new OperationView({
model: operation,
tagName: 'li',
className: 'endpoint'
className: 'endpoint',
swaggerOptions: this.options.swaggerOptions
});
$('.endpoints', $(this.el)).append(operationView.render().el);
return this.number++;
};
ResourceView.prototype.callDocs = function(fnName, e) {
e.preventDefault();
return Docs[fnName](e.currentTarget.getAttribute('data-id'));
};
return ResourceView;
})(Backbone.View);
@@ -1541,8 +1589,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
OperationView.prototype.mouseEnter = function(e) {
var elem, hgh, pos, scMaxX, scMaxY, scX, scY, wd, x, y;
elem = $(e.currentTarget.parentNode).find('#api_information_panel');
x = event.pageX;
y = event.pageY;
x = e.pageX;
y = e.pageY;
scX = $(window).scrollLeft();
scY = $(window).scrollTop();
scMaxX = scX + $(window).width();
@@ -1747,7 +1795,7 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) {
param = _ref6[_j];
if (param.paramType === 'form') {
if (map[param.name] !== void 0) {
if (param.type.toLowerCase() !== 'file' && map[param.name] !== void 0) {
bodyParam.append(param.name, map[param.name]);
}
}
@@ -1769,9 +1817,9 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
params += 1;
}
}
log(bodyParam);
this.invocationUrl = this.model.supportHeaderParams() ? (headerParams = this.model.getHeaderParams(map), this.model.urlify(map, false)) : this.model.urlify(map, true);
$(".request_url", $(this.el)).html("<pre>" + this.invocationUrl + "</pre>");
$(".request_url", $(this.el)).html("<pre></pre>");
$(".request_url pre", $(this.el)).text(this.invocationUrl);
obj = {
type: this.model.method,
url: this.invocationUrl,
@@ -1938,7 +1986,7 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
};
OperationView.prototype.showStatus = function(response) {
var code, content, contentType, headers, pre, response_body, url;
var code, content, contentType, headers, opts, pre, response_body, response_body_el, url;
if (response.content === void 0) {
content = response.data;
url = response.url;
@@ -1967,14 +2015,21 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
pre = $('<pre class="json" />').append(code);
}
response_body = pre;
$(".request_url", $(this.el)).html("<pre>" + url + "</pre>");
$(".request_url", $(this.el)).html("<pre></pre>");
$(".request_url pre", $(this.el)).text(url);
$(".response_code", $(this.el)).html("<pre>" + response.status + "</pre>");
$(".response_body", $(this.el)).html(response_body);
$(".response_headers", $(this.el)).html("<pre>" + JSON.stringify(response.headers, null, " ").replace(/\n/g, "<br>") + "</pre>");
$(".response_headers", $(this.el)).html("<pre>" + _.escape(JSON.stringify(response.headers, null, " ")).replace(/\n/g, "<br>") + "</pre>");
$(".response", $(this.el)).slideDown();
$(".response_hider", $(this.el)).show();
$(".response_throbber", $(this.el)).hide();
return hljs.highlightBlock($('.response_body', $(this.el))[0]);
response_body_el = $('.response_body', $(this.el))[0];
opts = this.options.swaggerOptions;
if (opts.highlightSizeThreshold && response.data.length > opts.highlightSizeThreshold) {
return response_body_el;
} else {
return hljs.highlightBlock(response_body_el);
}
};
OperationView.prototype.toggleOperationContent = function() {
+1 -1
View File
File diff suppressed because one or more lines are too long
+48 -55
View File
@@ -48,72 +48,65 @@ function handleLogin() {
str += '</label></li>';
popup.append(str);
}
}
var $win = $(window),
dw = $win.width(),
dh = $win.height(),
st = $win.scrollTop(),
dlgWd = popupDialog.outerWidth(),
dlgHt = popupDialog.outerHeight(),
top = (dh -dlgHt)/2 + st,
left = (dw - dlgWd)/2;
var $win = $(window),
dw = $win.width(),
dh = $win.height(),
st = $win.scrollTop(),
dlgWd = popupDialog.outerWidth(),
dlgHt = popupDialog.outerHeight(),
top = (dh -dlgHt)/2 + st,
left = (dw - dlgWd)/2;
popupDialog.css({
top: (top < 0? 0 : top) + 'px',
left: (left < 0? 0 : left) + 'px'
});
popupDialog.css({
top: (top < 0? 0 : top) + 'px',
left: (left < 0? 0 : left) + 'px'
});
popupDialog.find('button.api-popup-cancel').click(function() {
popupMask.hide();
popupDialog.hide();
});
popupDialog.find('button.api-popup-authbtn').click(function() {
popupMask.hide();
popupDialog.hide();
popupDialog.find('button.api-popup-cancel').click(function() {
popupMask.hide();
popupDialog.hide();
});
popupDialog.find('button.api-popup-authbtn').click(function() {
popupMask.hide();
popupDialog.hide();
var authSchemes = window.swaggerUi.api.authSchemes;
var location = window.location;
var locationUrl = location.protocol + '//' + location.host + location.pathname;
var redirectUrl = locationUrl.replace("index.html","").concat("/o2c.html").replace("//o2c.html","/o2c.html");
var url = null;
var authSchemes = window.swaggerUi.api.authSchemes;
var host = window.location;
var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var redirectUrl = host.protocol + '//' + host.host + pathname + "/o2c.html";
var url = null;
var p = window.swaggerUi.api.authSchemes;
for (var key in p) {
if (p.hasOwnProperty(key)) {
var o = p[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
url = dets.loginEndpoint.url + "?response_type=token";
window.swaggerUi.tokenName = dets.tokenName;
}
for (var key in authSchemes) {
if (authSchemes.hasOwnProperty(key)) {
var o = authSchemes[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
url = dets.loginEndpoint.url + "?response_type=token";
window.swaggerUi.tokenName = dets.tokenName;
}
}
}
var scopes = [];
var scopeForUrl='';
var o = $('.api-popup-scopes').find('input:checked');
}
var scopes = []
var o = $('.api-popup-scopes').find('input:checked');
for(var k =0; k < o.length; k++) {
scopes.push($(o[k]).attr("scope"));
if(k > 0){
scopeForUrl+=' ';
}
scopeForUrl+=$(o[k]).attr("scope");
}
for(k =0; k < o.length; k++) {
scopes.push($(o[k]).attr("scope"));
}
window.enabledScopes=scopes;
window.enabledScopes=scopes;
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopeForUrl);
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopes);
window.open(url);
});
window.open(url);
});
}
popupMask.show();
popupDialog.show();
return;
@@ -211,7 +204,7 @@ function onOAuthComplete(token) {
}
});
window.authorizations.add("key", new ApiKeyAuthorization("Authorization", "Bearer " + b, "header"));
window.authorizations.add("oauth2", new ApiKeyAuthorization("Authorization", "Bearer " + b, "header"));
}
}
}
+220 -136
View File
@@ -1,5 +1,5 @@
// swagger.js
// version 2.0.31
// version 2.0.39
var __bind = function(fn, me){
return function(){
@@ -11,10 +11,20 @@ log = function(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
console.log( Array.prototype.slice.call(arguments)[0] );
}
};
// if you want to apply conditional formatting of parameter values
parameterMacro = function(value) {
return value;
}
// if you want to apply conditional formatting of model property values
modelPropertyMacro = function(value) {
return value;
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++) {
@@ -45,42 +55,42 @@ if (!('map' in Array.prototype)) {
}
Object.keys = Object.keys || (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
DontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
DontEnumsLength = DontEnums.length;
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
DontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
DontEnumsLength = DontEnums.length;
return function (o) {
if (typeof o != "object" && typeof o != "function" || o === null)
throw new TypeError("Object.keys called on a non-object");
return function (o) {
if (typeof o != "object" && typeof o != "function" || o === null)
throw new TypeError("Object.keys called on a non-object");
var result = [];
for (var name in o) {
if (hasOwnProperty.call(o, name))
result.push(name);
}
var result = [];
for (var name in o) {
if (hasOwnProperty.call(o, name))
result.push(name);
}
if (hasDontEnumBug) {
for (var i = 0; i < DontEnumsLength; i++) {
if (hasOwnProperty.call(o, DontEnums[i]))
result.push(DontEnums[i]);
}
}
if (hasDontEnumBug) {
for (var i = 0; i < DontEnumsLength; i++) {
if (hasOwnProperty.call(o, DontEnums[i]))
result.push(DontEnums[i]);
}
}
return result;
};
return result;
};
})();
var SwaggerApi = function(url, options) {
this.isBuilt = false;
this.url = null;
this.debug = false;
this.basePath = null;
@@ -88,6 +98,7 @@ var SwaggerApi = function(url, options) {
this.authorizationScheme = null;
this.info = null;
this.useJQuery = false;
this.modelsArray = [];
options = (options||{});
if (url)
@@ -109,11 +120,15 @@ var SwaggerApi = function(url, options) {
this.failure = options.failure != null ? options.failure : function() {};
this.progress = options.progress != null ? options.progress : function() {};
if (options.success != null)
if (options.success != null) {
this.build();
this.isBuilt = true;
}
}
SwaggerApi.prototype.build = function() {
if(this.isBuilt)
return this;
var _this = this;
this.progress('fetching resource list: ' + this.url);
var obj = {
@@ -121,7 +136,7 @@ SwaggerApi.prototype.build = function() {
url: this.url,
method: "get",
headers: {
accept: "application/json"
accept: "application/json,application/json;charset=\"utf-8\",*/*"
},
on: {
error: function(response) {
@@ -158,6 +173,7 @@ SwaggerApi.prototype.buildFromSpec = function(response) {
}
this.apis = {};
this.apisArray = [];
this.consumes = response.consumes;
this.produces = response.produces;
this.authSchemes = response.authorizations;
if (response.info != null) {
@@ -175,13 +191,13 @@ SwaggerApi.prototype.buildFromSpec = function(response) {
}
}
}
if (response.basePath) {
if (response.basePath)
this.basePath = response.basePath;
} else if (this.url.indexOf('?') > 0) {
else if (this.url.indexOf('?') > 0)
this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
} else {
else
this.basePath = this.url;
}
if (isApi) {
var newName = response.resourcePath.replace(/\//g, '');
this.resourcePath = response.resourcePath;
@@ -276,7 +292,6 @@ SwaggerApi.prototype.fail = function(message) {
SwaggerApi.prototype.setConsolidatedModels = function() {
var model, modelName, resource, resource_name, _i, _len, _ref, _ref1, _results;
this.modelsArray = [];
this.models = {};
_ref = this.apis;
for (resource_name in _ref) {
@@ -321,8 +336,8 @@ var SwaggerResource = function(resourceObj, api) {
var _this = this;
this.api = api;
this.api = this.api;
produces = [];
consumes = [];
consumes = (this.consumes | []);
produces = (this.produces | []);
this.path = this.api.resourcePath != null ? this.api.resourcePath : resourceObj.path;
this.description = resourceObj.description;
@@ -353,7 +368,7 @@ var SwaggerResource = function(resourceObj, api) {
method: "get",
useJQuery: this.useJQuery,
headers: {
accept: "application/json"
accept: "application/json,application/json;charset=\"utf-8\",*/*"
},
on: {
response: function(resp) {
@@ -378,20 +393,22 @@ SwaggerResource.prototype.getAbsoluteBasePath = function (relativeBasePath) {
pos = url.lastIndexOf(relativeBasePath);
var parts = url.split("/");
var rootUrl = parts[0] + "//" + parts[2];
//if the relative path is '/' return the root url
if (relativeBasePath === '/'){
return rootUrl
if(relativeBasePath.indexOf("http") === 0)
return relativeBasePath;
if(relativeBasePath === "/")
return rootUrl;
if(relativeBasePath.substring(0, 1) == "/") {
// use root + relative
return rootUrl + relativeBasePath;
}
//if the relative path is not in the base path
else if (pos === -1 ) {
if (relativeBasePath.indexOf("/") === 0) {
return url + relativeBasePath;
} else {
return url + "/" + relativeBasePath;
}
//If the relative path is in the base path
} else {
return url.substring(0, pos) + relativeBasePath;
else {
var pos = this.basePath.lastIndexOf("/");
var base = this.basePath.substring(0, pos);
if(base.substring(base.length - 1) == "/")
return base + relativeBasePath;
else
return base + "/" + relativeBasePath;
}
};
@@ -591,6 +608,7 @@ var SwaggerModelProperty = function(name, obj) {
this.isCollection = this.dataType && (this.dataType.toLowerCase() === 'array' || this.dataType.toLowerCase() === 'list' || this.dataType.toLowerCase() === 'set');
this.descr = obj.description;
this.required = obj.required;
this.defaultValue = modelPropertyMacro(obj.defaultValue);
if (obj.items != null) {
if (obj.items.type != null) {
this.refDataType = obj.items.type;
@@ -636,7 +654,9 @@ SwaggerModelProperty.prototype.getSampleValue = function(modelsToIgnore) {
SwaggerModelProperty.prototype.toSampleValue = function(value) {
var result;
if (value === "integer") {
if ((typeof this.defaultValue !== 'undefined') && this.defaultValue !== null) {
result = this.defaultValue;
} else if (value === "integer") {
result = 0;
} else if (value === "boolean") {
result = false;
@@ -766,6 +786,7 @@ var SwaggerOperation = function(nickname, path, method, parameters, summary, not
}
}
}
param.defaultValue = parameterMacro(param.defaultValue);
}
this.resource[this.nickname] = function(args, callback, error) {
return _this["do"](args, callback, error);
@@ -1097,98 +1118,59 @@ var SwaggerRequest = function(type, url, params, opts, successCallback, errorCal
this.type = this.type.toUpperCase();
var myHeaders = {};
// set request, response content type headers
var headers = this.setHeaders(params, this.operation);
var body = params.body;
var parent = params["parent"];
var requestContentType = "application/json";
var formParams = [];
var fileParams = [];
var params = this.operation.parameters;
for(var i = 0; i < params.length; i++) {
var param = params[i];
if(param.paramType === "form")
formParams.push(param);
else if(param.paramType === "file")
fileParams.push(param);
}
if (body && (this.type === "POST" || this.type === "PUT" || this.type === "PATCH")) {
if (this.opts.requestContentType) {
requestContentType = this.opts.requestContentType;
}
} else {
// if any form params, content type must be set
if(formParams.length > 0) {
if(fileParams.length > 0)
requestContentType = "multipart/form-data";
else
requestContentType = "application/x-www-form-urlencoded";
}
else if (this.type == "DELETE")
body = "{}";
else if (this.type != "DELETE")
requestContentType = null;
}
if (requestContentType && this.operation.consumes) {
if (this.operation.consumes[requestContentType] === 'undefined') {
log("server doesn't consume " + requestContentType + ", try " + JSON.stringify(this.operation.consumes));
if (this.requestContentType === null) {
requestContentType = this.operation.consumes[0];
}
}
}
var responseContentType = null;
if (this.opts.responseContentType) {
responseContentType = this.opts.responseContentType;
} else {
responseContentType = "application/json";
}
if (responseContentType && this.operation.produces) {
if (this.operation.produces[responseContentType] === 'undefined') {
log("server can't produce " + responseContentType);
}
}
if (requestContentType && requestContentType.indexOf("application/x-www-form-urlencoded") === 0) {
var fields = {};
var possibleParams = {};
// encode the body for form submits
if (headers["Content-Type"]) {
var values = {};
var key;
for(key in formParams){
var param = formParams[key];
values[param.name] = param;
var i;
var operationParams = this.operation.parameters;
for(i = 0; i < operationParams.length; i++) {
var param = operationParams[i];
if(param.paramType === "form")
values[param.name] = param;
}
var encoded = "";
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined'){
if(encoded !== "")
encoded += "&";
encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
if(headers["Content-Type"].indexOf("application/x-www-form-urlencoded") === 0) {
var encoded = "";
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined'){
if(encoded !== "")
encoded += "&";
encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
}
body = encoded;
}
else if (headers["Content-Type"].indexOf("multipart/form-data") === 0) {
// encode the body for form submits
var data = "";
var boundary = "----SwaggerFormBoundary" + Date.now();
var key;
for(key in values) {
value = this.params[key];
if(typeof value !== 'undefined') {
data += '--' + boundary + '\n';
data += 'Content-Disposition: form-data; name="' + key + '"';
data += '\n\n';
data += value + "\n";
}
}
data += "--" + boundary + "--\n";
headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
body = data;
}
body = encoded;
}
var name;
for (name in this.headers)
myHeaders[name] = this.headers[name];
if ((requestContentType && body !== "") || (requestContentType === "application/x-www-form-urlencoded"))
myHeaders["Content-Type"] = requestContentType;
if (responseContentType)
myHeaders["Accept"] = responseContentType;
if (!((this.headers != null) && (this.headers.mock != null))) {
obj = {
url: this.url,
method: this.type,
headers: myHeaders,
headers: headers,
body: body,
useJQuery: this.useJQuery,
on: {
@@ -1225,6 +1207,77 @@ var SwaggerRequest = function(type, url, params, opts, successCallback, errorCal
}
};
SwaggerRequest.prototype.setHeaders = function(params, operation) {
// default type
var accepts = "application/json";
var consumes = "application/json";
var allDefinedParams = this.operation.parameters;
var definedFormParams = [];
var definedFileParams = [];
var body = params.body;
var headers = {};
// get params from the operation and set them in definedFileParams, definedFormParams, headers
var i;
for(i = 0; i < allDefinedParams.length; i++) {
var param = allDefinedParams[i];
if(param.paramType === "form")
definedFormParams.push(param);
else if(param.paramType === "file")
definedFileParams.push(param);
else if(param.paramType === "header" && this.params.headers) {
var key = param.name;
var headerValue = this.params.headers[param.name];
if(typeof this.params.headers[param.name] !== 'undefined')
headers[key] = headerValue;
}
}
// if there's a body, need to set the accepts header via requestContentType
if (body && (this.type === "POST" || this.type === "PUT" || this.type === "PATCH" || this.type === "DELETE")) {
if (this.opts.requestContentType)
consumes = this.opts.requestContentType;
} else {
// if any form params, content type must be set
if(definedFormParams.length > 0) {
if(definedFileParams.length > 0)
consumes = "multipart/form-data";
else
consumes = "application/x-www-form-urlencoded";
}
else if (this.type === "DELETE")
body = "{}";
else if (this.type != "DELETE")
accepts = null;
}
if (consumes && this.operation.consumes) {
if (this.operation.consumes.indexOf(consumes) === -1) {
log("server doesn't consume " + consumes + ", try " + JSON.stringify(this.operation.consumes));
consumes = this.operation.consumes[0];
}
}
if (this.opts.responseContentType) {
accepts = this.opts.responseContentType;
} else {
accepts = "application/json";
}
if (accepts && this.operation.produces) {
if (this.operation.produces.indexOf(accepts) === -1) {
log("server can't produce " + accepts);
accepts = this.operation.produces[0];
}
}
if ((consumes && body !== "") || (consumes === "application/x-www-form-urlencoded"))
headers["Content-Type"] = consumes;
if (accepts)
headers["Accept"] = accepts;
return headers;
}
SwaggerRequest.prototype.asCurl = function() {
var results = [];
if(this.headers) {
@@ -1427,11 +1480,36 @@ ShredHttpClient.prototype.execute = function(obj) {
return out;
};
// Transform an error into a usable response-like object
var transformError = function(error) {
var out = {
// Default to a status of 0 - The client will treat this as a generic permissions sort of error
status: 0,
data: error.message || error
};
if(error.code) {
out.obj = error;
if(error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED' ) {
// We can tell the client that this should be treated as a missing resource and not as a permissions thing
out.status = 404;
}
}
return out;
};
res = {
error: function(response) {
if (obj)
return cb.error(transform(response));
},
// Catch the Shred error raised when the request errors as it is made (i.e. No Response is coming)
request_error: function(err) {
if(obj)
return cb.error(transformError(err));
},
redirect: function(response) {
if (obj)
return cb.redirect(transform(response));
@@ -1499,10 +1577,11 @@ SwaggerAuthorizations.prototype.apply = function(obj, authorizations) {
/**
* ApiKeyAuthorization allows a query param or header to be injected
*/
var ApiKeyAuthorization = function(name, value, type) {
var ApiKeyAuthorization = function(name, value, type, delimiter) {
this.name = name;
this.value = value;
this.type = type;
this.delimiter = delimiter;
};
ApiKeyAuthorization.prototype.apply = function(obj, authorizations) {
@@ -1513,7 +1592,12 @@ ApiKeyAuthorization.prototype.apply = function(obj, authorizations) {
obj.url = obj.url + "?" + this.name + "=" + this.value;
return true;
} else if (this.type === "header") {
obj.headers[this.name] = this.value;
if(typeof obj.headers[this.name] !== 'undefined') {
if(typeof this.delimiter !== 'undefined')
obj.headers[this.name] = obj.headers[this.name] + this.delimiter + this.value;
}
else
obj.headers[this.name] = this.value;
return true;
}
};
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "2.0.18",
"version": "2.0.24",
"description": "Swagger UI is a dependency-free collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API",
"scripts": {
"build": "PATH=$PATH:./node_modules/.bin cake dist",
@@ -18,8 +18,8 @@
"license": "Apache",
"readmeFilename": "README.md",
"dependencies": {
"coffee-script": "~1.5.0",
"swagger-client": "2.0.29",
"coffee-script": "~1.6.3",
"swagger-client": "2.0.36",
"handlebars": "~1.0.10",
"less": "~1.4.2"
}
+1 -1
View File
@@ -55,7 +55,7 @@ class SwaggerUi extends Backbone.Router
# so it gets called when SwaggerApi completes loading
render:() ->
@showMessage('Finished Loading Resource Information. Rendering Swagger UI...')
@mainView = new MainView({model: @api, el: $('#' + @dom_id)}).render()
@mainView = new MainView({model: @api, el: $('#' + @dom_id), swaggerOptions: @options}).render()
@showMessage()
switch @options.docExpansion
when "full" then Docs.expandOperationsForResource('')
+15 -3
View File
@@ -1,6 +1,18 @@
class MainView extends Backbone.View
initialize: ->
sorters = {
'alpha' : (a,b) -> return a.path.localeCompare(b.path),
'method' : (a,b) -> return a.method.localeCompare(b.method),
}
initialize: (opts={}) ->
if opts.swaggerOptions.sorter
sorterName = opts.swaggerOptions.sorter
sorter = sorters[sorterName]
for route in @model.apisArray
route.operationsArray.sort sorter
if (sorterName == "alpha") # sort top level paths if alpha
@model.apisArray.sort sorter
render: ->
# Render the outer container for resources
$(@el).html(Handlebars.templates.main(@model))
@@ -21,8 +33,8 @@ class MainView extends Backbone.View
addResource: (resource) ->
# Render a resource and add it to resources li
resourceView = new ResourceView({model: resource, tagName: 'li', id: 'resource_' + resource.id, className: 'resource'})
resourceView = new ResourceView({model: resource, tagName: 'li', id: 'resource_' + resource.id, className: 'resource', swaggerOptions: @options.swaggerOptions})
$('#resources').append resourceView.render().el
clear: ->
$(@el).html ''
$(@el).html ''
+13 -10
View File
@@ -14,8 +14,8 @@ class OperationView extends Backbone.View
mouseEnter: (e) ->
elem = $(e.currentTarget.parentNode).find('#api_information_panel')
x = event.pageX
y = event.pageY
x = e.pageX
y = e.pageY
scX = $(window).scrollLeft()
scY = $(window).scrollTop()
scMaxX = scX + $(window).width()
@@ -162,7 +162,7 @@ class OperationView extends Backbone.View
# add params
for param in @model.parameters
if param.paramType is 'form'
if map[param.name] != undefined
if param.type.toLowerCase() isnt 'file' and map[param.name] != undefined
bodyParam.append(param.name, map[param.name])
# headers in operation
@@ -179,8 +179,6 @@ class OperationView extends Backbone.View
bodyParam.append($(el).attr('name'), el.files[0])
params += 1
log(bodyParam)
@invocationUrl =
if @model.supportHeaderParams()
headerParams = @model.getHeaderParams(map)
@@ -188,8 +186,9 @@ class OperationView extends Backbone.View
else
@model.urlify(map, true)
$(".request_url", $(@el)).html "<pre>" + @invocationUrl + "</pre>"
$(".request_url", $(@el)).html("<pre></pre>")
$(".request_url pre", $(@el)).text(@invocationUrl);
obj =
type: @model.method
url: @invocationUrl
@@ -358,14 +357,18 @@ class OperationView extends Backbone.View
pre = $('<pre class="json" />').append(code)
response_body = pre
$(".request_url", $(@el)).html "<pre>" + url + "</pre>"
$(".request_url", $(@el)).html("<pre></pre>")
$(".request_url pre", $(@el)).text(url);
$(".response_code", $(@el)).html "<pre>" + response.status + "</pre>"
$(".response_body", $(@el)).html response_body
$(".response_headers", $(@el)).html "<pre>" + JSON.stringify(response.headers, null, " ").replace(/\n/g, "<br>") + "</pre>"
$(".response_headers", $(@el)).html "<pre>" + _.escape(JSON.stringify(response.headers, null, " ")).replace(/\n/g, "<br>") + "</pre>"
$(".response", $(@el)).slideDown()
$(".response_hider", $(@el)).show()
$(".response_throbber", $(@el)).hide()
hljs.highlightBlock($('.response_body', $(@el))[0])
response_body_el = $('.response_body', $(@el))[0]
# only highlight the response if response is less than threshold, default state is highlight response
opts = @options.swaggerOptions
if opts.highlightSizeThreshold && response.data.length > opts.highlightSizeThreshold then response_body_el else hljs.highlightBlock(response_body_el)
toggleOperationContent: ->
elem = $('#' + Docs.escapeResourceName(@model.parentId) + "_" + @model.nickname + "_content")
+16 -3
View File
@@ -20,14 +20,27 @@ class ResourceView extends Backbone.View
operation.nickname = id
operation.parentId = @model.id
@addOperation operation
@
$('.toggleEndpointList', @el).click(this.callDocs.bind(this, 'toggleEndpointListForResource'))
$('.collapseResource', @el).click(this.callDocs.bind(this, 'collapseOperationsForResource'))
$('.expandResource', @el).click(this.callDocs.bind(this, 'expandOperationsForResoruce'))
return @
addOperation: (operation) ->
operation.number = @number
# Render an operation and add it to operations li
operationView = new OperationView({model: operation, tagName: 'li', className: 'endpoint'})
operationView = new OperationView({model: operation, tagName: 'li', className: 'endpoint', swaggerOptions: @options.swaggerOptions})
$('.endpoints', $(@el)).append operationView.render().el
@number++
@number++
#
# Generic Event handler (`Docs` is global)
#
callDocs: (fnName, e) ->
e.preventDefault()
Docs[fnName](e.currentTarget.getAttribute('data-id'))
+8 -5
View File
@@ -743,17 +743,20 @@
display: inline-block;
font-size: 0.9em;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header img {
display: block;
clear: none;
float: right;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit {
display: block;
clear: none;
float: left;
padding: 6px 8px;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber {
background-image: url('../images/throbber.gif');
width: 128px;
height: 16px;
display: block;
clear: none;
float: right;
}
.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error {
outline: 2px solid black;
outline-color: #cc0000;
+2 -1
View File
@@ -47,7 +47,8 @@
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none"
docExpansion: "none",
sorter : "alpha"
});
$('#input_apiKey').change(function() {
+1 -1
View File
@@ -66,7 +66,7 @@ log = function(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
console.log( Array.prototype.slice.call(arguments)[0] );
}
};
+8 -5
View File
@@ -671,17 +671,20 @@
display: inline-block;
font-size: 0.9em;
}
img {
display: block;
clear: none;
float: right;
}
input.submit {
display: block;
clear: none;
float: left;
padding: 6px 8px;
}
span.response_throbber {
background-image: url('../images/throbber.gif');
width: 128px;
height: 16px;
display: block;
clear: none;
float: right;
}
}
form {
input[type='text'].error {
+1 -1
View File
@@ -83,7 +83,7 @@
<div class='sandbox_header'>
<input class='submit' name='commit' type='button' value='Try it out!' />
<a href='#' class='response_hider' style='display:none'>Hide Response</a>
<img alt='Throbber' class='response_throbber' src='images/throbber.gif' style='display:none' />
<span class='response_throbber' style='display:none'></span>
</div>
{{/if}}
</form>
+8 -3
View File
@@ -15,10 +15,15 @@
{{/if}}
{{/if}}
{{else}}
{{#if defaultValue}}
<input class='parameter' minlength='0' name='{{name}}' placeholder='' type='text' value='{{defaultValue}}'/>
{{#if isFile}}
<input type="file" name='{{name}}'/>
<div class="parameter-content-type" />
{{else}}
<input class='parameter' minlength='0' name='{{name}}' placeholder='' type='text' value=''/>
{{#if defaultValue}}
<input class='parameter' minlength='0' name='{{name}}' placeholder='' type='text' value='{{defaultValue}}'/>
{{else}}
<input class='parameter' minlength='0' name='{{name}}' placeholder='' type='text' value=''/>
{{/if}}
{{/if}}
{{/if}}
+4 -5
View File
@@ -1,19 +1,18 @@
<div class='heading'>
<h2>
<a href='#!/{{id}}' onclick="Docs.toggleEndpointListForResource('{{id}}');">{{name}}</a> {{#description}} : {{/description}}{{{description}}}
<a href='#!/{{id}}' class="toggleEndpointList" data-id="{{id}}">{{name}}</a> {{#description}} : {{/description}}{{{description}}}
</h2>
<ul class='options'>
<li>
<a href='#!/{{id}}' id='endpointListTogger_{{id}}'
onclick="Docs.toggleEndpointListForResource('{{id}}');">Show/Hide</a>
<a href='#!/{{id}}' id='endpointListTogger_{{id}}' class="toggleEndpointList" data-id="{{id}}">Show/Hide</a>
</li>
<li>
<a href='#' onclick="Docs.collapseOperationsForResource('{{id}}'); return false;">
<a href='#' class="collapseResource" data-id="{{id}}">
List Operations
</a>
</li>
<li>
<a href='#' onclick="Docs.expandOperationsForResource('{{id}}'); return false;">
<a href='#' class="expandResource" data-id={{id}}>
Expand Operations
</a>
</li>