api.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. var responseDisplay = 'data'
  2. var coreapi = window.coreapi
  3. var schema = window.schema
  4. function normalizeKeys (arr) {
  5. var _normarr = [];
  6. for (var i = 0; i < arr.length; i++) {
  7. _normarr = _normarr.concat(arr[i].split(' > '));
  8. }
  9. return _normarr;
  10. }
  11. function normalizeHTTPHeader (str) {
  12. // Capitalize HTTP headers for display.
  13. return (str.charAt(0).toUpperCase() + str.substring(1))
  14. .replace(/-(.)/g, function ($1) {
  15. return $1.toUpperCase()
  16. })
  17. .replace(/(Www)/g, function ($1) {
  18. return 'WWW'
  19. })
  20. .replace(/(Xss)/g, function ($1) {
  21. return 'XSS'
  22. })
  23. .replace(/(Md5)/g, function ($1) {
  24. return 'MD5'
  25. })
  26. }
  27. function formEntries (form) {
  28. // Polyfill for new FormData(form).entries()
  29. var formData = new FormData(form)
  30. if (formData.entries !== undefined) {
  31. return Array.from(formData.entries())
  32. }
  33. var entries = []
  34. for (var i = 0; i < form.elements.length; i++) {
  35. var element = form.elements[i]
  36. if (!element.name) {
  37. continue
  38. }
  39. if (element.type === 'file') {
  40. for (var j = 0; j < element.files.length; j++) {
  41. entries.push([element.name, element.files[j]])
  42. }
  43. } else if (element.type === 'select-multiple' || element.type === 'select-one') {
  44. for (var j = 0; j < element.selectedOptions.length; j++) {
  45. entries.push([element.name, element.selectedOptions[j].value])
  46. }
  47. } else if (element.type === 'checkbox') {
  48. if (element.checked) {
  49. entries.push([element.name, element.value])
  50. }
  51. } else {
  52. entries.push([element.name, element.value])
  53. }
  54. }
  55. return entries
  56. }
  57. $(function () {
  58. var $selectedAuthentication = $('#selected-authentication')
  59. var $authControl = $('#auth-control')
  60. var $authTokenModal = $('#auth_token_modal')
  61. var $authBasicModal = $('#auth_basic_modal')
  62. var $authSessionModal = $('#auth_session_modal')
  63. // Language Control
  64. $('#language-control li').click(function (event) {
  65. event.preventDefault()
  66. var $languageMenuItem = $(this).find('a')
  67. var $languageControls = $(this).closest('ul').find('li')
  68. var $languageControlLinks = $languageControls.find('a')
  69. var language = $languageMenuItem.data('language')
  70. $languageControlLinks.not('[data-language="' + language + '"]').parent().removeClass('active')
  71. $languageControlLinks.filter('[data-language="' + language + '"]').parent().addClass('active')
  72. $('#selected-language').text(language)
  73. var $codeBlocks = $('pre.highlight')
  74. $codeBlocks.not('[data-language="' + language + '"]').addClass('hide')
  75. $codeBlocks.filter('[data-language="' + language + '"]').removeClass('hide')
  76. })
  77. // API Explorer
  78. $('form.api-interaction').submit(function (event) {
  79. event.preventDefault()
  80. var $form = $(this).closest('form')
  81. var $requestMethod = $form.find('.request-method')
  82. var $requestUrl = $form.find('.request-url')
  83. var $toggleView = $form.closest('.modal-content').find('.toggle-view')
  84. var $responseStatusCode = $form.find('.response-status-code')
  85. var $meta = $form.find('.meta')
  86. var $responseRawResponse = $form.find('.response-raw-response')
  87. var $requestAwaiting = $form.find('.request-awaiting')
  88. var $responseRaw = $form.find('.response-raw')
  89. var $responseData = $form.find('.response-data')
  90. var key = normalizeKeys($form.data('key'))
  91. var params = {}
  92. var entries = formEntries($form.get()[0])
  93. for (var i = 0; i < entries.length; i++) {
  94. var entry = entries[i]
  95. var paramKey = entry[0]
  96. var paramValue = entry[1]
  97. var $elem = $form.find('[name="' + paramKey + '"]')
  98. var dataType = $elem.data('type') || 'string'
  99. if (dataType === 'integer' && paramValue) {
  100. var value = parseInt(paramValue)
  101. if (!isNaN(value)) {
  102. params[paramKey] = value
  103. }
  104. } else if (dataType === 'number' && paramValue) {
  105. var value = parseFloat(paramValue)
  106. if (!isNaN(value)) {
  107. params[paramKey] = value
  108. }
  109. } else if (dataType === 'boolean' && paramValue) {
  110. var value = {
  111. 'true': true,
  112. 'false': false
  113. }[paramValue.toLowerCase()]
  114. if (value !== undefined) {
  115. params[paramKey] = value
  116. }
  117. } else if ((dataType === 'array' && paramValue) || (dataType === 'object' && paramValue)) {
  118. try {
  119. params[paramKey] = JSON.parse(paramValue)
  120. } catch (err) {
  121. // Ignore malformed JSON
  122. }
  123. } else if (dataType === 'string' && paramValue) {
  124. params[paramKey] = paramValue
  125. }
  126. }
  127. $form.find(':checkbox').each(function (index) {
  128. // Handle unselected checkboxes
  129. var name = $(this).attr('name')
  130. if (!params.hasOwnProperty(name)) {
  131. params[name] = false
  132. }
  133. })
  134. function requestCallback (request) {
  135. // Fill in the "GET /foo/" display.
  136. var parser = document.createElement('a')
  137. parser.href = request.url
  138. var method = request.options.method
  139. var path = parser.pathname + parser.hash + parser.search
  140. $requestMethod.text(method)
  141. $requestUrl.text(path)
  142. }
  143. function responseCallback (response, responseText) {
  144. // Display the 'Data'/'Raw' control.
  145. $toggleView.removeClass('hide')
  146. // Fill in the "200 OK" display.
  147. $responseStatusCode.removeClass('label-success').removeClass('label-danger')
  148. if (response.ok) {
  149. $responseStatusCode.addClass('label-success')
  150. } else {
  151. $responseStatusCode.addClass('label-danger')
  152. }
  153. $responseStatusCode.text(response.status)
  154. $meta.removeClass('hide')
  155. // Fill in the Raw HTTP response display.
  156. var panelText = 'HTTP/1.1 ' + response.status + ' ' + response.statusText + '\n'
  157. response.headers.forEach(function (header, key) {
  158. panelText += normalizeHTTPHeader(key) + ': ' + header + '\n'
  159. })
  160. if (responseText) {
  161. panelText += '\n' + responseText
  162. }
  163. $responseRawResponse.text(panelText)
  164. }
  165. // Instantiate a client to make the outgoing request.
  166. var options = {
  167. requestCallback: requestCallback,
  168. responseCallback: responseCallback
  169. }
  170. // Setup authentication options.
  171. if (window.auth && window.auth.type === 'token') {
  172. // Header authentication
  173. options.auth = new coreapi.auth.TokenAuthentication({
  174. scheme: window.auth.scheme,
  175. token: window.auth.token
  176. })
  177. } else if (window.auth && window.auth.type === 'basic') {
  178. // Basic authentication
  179. options.auth = new coreapi.auth.BasicAuthentication({
  180. username: window.auth.username,
  181. password: window.auth.password
  182. })
  183. } else if (window.auth && window.auth.type === 'session') {
  184. // Session authentication
  185. options.auth = new coreapi.auth.SessionAuthentication({
  186. csrfCookieName: 'csrftoken',
  187. csrfHeaderName: 'X-CSRFToken'
  188. })
  189. }
  190. var client = new coreapi.Client(options)
  191. client.action(schema, key, params).then(function (data) {
  192. var response = JSON.stringify(data, null, 2)
  193. $requestAwaiting.addClass('hide')
  194. $responseRaw.addClass('hide')
  195. $responseData.addClass('hide').text('').jsonView(response)
  196. if (responseDisplay === 'data') {
  197. $responseData.removeClass('hide')
  198. } else {
  199. $responseRaw.removeClass('hide')
  200. }
  201. }).catch(function (error) {
  202. var response = JSON.stringify(error.content, null, 2)
  203. $requestAwaiting.addClass('hide')
  204. $responseRaw.addClass('hide')
  205. $responseData.addClass('hide').text('').jsonView(response)
  206. if (responseDisplay === 'data') {
  207. $responseData.removeClass('hide')
  208. } else {
  209. $responseRaw.removeClass('hide')
  210. }
  211. })
  212. })
  213. // 'Data'/'Raw' control
  214. $('.toggle-view button').click(function () {
  215. var $modalContent = $(this).closest('.modal-content')
  216. var $modalResponseRaw = $modalContent.find('.response-raw')
  217. var $modalResponseData = $modalContent.find('.response-data')
  218. responseDisplay = $(this).data('display-toggle')
  219. $(this).removeClass('btn-default').addClass('btn-info').siblings().removeClass('btn-info')
  220. if (responseDisplay === 'raw') {
  221. $modalResponseRaw.removeClass('hide')
  222. $modalResponseData.addClass('hide')
  223. } else {
  224. $modalResponseData.removeClass('hide')
  225. $modalResponseRaw.addClass('hide')
  226. }
  227. })
  228. // Authentication: none
  229. $authControl.find("[data-auth='none']").click(function (event) {
  230. event.preventDefault()
  231. window.auth = null
  232. $selectedAuthentication.text('none')
  233. $authControl.find("[data-auth]").closest('li').removeClass('active')
  234. $authControl.find("[data-auth='none']").closest('li').addClass('active')
  235. })
  236. // Authentication: token
  237. $('form.authentication-token-form').submit(function (event) {
  238. event.preventDefault()
  239. var $form = $(this).closest('form')
  240. var scheme = $form.find('input#scheme').val()
  241. var token = $form.find('input#token').val()
  242. window.auth = {
  243. 'type': 'token',
  244. 'scheme': scheme,
  245. 'token': token
  246. }
  247. $selectedAuthentication.text('token')
  248. $authControl.find("[data-auth]").closest('li').removeClass('active')
  249. $authControl.find("[data-auth='token']").closest('li').addClass('active')
  250. $authTokenModal.modal('hide')
  251. })
  252. // Authentication: basic
  253. $('form.authentication-basic-form').submit(function (event) {
  254. event.preventDefault()
  255. var $form = $(this).closest('form')
  256. var username = $form.find('input#username').val()
  257. var password = $form.find('input#password').val()
  258. window.auth = {
  259. 'type': 'basic',
  260. 'username': username,
  261. 'password': password
  262. }
  263. $selectedAuthentication.text('basic')
  264. $authControl.find("[data-auth]").closest('li').removeClass('active')
  265. $authControl.find("[data-auth='basic']").closest('li').addClass('active')
  266. $authBasicModal.modal('hide')
  267. })
  268. // Authentication: session
  269. $('form.authentication-session-form').submit(function (event) {
  270. event.preventDefault()
  271. window.auth = {
  272. 'type': 'session'
  273. }
  274. $selectedAuthentication.text('session')
  275. $authControl.find("[data-auth]").closest('li').removeClass('active')
  276. $authControl.find("[data-auth='session']").closest('li').addClass('active')
  277. $authSessionModal.modal('hide')
  278. })
  279. })