Server.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-data-proxy-Server'>/**
  19. </span> * @author Ed Spencer
  20. *
  21. * ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy}, and
  22. * would not usually be used directly.
  23. *
  24. * ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been
  25. * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now
  26. * an alias of AjaxProxy).
  27. * @private
  28. */
  29. Ext.define('Ext.data.proxy.Server', {
  30. extend: 'Ext.data.proxy.Proxy',
  31. alias : 'proxy.server',
  32. alternateClassName: 'Ext.data.ServerProxy',
  33. uses : ['Ext.data.Request'],
  34. <span id='Ext-data-proxy-Server-cfg-url'> /**
  35. </span> * @cfg {String} url
  36. * The URL from which to request the data object.
  37. */
  38. <span id='Ext-data-proxy-Server-cfg-pageParam'> /**
  39. </span> * @cfg {String} pageParam
  40. * The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to undefined if you don't
  41. * want to send a page parameter.
  42. */
  43. pageParam: 'page',
  44. <span id='Ext-data-proxy-Server-cfg-startParam'> /**
  45. </span> * @cfg {String} startParam
  46. * The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this to undefined if you don't
  47. * want to send a start parameter.
  48. */
  49. startParam: 'start',
  50. <span id='Ext-data-proxy-Server-cfg-limitParam'> /**
  51. </span> * @cfg {String} limitParam
  52. * The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this to undefined if you don't
  53. * want to send a limit parameter.
  54. */
  55. limitParam: 'limit',
  56. <span id='Ext-data-proxy-Server-cfg-groupParam'> /**
  57. </span> * @cfg {String} groupParam
  58. * The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this to undefined if you don't
  59. * want to send a group parameter.
  60. */
  61. groupParam: 'group',
  62. <span id='Ext-data-proxy-Server-cfg-groupDirectionParam'> /**
  63. </span> * @cfg {String} groupDirectionParam
  64. * The name of the direction parameter to send in a request. **This is only used when simpleGroupMode is set to
  65. * true.** Defaults to 'groupDir'.
  66. */
  67. groupDirectionParam: 'groupDir',
  68. <span id='Ext-data-proxy-Server-cfg-sortParam'> /**
  69. </span> * @cfg {String} sortParam
  70. * The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this to undefined if you don't
  71. * want to send a sort parameter.
  72. */
  73. sortParam: 'sort',
  74. <span id='Ext-data-proxy-Server-cfg-filterParam'> /**
  75. </span> * @cfg {String} filterParam
  76. * The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set this to undefined if you don't
  77. * want to send a filter parameter.
  78. */
  79. filterParam: 'filter',
  80. <span id='Ext-data-proxy-Server-cfg-directionParam'> /**
  81. </span> * @cfg {String} directionParam
  82. * The name of the direction parameter to send in a request. **This is only used when simpleSortMode is set to
  83. * true.** Defaults to 'dir'.
  84. */
  85. directionParam: 'dir',
  86. <span id='Ext-data-proxy-Server-cfg-simpleSortMode'> /**
  87. </span> * @cfg {Boolean} simpleSortMode
  88. * Enabling simpleSortMode in conjunction with remoteSort will only send one sort property and a direction when a
  89. * remote sort is requested. The {@link #directionParam} and {@link #sortParam} will be sent with the property name
  90. * and either 'ASC' or 'DESC'.
  91. */
  92. simpleSortMode: false,
  93. <span id='Ext-data-proxy-Server-cfg-simpleGroupMode'> /**
  94. </span> * @cfg {Boolean} simpleGroupMode
  95. * Enabling simpleGroupMode in conjunction with remoteGroup will only send one group property and a direction when a
  96. * remote group is requested. The {@link #groupDirectionParam} and {@link #groupParam} will be sent with the property name and either 'ASC'
  97. * or 'DESC'.
  98. */
  99. simpleGroupMode: false,
  100. <span id='Ext-data-proxy-Server-cfg-noCache'> /**
  101. </span> * @cfg {Boolean} noCache
  102. * Disable caching by adding a unique parameter name to the request. Set to false to allow caching. Defaults to true.
  103. */
  104. noCache : true,
  105. <span id='Ext-data-proxy-Server-cfg-cacheString'> /**
  106. </span> * @cfg {String} cacheString
  107. * The name of the cache param added to the url when using noCache. Defaults to &quot;_dc&quot;.
  108. */
  109. cacheString: &quot;_dc&quot;,
  110. <span id='Ext-data-proxy-Server-cfg-timeout'> /**
  111. </span> * @cfg {Number} timeout
  112. * The number of milliseconds to wait for a response. Defaults to 30000 milliseconds (30 seconds).
  113. */
  114. timeout : 30000,
  115. <span id='Ext-data-proxy-Server-cfg-api'> /**
  116. </span> * @cfg {Object} api
  117. * Specific urls to call on CRUD action methods &quot;create&quot;, &quot;read&quot;, &quot;update&quot; and &quot;destroy&quot;. Defaults to:
  118. *
  119. * api: {
  120. * create : undefined,
  121. * read : undefined,
  122. * update : undefined,
  123. * destroy : undefined
  124. * }
  125. *
  126. * The url is built based upon the action being executed [create|read|update|destroy] using the commensurate
  127. * {@link #api} property, or if undefined default to the configured
  128. * {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.
  129. *
  130. * For example:
  131. *
  132. * api: {
  133. * create : '/controller/new',
  134. * read : '/controller/load',
  135. * update : '/controller/update',
  136. * destroy : '/controller/destroy_action'
  137. * }
  138. *
  139. * If the specific URL for a given CRUD action is undefined, the CRUD action request will be directed to the
  140. * configured {@link Ext.data.proxy.Server#url url}.
  141. */
  142. constructor: function(config) {
  143. var me = this;
  144. config = config || {};
  145. <span id='Ext-data-proxy-Server-event-exception'> /**
  146. </span> * @event exception
  147. * Fires when the server returns an exception
  148. * @param {Ext.data.proxy.Proxy} this
  149. * @param {Object} response The response from the AJAX request
  150. * @param {Ext.data.Operation} operation The operation that triggered request
  151. */
  152. me.callParent([config]);
  153. <span id='Ext-data-proxy-Server-cfg-extraParams'> /**
  154. </span> * @cfg {Object} extraParams
  155. * Extra parameters that will be included on every request. Individual requests with params of the same name
  156. * will override these params when they are in conflict.
  157. */
  158. me.extraParams = config.extraParams || {};
  159. me.api = Ext.apply({}, config.api || me.api);
  160. //backwards compatibility, will be deprecated in 5.0
  161. me.nocache = me.noCache;
  162. },
  163. //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case
  164. create: function() {
  165. return this.doRequest.apply(this, arguments);
  166. },
  167. read: function() {
  168. return this.doRequest.apply(this, arguments);
  169. },
  170. update: function() {
  171. return this.doRequest.apply(this, arguments);
  172. },
  173. destroy: function() {
  174. return this.doRequest.apply(this, arguments);
  175. },
  176. <span id='Ext-data-proxy-Server-method-setExtraParam'> /**
  177. </span> * Sets a value in the underlying {@link #extraParams}.
  178. * @param {String} name The key for the new value
  179. * @param {Object} value The value
  180. */
  181. setExtraParam: function(name, value) {
  182. this.extraParams[name] = value;
  183. },
  184. <span id='Ext-data-proxy-Server-method-buildRequest'> /**
  185. </span> * Creates an {@link Ext.data.Request Request} object from {@link Ext.data.Operation Operation}.
  186. *
  187. * This gets called from doRequest methods in subclasses of Server proxy.
  188. *
  189. * @param {Ext.data.Operation} operation The operation to execute
  190. * @return {Ext.data.Request} The request object
  191. */
  192. buildRequest: function(operation) {
  193. var me = this,
  194. params = Ext.applyIf(operation.params || {}, me.extraParams || {}),
  195. request;
  196. //copy any sorters, filters etc into the params so they can be sent over the wire
  197. params = Ext.applyIf(params, me.getParams(operation));
  198. if (operation.id !== undefined &amp;&amp; params.id === undefined) {
  199. params.id = operation.id;
  200. }
  201. request = new Ext.data.Request({
  202. params : params,
  203. action : operation.action,
  204. records : operation.records,
  205. operation: operation,
  206. url : operation.url,
  207. // this is needed by JsonSimlet in order to properly construct responses for
  208. // requests from this proxy
  209. proxy: me
  210. });
  211. request.url = me.buildUrl(request);
  212. /*
  213. * Save the request on the Operation. Operations don't usually care about Request and Response data, but in the
  214. * ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing
  215. */
  216. operation.request = request;
  217. return request;
  218. },
  219. // Should this be documented as protected method?
  220. processResponse: function(success, operation, request, response, callback, scope) {
  221. var me = this,
  222. reader,
  223. result;
  224. if (success === true) {
  225. reader = me.getReader();
  226. // Apply defaults to incoming data only for read operations.
  227. // For create and update, there will already be a client-side record
  228. // to match with which will contain any defaulted in values.
  229. reader.applyDefaults = operation.action === 'read';
  230. result = reader.read(me.extractResponseData(response));
  231. if (result.success !== false) {
  232. //see comment in buildRequest for why we include the response object here
  233. Ext.apply(operation, {
  234. response: response,
  235. resultSet: result
  236. });
  237. operation.commitRecords(result.records);
  238. operation.setCompleted();
  239. operation.setSuccessful();
  240. } else {
  241. operation.setException(result.message);
  242. me.fireEvent('exception', this, response, operation);
  243. }
  244. } else {
  245. me.setException(operation, response);
  246. me.fireEvent('exception', this, response, operation);
  247. }
  248. //this callback is the one that was passed to the 'read' or 'write' function above
  249. if (typeof callback == 'function') {
  250. callback.call(scope || me, operation);
  251. }
  252. me.afterRequest(request, success);
  253. },
  254. <span id='Ext-data-proxy-Server-method-setException'> /**
  255. </span> * Sets up an exception on the operation
  256. * @private
  257. * @param {Ext.data.Operation} operation The operation
  258. * @param {Object} response The response
  259. */
  260. setException: function(operation, response) {
  261. operation.setException({
  262. status: response.status,
  263. statusText: response.statusText
  264. });
  265. },
  266. <span id='Ext-data-proxy-Server-method-extractResponseData'> /**
  267. </span> * Template method to allow subclasses to specify how to get the response for the reader.
  268. * @template
  269. * @private
  270. * @param {Object} response The server response
  271. * @return {Object} The response data to be used by the reader
  272. */
  273. extractResponseData: function(response) {
  274. return response;
  275. },
  276. <span id='Ext-data-proxy-Server-method-applyEncoding'> /**
  277. </span> * Encode any values being sent to the server. Can be overridden in subclasses.
  278. * @private
  279. * @param {Array} An array of sorters/filters.
  280. * @return {Object} The encoded value
  281. */
  282. applyEncoding: function(value) {
  283. return Ext.encode(value);
  284. },
  285. <span id='Ext-data-proxy-Server-method-encodeSorters'> /**
  286. </span> * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default,
  287. * this simply JSON-encodes the sorter data
  288. * @param {Ext.util.Sorter[]} sorters The array of {@link Ext.util.Sorter Sorter} objects
  289. * @return {String} The encoded sorters
  290. */
  291. encodeSorters: function(sorters) {
  292. var min = [],
  293. length = sorters.length,
  294. i = 0;
  295. for (; i &lt; length; i++) {
  296. min[i] = {
  297. property : sorters[i].property,
  298. direction: sorters[i].direction
  299. };
  300. }
  301. return this.applyEncoding(min);
  302. },
  303. <span id='Ext-data-proxy-Server-method-encodeFilters'> /**
  304. </span> * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default,
  305. * this simply JSON-encodes the filter data
  306. * @param {Ext.util.Filter[]} filters The array of {@link Ext.util.Filter Filter} objects
  307. * @return {String} The encoded filters
  308. */
  309. encodeFilters: function(filters) {
  310. var min = [],
  311. length = filters.length,
  312. i = 0;
  313. for (; i &lt; length; i++) {
  314. min[i] = {
  315. property: filters[i].property,
  316. value : filters[i].value
  317. };
  318. }
  319. return this.applyEncoding(min);
  320. },
  321. <span id='Ext-data-proxy-Server-method-getParams'> /**
  322. </span> * @private
  323. * Copy any sorters, filters etc into the params so they can be sent over the wire
  324. */
  325. getParams: function(operation) {
  326. var me = this,
  327. params = {},
  328. isDef = Ext.isDefined,
  329. groupers = operation.groupers,
  330. sorters = operation.sorters,
  331. filters = operation.filters,
  332. page = operation.page,
  333. start = operation.start,
  334. limit = operation.limit,
  335. simpleSortMode = me.simpleSortMode,
  336. simpleGroupMode = me.simpleGroupMode,
  337. pageParam = me.pageParam,
  338. startParam = me.startParam,
  339. limitParam = me.limitParam,
  340. groupParam = me.groupParam,
  341. groupDirectionParam = me.groupDirectionParam,
  342. sortParam = me.sortParam,
  343. filterParam = me.filterParam,
  344. directionParam = me.directionParam;
  345. if (pageParam &amp;&amp; isDef(page)) {
  346. params[pageParam] = page;
  347. }
  348. if (startParam &amp;&amp; isDef(start)) {
  349. params[startParam] = start;
  350. }
  351. if (limitParam &amp;&amp; isDef(limit)) {
  352. params[limitParam] = limit;
  353. }
  354. if (groupParam &amp;&amp; groupers &amp;&amp; groupers.length &gt; 0) {
  355. // Grouper is a subclass of sorter, so we can just use the sorter method
  356. if (simpleGroupMode) {
  357. params[groupParam] = groupers[0].property;
  358. params[groupDirectionParam] = groupers[0].direction || 'ASC';
  359. } else {
  360. params[groupParam] = me.encodeSorters(groupers);
  361. }
  362. }
  363. if (sortParam &amp;&amp; sorters &amp;&amp; sorters.length &gt; 0) {
  364. if (simpleSortMode) {
  365. params[sortParam] = sorters[0].property;
  366. params[directionParam] = sorters[0].direction;
  367. } else {
  368. params[sortParam] = me.encodeSorters(sorters);
  369. }
  370. }
  371. if (filterParam &amp;&amp; filters &amp;&amp; filters.length &gt; 0) {
  372. params[filterParam] = me.encodeFilters(filters);
  373. }
  374. return params;
  375. },
  376. <span id='Ext-data-proxy-Server-method-buildUrl'> /**
  377. </span> * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will add the
  378. * cache-buster param to the end of the url. Subclasses may need to perform additional modifications to the url.
  379. * @param {Ext.data.Request} request The request object
  380. * @return {String} The url
  381. */
  382. buildUrl: function(request) {
  383. var me = this,
  384. url = me.getUrl(request);
  385. //&lt;debug&gt;
  386. if (!url) {
  387. Ext.Error.raise(&quot;You are using a ServerProxy but have not supplied it with a url.&quot;);
  388. }
  389. //&lt;/debug&gt;
  390. if (me.noCache) {
  391. url = Ext.urlAppend(url, Ext.String.format(&quot;{0}={1}&quot;, me.cacheString, Ext.Date.now()));
  392. }
  393. return url;
  394. },
  395. <span id='Ext-data-proxy-Server-method-getUrl'> /**
  396. </span> * Get the url for the request taking into account the order of priority,
  397. * - The request
  398. * - The api
  399. * - The url
  400. * @private
  401. * @param {Ext.data.Request} request The request
  402. * @return {String} The url
  403. */
  404. getUrl: function(request) {
  405. return request.url || this.api[request.action] || this.url;
  406. },
  407. <span id='Ext-data-proxy-Server-method-doRequest'> /**
  408. </span> * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all
  409. * pass through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link
  410. * Ext.data.proxy.JsonP} and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as
  411. * each of the methods that delegate to it.
  412. *
  413. * @param {Ext.data.Operation} operation The Ext.data.Operation object
  414. * @param {Function} callback The callback function to call when the Operation has completed
  415. * @param {Object} scope The scope in which to execute the callback
  416. */
  417. doRequest: function(operation, callback, scope) {
  418. //&lt;debug&gt;
  419. Ext.Error.raise(&quot;The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details&quot;);
  420. //&lt;/debug&gt;
  421. },
  422. <span id='Ext-data-proxy-Server-method-afterRequest'> /**
  423. </span> * Optional callback function which can be used to clean up after a request has been completed.
  424. * @param {Ext.data.Request} request The Request object
  425. * @param {Boolean} success True if the request was successful
  426. * @protected
  427. * @template
  428. * @method
  429. */
  430. afterRequest: Ext.emptyFn,
  431. onDestroy: function() {
  432. Ext.destroy(this.reader, this.writer);
  433. }
  434. });
  435. </pre>
  436. </body>
  437. </html>