Rest.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.rpc.Rest"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.rpc.Rest"] = true;
  8. dojo.provide("dojox.rpc.Rest");
  9. // Note: This doesn't require dojox.rpc.Service, and if you want it you must require it
  10. // yourself, and you must load it prior to dojox.rpc.Rest.
  11. // summary:
  12. // This provides a HTTP REST service with full range REST verbs include PUT,POST, and DELETE.
  13. // description:
  14. // A normal GET query is done by using the service directly:
  15. // | var restService = dojox.rpc.Rest("Project");
  16. // | restService("4");
  17. // This will do a GET for the URL "/Project/4".
  18. // | restService.put("4","new content");
  19. // This will do a PUT to the URL "/Project/4" with the content of "new content".
  20. // You can also use the SMD service to generate a REST service:
  21. // | var services = dojox.rpc.Service({services: {myRestService: {transport: "REST",...
  22. // | services.myRestService("parameters");
  23. //
  24. // The modifying methods can be called as sub-methods of the rest service method like:
  25. // | services.myRestService.put("parameters","data to put in resource");
  26. // | services.myRestService.post("parameters","data to post to the resource");
  27. // | services.myRestService['delete']("parameters");
  28. // Wrap the code in a function as the "define" header will be remove by the build.
  29. (function(){
  30. if(dojox.rpc && dojox.rpc.transportRegistry){
  31. // register it as an RPC service if the registry is available
  32. dojox.rpc.transportRegistry.register(
  33. "REST",
  34. function(str){return str == "REST";},
  35. {
  36. getExecutor : function(func,method,svc){
  37. return new dojox.rpc.Rest(
  38. method.name,
  39. (method.contentType||svc._smd.contentType||"").match(/json|javascript/), // isJson
  40. null,
  41. function(id, args){
  42. var request = svc._getRequest(method,[id]);
  43. request.url= request.target + (request.data ? '?'+ request.data : '');
  44. if(args && (args.start >= 0 || args.count >= 0)){
  45. request.headers = request.headers || {};
  46. request.headers.Range = "items=" + (args.start || '0') + '-' +
  47. (("count" in args && args.count != Infinity) ?
  48. (args.count + (args.start || 0) - 1) : '');
  49. }
  50. return request;
  51. }
  52. );
  53. }
  54. }
  55. );
  56. }
  57. var drr;
  58. function index(deferred, service, range, id){
  59. deferred.addCallback(function(result){
  60. if(deferred.ioArgs.xhr && range){
  61. // try to record the total number of items from the range header
  62. range = deferred.ioArgs.xhr.getResponseHeader("Content-Range");
  63. deferred.fullLength = range && (range=range.match(/\/(.*)/)) && parseInt(range[1]);
  64. }
  65. return result;
  66. });
  67. return deferred;
  68. }
  69. drr = dojox.rpc.Rest = function(/*String*/path, /*Boolean?*/isJson, /*Object?*/schema, /*Function?*/getRequest){
  70. // summary:
  71. // Creates a REST service using the provided path.
  72. var service;
  73. // it should be in the form /Table/
  74. service = function(id, args){
  75. return drr._get(service, id, args);
  76. };
  77. service.isJson = isJson;
  78. service._schema = schema;
  79. // cache:
  80. // This is an object that provides indexing service
  81. // This can be overriden to take advantage of more complex referencing/indexing
  82. // schemes
  83. service.cache = {
  84. serialize: isJson ? ((dojox.json && dojox.json.ref) || dojo).toJson : function(result){
  85. return result;
  86. }
  87. };
  88. // the default XHR args creator:
  89. service._getRequest = getRequest || function(id, args){
  90. if(dojo.isObject(id)){
  91. id = dojo.objectToQuery(id);
  92. id = id ? "?" + id: "";
  93. }
  94. if(args && args.sort && !args.queryStr){
  95. id += (id ? "&" : "?") + "sort("
  96. for(var i = 0; i<args.sort.length; i++){
  97. var sort = args.sort[i];
  98. id += (i > 0 ? "," : "") + (sort.descending ? '-' : '+') + encodeURIComponent(sort.attribute);
  99. }
  100. id += ")";
  101. }
  102. var request = {
  103. url: path + (id == null ? "" : id),
  104. handleAs: isJson ? 'json' : 'text',
  105. contentType: isJson ? 'application/json' : 'text/plain',
  106. sync: dojox.rpc._sync,
  107. headers: {
  108. Accept: isJson ? 'application/json,application/javascript' : '*/*'
  109. }
  110. };
  111. if(args && (args.start >= 0 || args.count >= 0)){
  112. request.headers.Range = "items=" + (args.start || '0') + '-' +
  113. (("count" in args && args.count != Infinity) ?
  114. (args.count + (args.start || 0) - 1) : '');
  115. }
  116. dojox.rpc._sync = false;
  117. return request;
  118. };
  119. // each calls the event handler
  120. function makeRest(name){
  121. service[name] = function(id,content){
  122. return drr._change(name,service,id,content); // the last parameter is to let the OfflineRest know where to store the item
  123. };
  124. }
  125. makeRest('put');
  126. makeRest('post');
  127. makeRest('delete');
  128. // record the REST services for later lookup
  129. service.servicePath = path;
  130. return service;
  131. };
  132. drr._index={};// the map of all indexed objects that have gone through REST processing
  133. drr._timeStamps={};
  134. // these do the actual requests
  135. drr._change = function(method,service,id,content){
  136. // this is called to actually do the put, post, and delete
  137. var request = service._getRequest(id);
  138. request[method+"Data"] = content;
  139. return index(dojo.xhr(method.toUpperCase(),request,true),service);
  140. };
  141. drr._get= function(service,id, args){
  142. args = args || {};
  143. // this is called to actually do the get
  144. return index(dojo.xhrGet(service._getRequest(id, args)), service, (args.start >= 0 || args.count >= 0), id);
  145. };
  146. })();
  147. }