PageRenderTime 106ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/WCFWebApi/src/Microsoft.ApplicationServer.Http/Microsoft/ApplicationServer/Http/Test/testscript.js

#
JavaScript | 1090 lines | 882 code | 169 blank | 39 comment | 141 complexity | 6a66f0dea8071e77e809dcf85ee3813f MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. var contentTypePatterns = { 'xml': /(text|application)\s*\/\s*xml/i, 'json': /(text|application)\s*\/\s*json/i, 'raw': /(text)\s*\/\s*plain/i };
  2. var defaultContentTypes = { 'xml': 'text/xml', 'json': 'application/json', 'raw': 'text/plain' };
  3. var httpMethodsNoBody = ['GET', 'HEAD', 'MOVE', 'TRACE', 'DELETE', 'CONNECT', 'MKCOL', 'COPY', 'UNLOCK', 'OPTIONS'];
  4. var formatList = ['Xml', 'Json', 'Raw'];
  5. var server = {};
  6. var currentResource = null;
  7. var invokeHistory = {'records':[], 'maxWidth':0};
  8. var autoCompletesResetList = [];
  9. var currentFormat = 0;
  10. var formatTabs = null;
  11. var contentLengthRegex = /^\s*Content\-Length\s*(\:|$)/i;
  12. var contentTypeRegex = /^\s*Content\-Type\s*(\:[^\;]*|$)/i;
  13. var defaultHttpMethod = 'GET';
  14. (function ($) {
  15. $.tree = function (uri) {
  16. this.uri = uri;
  17. this.indexInServer = -1;
  18. this.subtree = new Array();
  19. };
  20. $.extend($.tree.prototype, {
  21. show: function (level) {
  22. var content = ["<div>"];
  23. for (var i = 0; i < level * 4; i++) {
  24. content.push("&nbsp;");
  25. }
  26. if (this.indexInServer >= 0) {
  27. content.push("<a class='resourceTreeNode' href='javascript:void(0);' indexInServer='");
  28. content.push(this.indexInServer);
  29. content.push("' title='");
  30. content.push(server.Resources[this.indexInServer].Uri);
  31. content.push("'>");
  32. content.push(this.uri);
  33. content.push("</a>");
  34. }
  35. else {
  36. content.push(this.uri);
  37. }
  38. content.push("</div>");
  39. for (var i = 0; i < this.subtree.length; i++) {
  40. content.push(this.subtree[i].show(level + 1));
  41. }
  42. return content.join('');
  43. },
  44. add: function (uri, indexInServer) {
  45. if (uri.length == 0) {
  46. this.indexInServer = indexInServer;
  47. return;
  48. }
  49. else {
  50. var j = uri.indexOf("/");
  51. if (j < 0) {
  52. j = uri.length;
  53. }
  54. var sub_uri = uri.substring(0, j);
  55. var sub_tree_id = -1;
  56. for (var i = 0; i < this.subtree.length; i++) {
  57. if (this.subtree[i].uri == sub_uri) {
  58. sub_tree_id = i;
  59. break;
  60. }
  61. }
  62. if (sub_tree_id < 0) {
  63. this.subtree.push(new $.tree(sub_uri));
  64. sub_tree_id = this.subtree.length - 1;
  65. }
  66. this.subtree[sub_tree_id].add(uri.substring(j + 1), indexInServer);
  67. }
  68. }
  69. });
  70. $.resourceTree = function () {
  71. };
  72. $.extend($.resourceTree.prototype, {
  73. stretchItemsWidthToSame: function(controls){
  74. var maxWidth = 0;
  75. var width = 0;
  76. for(var i=0; i<controls.length; i++)
  77. {
  78. width = $(controls[i]).width();
  79. maxWidth = (maxWidth > width)? maxWidth: width;
  80. }
  81. controls.width(maxWidth);
  82. },
  83. getHostNormalizedUri: function(uri){
  84. var i = uri.indexOf('//');
  85. if(i < 0){
  86. return uri;
  87. }
  88. i += 2;
  89. var j = uri.indexOf('/', i);
  90. if(j < 0){
  91. return uri;
  92. }
  93. return uri.slice(0, i) + window.location.host + uri.slice(j);
  94. },
  95. build: function (placeHolder, callback) {
  96. var THIS = this;
  97. proxy.getResource(function (data) {
  98. server = data;
  99. if(server.Resources.length > 0){
  100. var baseAddress = THIS.getHostNormalizedUri(server.Resources[0].BaseAddress);
  101. var resourcesTree = new $.tree(baseAddress);
  102. var length = (baseAddress.charAt(baseAddress.length-1) == '/')? baseAddress.length : baseAddress.length + 1;
  103. for (i = 0; i < server.Resources.length; i++) {
  104. resourcesTree.add(THIS.getHostNormalizedUri(server.Resources[i].Uri).substring(length), i);
  105. server.Resources[i].operationMap = {};
  106. for(j=0; j<server.Resources[i].Operations.length; j++){
  107. server.Resources[i].operationMap[server.Resources[i].Operations[j].HttpMethod] = server.Resources[i].Operations[j].Name;
  108. }
  109. }
  110. var content = resourcesTree.show(0);
  111. placeHolder.html(content);
  112. THIS.stretchItemsWidthToSame(placeHolder.contents());
  113. $(".resourceTreeNode").click(callback);
  114. $("#resources").show();
  115. if(server.HelpEnabled){
  116. $("#sampleButton").show();
  117. }
  118. else{
  119. $("#sampleButton").hide();
  120. }
  121. }
  122. },
  123. function(){
  124. $("#resources").hide();
  125. });
  126. }
  127. });
  128. })(jQuery);
  129. function lengthInUtf8Bytes(str) {
  130. var m = encodeURIComponent(str).match(/\%[89ABab]/g);
  131. return str.length + (m ? m.length : 0);
  132. }
  133. function setContentLength(str) {
  134. var requestHeaderTextArea = $("#requestHeader");
  135. var headers = requestHeaderTextArea.val().split('\n');
  136. var contentLength = "Content-Length:" + lengthInUtf8Bytes(str);
  137. var contentLengthExists = false;
  138. for (var i = 0; i < headers.length; i++) {
  139. if (headers[i].match(contentLengthRegex)) {
  140. headers[i] = contentLength;
  141. contentLengthExists = true;
  142. }
  143. }
  144. headers = headers.join('\n');
  145. if (!contentLengthExists) {
  146. headers = headers.replace(/\s*$/, "");
  147. headers = headers + "\n" + contentLength;
  148. }
  149. requestHeaderTextArea.val(headers);
  150. }
  151. function setContentType(format) {
  152. if (format in defaultContentTypes) {
  153. var contentType = "Content-Type:" + defaultContentTypes[format];
  154. var requestHeaderTextArea = $("#requestHeader");
  155. var headers = requestHeaderTextArea.val().split('\n');
  156. var contentTypeExists = false;
  157. for (var i = 0; i < headers.length; i++) {
  158. var match = headers[i].match(contentTypeRegex)
  159. if (match) {
  160. contentTypeExists = true;
  161. if(match[0].match(contentTypePatterns[format]))
  162. {
  163. return;
  164. }
  165. headers[i] = headers[i].replace(contentTypeRegex, contentType);
  166. }
  167. }
  168. headers = headers.join('\n');
  169. if(!contentTypeExists)
  170. {
  171. headers = headers.replace(/\s*$/, "");
  172. headers = headers + "\n" + contentType;
  173. }
  174. requestHeaderTextArea.val(headers);
  175. }
  176. }
  177. function selectVariableInUriTextbox(textbox) {
  178. var val = textbox.val();
  179. var selectionEnd = textbox.getSelection().end;
  180. var s, e;
  181. s = val.lastIndexOf("{", selectionEnd);
  182. if (s < 0) {
  183. return;
  184. }
  185. e = val.indexOf("}", s);
  186. e = (e < 0) ? val.length : e + 1;
  187. textbox.setSelection({
  188. start: s,
  189. end: e
  190. });
  191. }
  192. function enableIntellisense(control, postTextCallback) {
  193. var autoComplete = control.enableAutoComplete();
  194. control.keydown(function (event) {
  195. return autoComplete.onKeyDown(event);
  196. });
  197. control.keyup(function (event) {
  198. return autoComplete.onKeyUp(event, function (fullText, curPos, callback) {
  199. return postTextCallback(fullText, curPos, callback);
  200. });
  201. });
  202. control.click(function (event) {
  203. return autoComplete.onMouseClick(event);
  204. });
  205. control.focus(function (event) {
  206. return autoComplete.onFocus(event);
  207. });
  208. control.blur(function (event) {
  209. return autoComplete.onBlur(event);
  210. });
  211. return autoComplete;
  212. }
  213. function enableUriIntellisense(uri, uriTemplate, httpMethod) {
  214. var autoComplete = enableIntellisense(uri, function (fullText, curPos, callback) {
  215. return proxy.postUriText(uriTemplate.val(), httpMethod.val(), curPos, fullText, callback);
  216. });
  217. autoComplete.regexContextId(/^.*[\/\?\=\&\#]/);
  218. return autoComplete;
  219. }
  220. function enableHeaderIntellisense(header) {
  221. var autoComplete = enableIntellisense(header, function (fullText, curPos, callback) {
  222. return proxy.postHeaderText(curPos, fullText, callback);
  223. });
  224. autoComplete.regexContextId(/^(.*\n)*([^\:]+\:)?/);
  225. return autoComplete;
  226. }
  227. function enableRequestBodyXmlIntellisense(body, uriTemplate, httpMethod) {
  228. var autoComplete = enableIntellisense(body, function (fullText, curPos, callback) {
  229. return proxy.postBodyText(uriTemplate.val(), httpMethod.val(), "xml", curPos, fullText, callback);
  230. });
  231. // (\s|\S) is stronger than . because the former also matches \n
  232. autoComplete.regexContextId(/^(\s|\S)*(\<\/|\<([^\>]*(\s|\"))?|\>)/);
  233. return autoComplete;
  234. }
  235. function enableRequestBodyJsonIntellisense(body, uriTemplate, httpMethod) {
  236. var autoComplete = enableIntellisense(body, function (fullText, curPos, callback) {
  237. return proxy.postBodyText(uriTemplate.val(), httpMethod.val(), "json", curPos, fullText, callback);
  238. });
  239. autoComplete.regexContextId(/^(\s|\S)*[\{\}\"\:\[\]\,]/);
  240. return autoComplete;
  241. }
  242. function enableHttpMethodIntellisense(httpMethod) {
  243. var autoComplete = enableIntellisense(httpMethod, function (fullText, curPos, callback) {
  244. return getHttpMethodAutoCompleteList(curPos, fullText, callback);
  245. });
  246. autoComplete.filteringOn1stChar(true);
  247. autoComplete.comboboxMode(true);
  248. return autoComplete;
  249. }
  250. function getHttpMethodAutoCompleteList(curPos, fullText, callback) {
  251. var data = {
  252. autoCompleteList: ["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH", "TRACE", "OPTIONS"]
  253. };
  254. if (!currentResource) {
  255. // no resource is selected yet
  256. // assume every method is applicable
  257. return callback(data);
  258. }
  259. var map = {};
  260. for (var j = 0; j < currentResource.Operations.length; j++) {
  261. map[currentResource.Operations[j].HttpMethod] = true;
  262. }
  263. // need to mark not applicable methods
  264. for (var i = 0; i < data.autoCompleteList.length; i++) {
  265. var method = data.autoCompleteList[i];
  266. var applicable = map[method];
  267. if (!applicable) {
  268. data.autoCompleteList[i] = method + "\n" + method + "\n\n\nfalse";
  269. }
  270. else{
  271. delete map[method];
  272. }
  273. }
  274. for (var key in map){
  275. data.autoCompleteList.push(key);
  276. }
  277. return callback(data);
  278. }
  279. function clearLastRequest() {
  280. $("#httpMethodTextBox").val("");
  281. $("#uri").val("");
  282. $("#requestHeader").val("Accept:*/*");
  283. for(var i=0; i<formatList.length; i++){
  284. $("#requestBody"+formatList[i]).val("");
  285. }
  286. clearAllValidationResult();
  287. clearAutoCompleteResetListContext(0); // also reset http-method textbox
  288. }
  289. function clearLastResponse() {
  290. $("#statusBar").text("");
  291. $("#status").text("");
  292. $("#responseHeader").val("");
  293. $("#responseBody").val("");
  294. }
  295. function clearLastSession() {
  296. clearLastResponse();
  297. clearLastRequest();
  298. }
  299. function initResourceTree() {
  300. var rt = new $.resourceTree();
  301. rt.build(
  302. $("#resourceTree"),
  303. function (event) {
  304. clearLastSession();
  305. var target = $(event.target);
  306. var i = target.attr("indexInServer") - 0;
  307. currentResource = server.Resources[i];
  308. // host name in the url could be wrong, e.g. in Azure case, service returns urls with service's internal host name
  309. // fixed here with the real host name in order to invoke the service, e.g. in Azure case, must use the external host name of the service
  310. $("#uri").val(rt.getHostNormalizedUri(currentResource.Uri));
  311. // the url template here is used to match web api operation on service side
  312. // so keep the host name got from service side
  313. $("#uriTemplate").val(currentResource.Uri);
  314. // make 'GET' as the default httpmethod as long as the selected service supports 'GET'.
  315. if (defaultHttpMethod in currentResource.operationMap) {
  316. $("#httpMethodTextBox").val(defaultHttpMethod);
  317. }
  318. else {
  319. $("#httpMethodTextBox").val((currentResource.Operations[0].HttpMethod));
  320. }
  321. $("#httpMethodTextBox").change();
  322. enableFormattingButton(currentFormat);
  323. $(".resourceSelected").removeClass("resourceSelected");
  324. target.parent().addClass("resourceSelected");
  325. $("#uri").focus();
  326. return false;
  327. });
  328. }
  329. function dateToString(date) {
  330. var h = date.getHours();
  331. var m = date.getMinutes();
  332. var s = date.getSeconds();
  333. var ms = date.getMilliseconds();
  334. return "time: " + Math.floor(h / 10) + h % 10 + "." + Math.floor(m / 10) + m % 10 + "." + Math.floor(s / 10) + s % 10+ "." + Math.floor(ms / 100) + Math.floor(ms / 10) + ms % 10;
  335. }
  336. (function ($) {
  337. $.invokeRecord = function () {
  338. this._resource = null,
  339. this._httpMethod = "";
  340. this._uri = "";
  341. this._format = "";
  342. this._uriTemplate = "";
  343. this._requestHeader = "";
  344. this._requestBody = "";
  345. this._responseHeader = "";
  346. this._responseBody = "";
  347. this._duration = 0;
  348. this._statusCode = 0;
  349. this._statusText = "";
  350. this._requestTimeStr = "";
  351. this._responseTimeStr = "";
  352. };
  353. $.extend($.invokeRecord.prototype,
  354. {
  355. resource: function (value) {
  356. if (value) {
  357. // setter
  358. this._resource = value;
  359. }
  360. else {
  361. // getter
  362. return this._resource;
  363. }
  364. },
  365. httpMethod: function (value) {
  366. if (value) {
  367. // setter
  368. this._httpMethod = value;
  369. }
  370. else {
  371. // getter
  372. return this._httpMethod;
  373. }
  374. },
  375. uri: function (value) {
  376. if (value) {
  377. // setter
  378. this._uri = value;
  379. }
  380. else {
  381. // getter
  382. return this._uri;
  383. }
  384. },
  385. format: function (value) {
  386. if (value != null) {
  387. // setter
  388. this._format = value;
  389. }
  390. else {
  391. // getter
  392. return this._format;
  393. }
  394. },
  395. uriTemplate: function (value) {
  396. if (value) {
  397. // setter
  398. this._uriTemplate = value;
  399. }
  400. else {
  401. // getter
  402. return this._uriTemplate;
  403. }
  404. },
  405. requestHeader: function (value) {
  406. if (value) {
  407. // setter
  408. this._requestHeader = value;
  409. }
  410. else {
  411. // getter
  412. return this._requestHeader;
  413. }
  414. },
  415. requestBody: function (value) {
  416. if (value) {
  417. // setter
  418. this._requestBody = value;
  419. }
  420. else {
  421. // getter
  422. return this._requestBody;
  423. }
  424. },
  425. responseHeader: function (value) {
  426. if (value) {
  427. // setter
  428. this._responseHeader = value;
  429. }
  430. else {
  431. // getter
  432. return this._responseHeader;
  433. }
  434. },
  435. responseBody: function (value) {
  436. if (value) {
  437. // setter
  438. this._responseBody = value;
  439. }
  440. else {
  441. // getter
  442. return this._responseBody;
  443. }
  444. },
  445. duration: function (value) {
  446. if (value || value == 0) {
  447. // setter
  448. this._duration = value;
  449. }
  450. else {
  451. // getter
  452. return this._duration;
  453. }
  454. },
  455. requestTimeStr: function (value) {
  456. if (value) {
  457. // setter
  458. this._requestTimeStr = value;
  459. }
  460. else {
  461. // getter
  462. return this._requestTimeStr;
  463. }
  464. },
  465. responseTimeStr: function (value) {
  466. if (value) {
  467. // setter
  468. this._responseTimeStr = value;
  469. }
  470. else {
  471. // getter
  472. return this._responseTimeStr;
  473. }
  474. },
  475. statusText: function (value) {
  476. if (value) {
  477. // setter
  478. this._statusText = value;
  479. }
  480. else {
  481. // getter
  482. return this._statusText;
  483. }
  484. },
  485. statusCode: function (value) {
  486. if (value || value == 0) {
  487. // setter
  488. this._statusCode = value;
  489. }
  490. else {
  491. // getter
  492. return this._statusCode;
  493. }
  494. },
  495. show: function (index) {
  496. var html = [];
  497. var i = 0;
  498. html.push("<a href='javascript:void(0);' class='historyRecord'");
  499. html.push("' queueIndex='");
  500. html.push(index);
  501. html.push("'>");
  502. html.push("<span class='historyIndex'>");
  503. html.push(index+1);
  504. html.push("</span>");
  505. html.push("<span class='historyDuration'>");
  506. html.push(this._duration);
  507. html.push("s</span>");
  508. html.push("<span class='historyStatus ");
  509. if (this._statusCode < 400) {
  510. html.push("requestStatusOK'>");
  511. }
  512. else {
  513. html.push("requestStatusError'>");
  514. }
  515. html.push(this._statusCode);
  516. html.push("</span>");
  517. html.push("<span class='historyHttpMethod'>");
  518. html.push(this._httpMethod);
  519. html.push("</span>");
  520. html.push("<span>");
  521. if(this._resource && this._uri.indexOf(this._resource.BaseAddress)==0){
  522. html.push((this._resource.BaseAddress.length < this._uri.length) ? this._uri.substring(this._resource.BaseAddress.length) : this._uri);
  523. }
  524. else{
  525. html.push(this._uri);
  526. }
  527. html.push("</span>");
  528. html.push("</a>");
  529. var _a = $(html.join(""));
  530. _a.click(function (event) {
  531. var target = $(this);
  532. var queueIndex = target.attr("queueIndex") - 0;
  533. var ihr = invokeHistory.records[queueIndex];
  534. clearLastSession();
  535. currentResource = ihr.resource();
  536. $("#uri").val(ihr.uri());
  537. $("#uriTemplate").val(ihr.uriTemplate());
  538. $("#requestHeader").val(ihr.requestHeader());
  539. currentFormat = ihr.format();
  540. enableFormattingButton(currentFormat);
  541. $("#requestBody"+formatList[currentFormat]).val(ihr.requestBody());
  542. formatTabs.tabs('select', currentFormat);
  543. $("#httpMethodTextBox").val(ihr.httpMethod());
  544. $("#httpMethodTextBox").change();
  545. $("#responseHeader").val(ihr.responseHeader());
  546. $("#responseBody").val(ihr.responseBody());
  547. $("#statusBar").text("Request " + ihr.requestTimeStr()+" Response " + ihr.responseTimeStr() + " Duration: " + ihr.duration()+"s");
  548. $("#status").text(ihr.statusCode() + "/" + ihr.statusText());
  549. if (ihr.statusCode() < 400) {
  550. $("#status").switchClass("requestStatusError","requestStatusOK", 0);
  551. }
  552. else {
  553. $("#status").switchClass("requestStatusOK","requestStatusError", 0);
  554. }
  555. });
  556. return _a;
  557. }
  558. }
  559. );
  560. })(jQuery);
  561. function enableAllIntellisense() {
  562. autoCompletesResetList.push(enableHttpMethodIntellisense($("#httpMethodTextBox")));
  563. enableHeaderIntellisense($("#requestHeader"));
  564. autoCompletesResetList.push(enableUriIntellisense($("#uri"), $("#uriTemplate"), $("#httpMethodTextBox")));
  565. autoCompletesResetList.push(enableRequestBodyXmlIntellisense($("#requestBodyXml"), $("#uriTemplate"), $("#httpMethodTextBox")));
  566. autoCompletesResetList.push(enableRequestBodyJsonIntellisense($("#requestBodyJson"), $("#uriTemplate"), $("#httpMethodTextBox")));
  567. }
  568. function clearAutoCompleteResetListContext(index)
  569. {
  570. for (var i = index; i < autoCompletesResetList.length; i++) {
  571. autoCompletesResetList[i].clearContext();
  572. }
  573. }
  574. function clearValidationWarning(control){
  575. control.css('visibility', 'hidden');
  576. control.removeAttr('title');
  577. }
  578. function setValidationWarning(control, warningMessage){
  579. control.css('visibility', 'visible');
  580. control.attr('title', warningMessage);
  581. }
  582. function clearAllValidationResult(){
  583. clearValidationWarning($("#httpMethodValidationIndicator"));
  584. clearValidationWarning($("#uriValidationIndicator"));
  585. clearValidationWarning($("#requestBodyValidationIndicator"));
  586. }
  587. function validateHttpMethod(httpMethod){
  588. var indicator = $("#httpMethodValidationIndicator");
  589. clearValidationWarning(indicator);
  590. if(currentResource && !(httpMethod in currentResource.operationMap)) {
  591. setValidationWarning(indicator, "The selected method may not be available, and autocomplete of uri and request body will be affected.");
  592. }
  593. }
  594. function validateUriOrRequestBody(control){
  595. var type = null;
  596. var indicator = null;
  597. if(control.attr('id') == 'uri'){
  598. type = 'uri';
  599. indicator = $("#uriValidationIndicator");
  600. }
  601. else{
  602. type = 'content';
  603. indicator = $("#requestBodyValidationIndicator");
  604. }
  605. clearValidationWarning(indicator);
  606. if(!currentResource){
  607. return;
  608. }
  609. var uriTemplate = $("#uriTemplate").val();
  610. var httpMethod = $("#httpMethodTextBox").val();
  611. var fullText = control.val();
  612. if(uriTemplate.length==0 || httpMethod.length==0 || fullText.length==0){
  613. return;
  614. }
  615. var context = httpMethod + uriTemplate + currentFormat + fullText;
  616. proxy.validateText(
  617. type,
  618. uriTemplate,
  619. httpMethod,
  620. formatList[currentFormat],
  621. fullText,
  622. function(isValid){
  623. var _context = $("#httpMethodTextBox").val() + $("#uriTemplate").val() + currentFormat + control.val();
  624. if(context != _context){
  625. return; //the validation result is out of date.
  626. }
  627. if (!isValid) {
  628. if(type == 'uri') {
  629. setValidationWarning(indicator, "The uri does not match currently selected resource.");
  630. }
  631. else {
  632. setValidationWarning(indicator, "The request body may not be expected given currently selected resource.");
  633. }
  634. }
  635. else {
  636. clearValidationWarning(indicator);
  637. }
  638. },
  639. function(){
  640. clearValidationWarning(indicator);
  641. });
  642. }
  643. function enableFormattingButton(format){
  644. if((format==0 || format==1)){ // xml or json
  645. if($("#formatButton").is('.unclickableLink')){
  646. $("#formatButton").attr('href',"javascript:void(0);");
  647. $("#formatButton").switchClass('unclickableLink', 'clickableLink', 0);
  648. }
  649. }
  650. else {
  651. if($("#formatButton").is('.clickableLink')){
  652. $('#formatButton').removeAttr('href');
  653. $("#formatButton").switchClass('clickableLink', 'unclickableLink', 0);
  654. }
  655. }
  656. }
  657. function updateSampleLink(httpMethod){
  658. if(currentResource && currentFormat!=2 && currentResource.operationMap[httpMethod]){
  659. var href = currentResource.BaseAddress+"/help/operations/" + currentResource.operationMap[httpMethod] + "#request-" + formatList[currentFormat];
  660. $("#sampleButton").attr('href',href);
  661. $("#sampleButton").attr('title',href);
  662. $("#sampleButton").switchClass('unclickableLink', 'clickableLink', 0);
  663. }
  664. else{
  665. $('#sampleButton').removeAttr('href');
  666. $('#sampleButton').removeAttr('title');
  667. $("#sampleButton").switchClass('clickableLink', 'unclickableLink', 0);
  668. }
  669. }
  670. function handleHttpResponse(httpRequest, ir){
  671. $("#status").text(httpRequest.status + "/" + httpRequest.statusText);
  672. if (httpRequest.status < 400) {
  673. $("#status").switchClass("requestStatusError", "requestStatusOK", 0);
  674. }
  675. else {
  676. $("#status").switchClass("requestStatusOK", "requestStatusError", 0);
  677. }
  678. ir.statusCode(httpRequest.status);
  679. ir.statusText(httpRequest.statusText);
  680. $("#responseHeader").val(httpRequest.getAllResponseHeaders());
  681. ir.responseHeader($("#responseHeader").val());
  682. var resTime = new Date();
  683. ir.responseTimeStr(dateToString(resTime));
  684. ir.duration(Math.ceil((resTime - reqTime) / 10) / 100);
  685. var format = null;
  686. var contentType = httpRequest.getResponseHeader("Content-Type");
  687. for (var key in contentTypePatterns) {
  688. if (contentType.match(contentTypePatterns[key])) {
  689. format = key;
  690. break;
  691. }
  692. }
  693. var rawResponse = httpRequest.responseText;
  694. if (format != null) {
  695. proxy.postResContText(
  696. rawResponse,
  697. format,
  698. function (formattedText) {
  699. $("#responseBody").val(formattedText);
  700. },
  701. function () {
  702. $("#responseBody").val(rawResponse);
  703. });
  704. }
  705. else {
  706. $("#responseBody").val(rawResponse);
  707. }
  708. ir.responseBody($("#responseBody").val());
  709. $("#statusBar").text(" Request " + ir.requestTimeStr() + " Response " + ir.responseTimeStr() + " Duration: " + ir.duration() + "s");
  710. invokeHistory.records.push(ir);
  711. var recordShow = ir.show(invokeHistory.records.length - 1);
  712. recordShow.prependTo($("#invokeList"));
  713. if (recordShow.width() > invokeHistory.maxWidth) {
  714. invokeHistory.maxWidth = recordShow.width();
  715. $("#invokeList").contents().width(invokeHistory.maxWidth);
  716. }
  717. else {
  718. recordShow.width(invokeHistory.maxWidth);
  719. }
  720. }
  721. $(document).ready(function () {
  722. initResourceTree();
  723. formatTabs = $("#requestBodyTabs").tabs();
  724. enableAllIntellisense();
  725. invokeHistory = { 'records': [], 'maxWidth': $('#history').width() };
  726. $("#clearHistory").click(function () {
  727. invokeHistory = { 'records': [], 'maxWidth': $('#history').width() };
  728. $("#invokeList").html("");
  729. });
  730. $("#uri").dblclick(function () {
  731. selectVariableInUriTextbox($("#uri"));
  732. });
  733. $("#uri").change(function () {
  734. validateUriOrRequestBody($("#uri"));
  735. });
  736. $("#requestBodyXml").change(function () {
  737. validateUriOrRequestBody($("#requestBodyXml"));
  738. });
  739. $("#requestBodyJson").change(function () {
  740. validateUriOrRequestBody($("#requestBodyJson"));
  741. });
  742. for (var i = 0; i < formatList.length; i++) {
  743. var requestBodyTextArea = $("#requestBody" + formatList[i]);
  744. requestBodyTextArea.change(function () {
  745. setContentLength($("#requestBody" + formatList[currentFormat]).val());
  746. });
  747. }
  748. $("#httpMethodTextBox").change(function () {
  749. var httpMethod = $("#httpMethodTextBox").val();
  750. var needHideRequestBody = false;
  751. for (var i = 0; i < httpMethodsNoBody.length; i++) {
  752. if (httpMethodsNoBody[i] == httpMethod) {
  753. needHideRequestBody = true;
  754. break;
  755. }
  756. }
  757. validateHttpMethod(httpMethod);
  758. validateUriOrRequestBody($("#uri"));
  759. $("#requestHeader").val("Accept:*/*");
  760. if (needHideRequestBody) {
  761. $("#requestBodyDiv").hide();
  762. $("#requestBodyTabs").hide();
  763. $("#responseBody").height(490);
  764. $("#requestBody" + formatList[currentFormat]).val("");
  765. }
  766. else {
  767. $("#requestBodyDiv").show();
  768. $("#requestBodyTabs").show();
  769. $("#responseBody").height(284);
  770. setContentType(formatList[currentFormat].toLowerCase());
  771. var requestBodyTextArea = $("#requestBody" + formatList[currentFormat]);
  772. setContentLength(requestBodyTextArea.val());
  773. validateUriOrRequestBody(requestBodyTextArea);
  774. updateSampleLink(httpMethod);
  775. }
  776. clearAutoCompleteResetListContext(1); // no need to reset http-method textbox
  777. });
  778. $(".formatTabs").click(function (event) {
  779. var targetFormat = formatTabs.tabs('option', 'selected');
  780. if (targetFormat != currentFormat) {
  781. var currentTextbox = $("#requestBody" + formatList[currentFormat]);
  782. var targetTextBox = $("#requestBody" + formatList[targetFormat]);
  783. var httpMethod = $("#httpMethodTextBox").val();
  784. if (currentTextbox.val().length < 1) {
  785. currentFormat = targetFormat;
  786. updateSampleLink(httpMethod);
  787. enableFormattingButton(currentFormat);
  788. setContentType(formatList[currentFormat].toLowerCase());
  789. return;
  790. }
  791. if (targetFormat == 2 || currentFormat == 2) { //raw format.
  792. targetTextBox.val(currentTextbox.val());
  793. currentFormat = targetFormat;
  794. }
  795. else {
  796. var uriTemplate = $("#uriTemplate").val();
  797. var content = currentTextbox.val();
  798. var errorMessage = null;
  799. proxy.convertRequestBodyFormat(
  800. uriTemplate,
  801. httpMethod,
  802. formatList[currentFormat].toLowerCase(),
  803. formatList[targetFormat].toLowerCase(),
  804. content,
  805. function (convertResult) {
  806. targetTextBox.val(convertResult);
  807. currentTextbox.val("");
  808. currentFormat = targetFormat;
  809. setContentLength(targetTextBox.val());
  810. },
  811. function () {
  812. errorMessage = ["The request body cannot be converted from "];
  813. errorMessage.push(formatList[currentFormat]);
  814. errorMessage.push(" to ");
  815. errorMessage.push(formatList[targetFormat]);
  816. errorMessage.push(". Do you want to paste it to ");
  817. errorMessage.push(formatList[targetFormat] + " tab?");
  818. });
  819. if (errorMessage != null) {
  820. var answer = window.confirm(errorMessage.join(""));
  821. if (answer) {
  822. targetTextBox.val(content);
  823. currentTextbox.val("");
  824. currentFormat = targetFormat;
  825. setContentLength(targetTextBox.val());
  826. }
  827. else {
  828. formatTabs.tabs('select', currentFormat);
  829. }
  830. }
  831. }
  832. enableFormattingButton(currentFormat);
  833. updateSampleLink(httpMethod);
  834. setContentType(formatList[currentFormat].toLowerCase());
  835. }
  836. });
  837. $("#formatButton").click(function () {
  838. if (currentFormat == 0 || currentFormat == 1) {
  839. //TODO: prevent the user from clicking other tabs.
  840. var currentTextBox = $("#requestBody" + formatList[currentFormat]);
  841. var rawRequestBody = currentTextBox.val();
  842. if (rawRequestBody.length > 0) {
  843. proxy.formatRequestBody(
  844. $("#uriTemplate").val(),
  845. $("#httpMethodTextBox").val(),
  846. rawRequestBody,
  847. formatList[currentFormat].toLowerCase(),
  848. function (formattedText) {
  849. currentTextBox.val(formattedText);
  850. },
  851. function () {
  852. //TODO: show Formatting failed message.
  853. });
  854. }
  855. }
  856. });
  857. $("#invokeButton").click(function () {
  858. clearLastResponse();
  859. var httpMethod = $("#httpMethodTextBox").val();
  860. var url = $("#uri").val();
  861. var requestHeader = $("#requestHeader").val();
  862. if (httpMethod.length == 0) {
  863. alert("HTTP Method should not be empty");
  864. $("#httpMethodTextBox").focus();
  865. return false;
  866. }
  867. if (url.length == 0) {
  868. alert("Url should not be empty");
  869. $("#uri").focus();
  870. return false;
  871. }
  872. var httpRequest = new XMLHttpRequest();
  873. try {
  874. httpRequest.open(httpMethod, encodeURI(url), false);
  875. }
  876. catch (e) {
  877. alert("Cannot send request. Check the security setting of your browser if you are sending request to a different domain.");
  878. return false;
  879. }
  880. var requestHeaders = requestHeader.split("\n");
  881. httpRequest.setRequestHeader("If-Modified-Since", new Date(0));
  882. for (var i = 0; i < requestHeaders.length; i++) {
  883. var headerPair = requestHeaders[i].split(":", 2);
  884. if (headerPair.length == 2) {
  885. httpRequest.setRequestHeader(headerPair[0], headerPair[1]);
  886. }
  887. }
  888. var ir = new $.invokeRecord();
  889. ir.resource(currentResource);
  890. ir.httpMethod(httpMethod);
  891. ir.uri(url);
  892. ir.uriTemplate($("#uriTemplate").val());
  893. ir.requestHeader(requestHeader);
  894. ir.requestBody($("#requestBody" + formatList[currentFormat]).val());
  895. ir.format(currentFormat);
  896. if ($.browser.mozilla) { //since firefox 3.5/3.6 will not trigger XMLHttpRequest.onreadystatechange().
  897. httpRequest.onload = httpRequest.onerror = httpRequest.onabort = function(){
  898. handleHttpResponse(httpRequest, ir);
  899. };
  900. }
  901. else{
  902. httpRequest.onreadystatechange = function () {
  903. switch (this.readyState) {
  904. case 4:
  905. handleHttpResponse(httpRequest, ir);
  906. break;
  907. default:
  908. break;
  909. }
  910. }
  911. }
  912. httpRequest.ontimeout = function () {
  913. $("#status").text("Request timed out.");
  914. }
  915. reqTime = new Date();
  916. ir.requestTimeStr(dateToString(reqTime));
  917. httpRequest.send($("#requestBody" + formatList[currentFormat]).val());
  918. return false;
  919. });
  920. $("#container").show();
  921. });