api-request.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**
  2. * Thin jQuery.ajax wrapper for WP REST API requests.
  3. *
  4. * Currently only applies to requests that do not use the `wp-api.js` Backbone
  5. * client library, though this may change. Serves several purposes:
  6. *
  7. * - Allows overriding these requests as needed by customized WP installations.
  8. * - Sends the REST API nonce as a request header.
  9. * - Allows specifying only an endpoint namespace/path instead of a full URL.
  10. *
  11. * @since 4.9.0
  12. * @since 5.6.0 Added overriding of the "PUT" and "DELETE" methods with "POST".
  13. * Added an "application/json" Accept header to all requests.
  14. * @output wp-includes/js/api-request.js
  15. */
  16. ( function( $ ) {
  17. var wpApiSettings = window.wpApiSettings;
  18. function apiRequest( options ) {
  19. options = apiRequest.buildAjaxOptions( options );
  20. return apiRequest.transport( options );
  21. }
  22. apiRequest.buildAjaxOptions = function( options ) {
  23. var url = options.url;
  24. var path = options.path;
  25. var method = options.method;
  26. var namespaceTrimmed, endpointTrimmed, apiRoot;
  27. var headers, addNonceHeader, addAcceptHeader, headerName;
  28. if (
  29. typeof options.namespace === 'string' &&
  30. typeof options.endpoint === 'string'
  31. ) {
  32. namespaceTrimmed = options.namespace.replace( /^\/|\/$/g, '' );
  33. endpointTrimmed = options.endpoint.replace( /^\//, '' );
  34. if ( endpointTrimmed ) {
  35. path = namespaceTrimmed + '/' + endpointTrimmed;
  36. } else {
  37. path = namespaceTrimmed;
  38. }
  39. }
  40. if ( typeof path === 'string' ) {
  41. apiRoot = wpApiSettings.root;
  42. path = path.replace( /^\//, '' );
  43. // API root may already include query parameter prefix
  44. // if site is configured to use plain permalinks.
  45. if ( 'string' === typeof apiRoot && -1 !== apiRoot.indexOf( '?' ) ) {
  46. path = path.replace( '?', '&' );
  47. }
  48. url = apiRoot + path;
  49. }
  50. // If ?_wpnonce=... is present, no need to add a nonce header.
  51. addNonceHeader = ! ( options.data && options.data._wpnonce );
  52. addAcceptHeader = true;
  53. headers = options.headers || {};
  54. for ( headerName in headers ) {
  55. if ( ! headers.hasOwnProperty( headerName ) ) {
  56. continue;
  57. }
  58. // If an 'X-WP-Nonce' or 'Accept' header (or any case-insensitive variation
  59. // thereof) was specified, no need to add the header again.
  60. switch ( headerName.toLowerCase() ) {
  61. case 'x-wp-nonce':
  62. addNonceHeader = false;
  63. break;
  64. case 'accept':
  65. addAcceptHeader = false;
  66. break;
  67. }
  68. }
  69. if ( addNonceHeader ) {
  70. // Do not mutate the original headers object, if any.
  71. headers = $.extend( {
  72. 'X-WP-Nonce': wpApiSettings.nonce
  73. }, headers );
  74. }
  75. if ( addAcceptHeader ) {
  76. headers = $.extend( {
  77. 'Accept': 'application/json, */*;q=0.1'
  78. }, headers );
  79. }
  80. if ( typeof method === 'string' ) {
  81. method = method.toUpperCase();
  82. if ( 'PUT' === method || 'DELETE' === method ) {
  83. headers = $.extend( {
  84. 'X-HTTP-Method-Override': method
  85. }, headers );
  86. method = 'POST';
  87. }
  88. }
  89. // Do not mutate the original options object.
  90. options = $.extend( {}, options, {
  91. headers: headers,
  92. url: url,
  93. method: method
  94. } );
  95. delete options.path;
  96. delete options.namespace;
  97. delete options.endpoint;
  98. return options;
  99. };
  100. apiRequest.transport = $.ajax;
  101. /** @namespace wp */
  102. window.wp = window.wp || {};
  103. window.wp.apiRequest = apiRequest;
  104. } )( jQuery );