@wordpress/api-fetch
Advanced tools
Comparing version 2.2.8 to 3.0.0
@@ -43,92 +43,110 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread"; | ||
}; | ||
var middlewares = []; | ||
var middlewares = [userLocaleMiddleware, namespaceEndpointMiddleware, httpV1Middleware, fetchAllMiddleware]; | ||
function registerMiddleware(middleware) { | ||
middlewares.push(middleware); | ||
middlewares.unshift(middleware); | ||
} | ||
function apiFetch(options) { | ||
var raw = function raw(nextOptions) { | ||
var url = nextOptions.url, | ||
path = nextOptions.path, | ||
data = nextOptions.data, | ||
_nextOptions$parse = nextOptions.parse, | ||
parse = _nextOptions$parse === void 0 ? true : _nextOptions$parse, | ||
remainingOptions = _objectWithoutProperties(nextOptions, ["url", "path", "data", "parse"]); | ||
var defaultFetchHandler = function defaultFetchHandler(nextOptions) { | ||
var url = nextOptions.url, | ||
path = nextOptions.path, | ||
data = nextOptions.data, | ||
_nextOptions$parse = nextOptions.parse, | ||
parse = _nextOptions$parse === void 0 ? true : _nextOptions$parse, | ||
remainingOptions = _objectWithoutProperties(nextOptions, ["url", "path", "data", "parse"]); | ||
var body = nextOptions.body, | ||
headers = nextOptions.headers; // Merge explicitly-provided headers with default values. | ||
var body = nextOptions.body, | ||
headers = nextOptions.headers; // Merge explicitly-provided headers with default values. | ||
headers = _objectSpread({}, DEFAULT_HEADERS, headers); // The `data` property is a shorthand for sending a JSON body. | ||
headers = _objectSpread({}, DEFAULT_HEADERS, headers); // The `data` property is a shorthand for sending a JSON body. | ||
if (data) { | ||
body = JSON.stringify(data); | ||
headers['Content-Type'] = 'application/json'; | ||
if (data) { | ||
body = JSON.stringify(data); | ||
headers['Content-Type'] = 'application/json'; | ||
} | ||
var responsePromise = window.fetch(url || path, _objectSpread({}, DEFAULT_OPTIONS, remainingOptions, { | ||
body: body, | ||
headers: headers | ||
})); | ||
var checkStatus = function checkStatus(response) { | ||
if (response.status >= 200 && response.status < 300) { | ||
return response; | ||
} | ||
var responsePromise = window.fetch(url || path, _objectSpread({}, DEFAULT_OPTIONS, remainingOptions, { | ||
body: body, | ||
headers: headers | ||
})); | ||
throw response; | ||
}; | ||
var checkStatus = function checkStatus(response) { | ||
if (response.status >= 200 && response.status < 300) { | ||
return response; | ||
var parseResponse = function parseResponse(response) { | ||
if (parse) { | ||
if (response.status === 204) { | ||
return null; | ||
} | ||
throw response; | ||
}; | ||
return response.json ? response.json() : Promise.reject(response); | ||
} | ||
var parseResponse = function parseResponse(response) { | ||
if (parse) { | ||
if (response.status === 204) { | ||
return null; | ||
} | ||
return response; | ||
}; | ||
return response.json ? response.json() : Promise.reject(response); | ||
} | ||
return responsePromise.then(checkStatus).then(parseResponse).catch(function (response) { | ||
if (!parse) { | ||
throw response; | ||
} | ||
return response; | ||
var invalidJsonError = { | ||
code: 'invalid_json', | ||
message: __('The response is not a valid JSON response.') | ||
}; | ||
return responsePromise.then(checkStatus).then(parseResponse).catch(function (response) { | ||
if (!parse) { | ||
throw response; | ||
} | ||
if (!response || !response.json) { | ||
throw invalidJsonError; | ||
} | ||
var invalidJsonError = { | ||
code: 'invalid_json', | ||
message: __('The response is not a valid JSON response.') | ||
return response.json().catch(function () { | ||
throw invalidJsonError; | ||
}).then(function (error) { | ||
var unknownError = { | ||
code: 'unknown_error', | ||
message: __('An unknown error occurred.') | ||
}; | ||
throw error || unknownError; | ||
}); | ||
}); | ||
}; | ||
if (!response || !response.json) { | ||
throw invalidJsonError; | ||
} | ||
var fetchHandler = defaultFetchHandler; | ||
/** | ||
* Defines a custom fetch handler for making the requests that will override | ||
* the default one using window.fetch | ||
* | ||
* @param {Function} newFetchHandler The new fetch handler | ||
*/ | ||
return response.json().catch(function () { | ||
throw invalidJsonError; | ||
}).then(function (error) { | ||
var unknownError = { | ||
code: 'unknown_error', | ||
message: __('An unknown error occurred.') | ||
}; | ||
throw error || unknownError; | ||
}); | ||
}); | ||
}; | ||
function setFetchHandler(newFetchHandler) { | ||
fetchHandler = newFetchHandler; | ||
} | ||
var steps = [raw, fetchAllMiddleware, httpV1Middleware, namespaceEndpointMiddleware, userLocaleMiddleware].concat(middlewares).reverse(); | ||
function apiFetch(options) { | ||
var steps = [].concat(middlewares, [fetchHandler]); | ||
var runMiddleware = function runMiddleware(index) { | ||
return function (nextOptions) { | ||
var nextMiddleware = steps[index]; | ||
var next = runMiddleware(index + 1); | ||
return nextMiddleware(nextOptions, next); | ||
var createRunStep = function createRunStep(index) { | ||
return function (workingOptions) { | ||
var step = steps[index]; | ||
if (index === steps.length - 1) { | ||
return step(workingOptions); | ||
} | ||
var next = createRunStep(index + 1); | ||
return step(workingOptions, next); | ||
}; | ||
}; | ||
return runMiddleware(0)(options); | ||
return createRunStep(0)(options); | ||
} | ||
apiFetch.use = registerMiddleware; | ||
apiFetch.setFetchHandler = setFetchHandler; | ||
apiFetch.createNonceMiddleware = createNonceMiddleware; | ||
@@ -135,0 +153,0 @@ apiFetch.createPreloadingMiddleware = createPreloadingMiddleware; |
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread"; | ||
/** | ||
* External dependencies | ||
*/ | ||
import { addAction } from '@wordpress/hooks'; | ||
var createNonceMiddleware = function createNonceMiddleware(nonce) { | ||
var usedNonce = nonce; | ||
/** | ||
* This is not ideal but it's fine for now. | ||
* | ||
* Configure heartbeat to refresh the wp-api nonce, keeping the editor | ||
* authorization intact. | ||
*/ | ||
addAction('heartbeat.tick', 'core/api-fetch/create-nonce-middleware', function (response) { | ||
if (response['rest-nonce']) { | ||
usedNonce = response['rest-nonce']; | ||
} | ||
}); | ||
return function (options, next) { | ||
var headers = options.headers || {}; // If an 'X-WP-Nonce' header (or any case-insensitive variation | ||
function createNonceMiddleware(nonce) { | ||
function middleware(options, next) { | ||
var _options$headers = options.headers, | ||
headers = _options$headers === void 0 ? {} : _options$headers; // If an 'X-WP-Nonce' header (or any case-insensitive variation | ||
// thereof) was specified, no need to add a nonce header. | ||
var addNonceHeader = true; | ||
for (var headerName in headers) { | ||
if (headers.hasOwnProperty(headerName)) { | ||
if (headerName.toLowerCase() === 'x-wp-nonce') { | ||
addNonceHeader = false; | ||
break; | ||
} | ||
if (headerName.toLowerCase() === 'x-wp-nonce') { | ||
return next(options); | ||
} | ||
} | ||
if (addNonceHeader) { | ||
// Do not mutate the original headers object, if any. | ||
headers = _objectSpread({}, headers, { | ||
'X-WP-Nonce': usedNonce | ||
}); | ||
} | ||
return next(_objectSpread({}, options, { | ||
headers: headers | ||
headers: _objectSpread({}, headers, { | ||
'X-WP-Nonce': middleware.nonce | ||
}) | ||
})); | ||
}; | ||
}; | ||
} | ||
middleware.nonce = nonce; | ||
return middleware; | ||
} | ||
export default createNonceMiddleware; | ||
//# sourceMappingURL=nonce.js.map |
@@ -61,91 +61,109 @@ "use strict"; | ||
}; | ||
var middlewares = []; | ||
var middlewares = [_userLocale.default, _namespaceEndpoint.default, _httpV.default, _fetchAllMiddleware.default]; | ||
function registerMiddleware(middleware) { | ||
middlewares.push(middleware); | ||
middlewares.unshift(middleware); | ||
} | ||
function apiFetch(options) { | ||
var raw = function raw(nextOptions) { | ||
var url = nextOptions.url, | ||
path = nextOptions.path, | ||
data = nextOptions.data, | ||
_nextOptions$parse = nextOptions.parse, | ||
parse = _nextOptions$parse === void 0 ? true : _nextOptions$parse, | ||
remainingOptions = (0, _objectWithoutProperties2.default)(nextOptions, ["url", "path", "data", "parse"]); | ||
var body = nextOptions.body, | ||
headers = nextOptions.headers; // Merge explicitly-provided headers with default values. | ||
var defaultFetchHandler = function defaultFetchHandler(nextOptions) { | ||
var url = nextOptions.url, | ||
path = nextOptions.path, | ||
data = nextOptions.data, | ||
_nextOptions$parse = nextOptions.parse, | ||
parse = _nextOptions$parse === void 0 ? true : _nextOptions$parse, | ||
remainingOptions = (0, _objectWithoutProperties2.default)(nextOptions, ["url", "path", "data", "parse"]); | ||
var body = nextOptions.body, | ||
headers = nextOptions.headers; // Merge explicitly-provided headers with default values. | ||
headers = (0, _objectSpread2.default)({}, DEFAULT_HEADERS, headers); // The `data` property is a shorthand for sending a JSON body. | ||
headers = (0, _objectSpread2.default)({}, DEFAULT_HEADERS, headers); // The `data` property is a shorthand for sending a JSON body. | ||
if (data) { | ||
body = JSON.stringify(data); | ||
headers['Content-Type'] = 'application/json'; | ||
if (data) { | ||
body = JSON.stringify(data); | ||
headers['Content-Type'] = 'application/json'; | ||
} | ||
var responsePromise = window.fetch(url || path, (0, _objectSpread2.default)({}, DEFAULT_OPTIONS, remainingOptions, { | ||
body: body, | ||
headers: headers | ||
})); | ||
var checkStatus = function checkStatus(response) { | ||
if (response.status >= 200 && response.status < 300) { | ||
return response; | ||
} | ||
var responsePromise = window.fetch(url || path, (0, _objectSpread2.default)({}, DEFAULT_OPTIONS, remainingOptions, { | ||
body: body, | ||
headers: headers | ||
})); | ||
throw response; | ||
}; | ||
var checkStatus = function checkStatus(response) { | ||
if (response.status >= 200 && response.status < 300) { | ||
return response; | ||
var parseResponse = function parseResponse(response) { | ||
if (parse) { | ||
if (response.status === 204) { | ||
return null; | ||
} | ||
throw response; | ||
}; | ||
return response.json ? response.json() : Promise.reject(response); | ||
} | ||
var parseResponse = function parseResponse(response) { | ||
if (parse) { | ||
if (response.status === 204) { | ||
return null; | ||
} | ||
return response; | ||
}; | ||
return response.json ? response.json() : Promise.reject(response); | ||
} | ||
return responsePromise.then(checkStatus).then(parseResponse).catch(function (response) { | ||
if (!parse) { | ||
throw response; | ||
} | ||
return response; | ||
var invalidJsonError = { | ||
code: 'invalid_json', | ||
message: (0, _i18n.__)('The response is not a valid JSON response.') | ||
}; | ||
return responsePromise.then(checkStatus).then(parseResponse).catch(function (response) { | ||
if (!parse) { | ||
throw response; | ||
} | ||
if (!response || !response.json) { | ||
throw invalidJsonError; | ||
} | ||
var invalidJsonError = { | ||
code: 'invalid_json', | ||
message: (0, _i18n.__)('The response is not a valid JSON response.') | ||
return response.json().catch(function () { | ||
throw invalidJsonError; | ||
}).then(function (error) { | ||
var unknownError = { | ||
code: 'unknown_error', | ||
message: (0, _i18n.__)('An unknown error occurred.') | ||
}; | ||
throw error || unknownError; | ||
}); | ||
}); | ||
}; | ||
if (!response || !response.json) { | ||
throw invalidJsonError; | ||
} | ||
var fetchHandler = defaultFetchHandler; | ||
/** | ||
* Defines a custom fetch handler for making the requests that will override | ||
* the default one using window.fetch | ||
* | ||
* @param {Function} newFetchHandler The new fetch handler | ||
*/ | ||
return response.json().catch(function () { | ||
throw invalidJsonError; | ||
}).then(function (error) { | ||
var unknownError = { | ||
code: 'unknown_error', | ||
message: (0, _i18n.__)('An unknown error occurred.') | ||
}; | ||
throw error || unknownError; | ||
}); | ||
}); | ||
}; | ||
function setFetchHandler(newFetchHandler) { | ||
fetchHandler = newFetchHandler; | ||
} | ||
var steps = [raw, _fetchAllMiddleware.default, _httpV.default, _namespaceEndpoint.default, _userLocale.default].concat(middlewares).reverse(); | ||
function apiFetch(options) { | ||
var steps = [].concat(middlewares, [fetchHandler]); | ||
var runMiddleware = function runMiddleware(index) { | ||
return function (nextOptions) { | ||
var nextMiddleware = steps[index]; | ||
var next = runMiddleware(index + 1); | ||
return nextMiddleware(nextOptions, next); | ||
var createRunStep = function createRunStep(index) { | ||
return function (workingOptions) { | ||
var step = steps[index]; | ||
if (index === steps.length - 1) { | ||
return step(workingOptions); | ||
} | ||
var next = createRunStep(index + 1); | ||
return step(workingOptions, next); | ||
}; | ||
}; | ||
return runMiddleware(0)(options); | ||
return createRunStep(0)(options); | ||
} | ||
apiFetch.use = registerMiddleware; | ||
apiFetch.setFetchHandler = setFetchHandler; | ||
apiFetch.createNonceMiddleware = _nonce.default; | ||
@@ -152,0 +170,0 @@ apiFetch.createPreloadingMiddleware = _preloading.default; |
@@ -12,51 +12,27 @@ "use strict"; | ||
var _hooks = require("@wordpress/hooks"); | ||
/** | ||
* External dependencies | ||
*/ | ||
var createNonceMiddleware = function createNonceMiddleware(nonce) { | ||
var usedNonce = nonce; | ||
/** | ||
* This is not ideal but it's fine for now. | ||
* | ||
* Configure heartbeat to refresh the wp-api nonce, keeping the editor | ||
* authorization intact. | ||
*/ | ||
(0, _hooks.addAction)('heartbeat.tick', 'core/api-fetch/create-nonce-middleware', function (response) { | ||
if (response['rest-nonce']) { | ||
usedNonce = response['rest-nonce']; | ||
} | ||
}); | ||
return function (options, next) { | ||
var headers = options.headers || {}; // If an 'X-WP-Nonce' header (or any case-insensitive variation | ||
function createNonceMiddleware(nonce) { | ||
function middleware(options, next) { | ||
var _options$headers = options.headers, | ||
headers = _options$headers === void 0 ? {} : _options$headers; // If an 'X-WP-Nonce' header (or any case-insensitive variation | ||
// thereof) was specified, no need to add a nonce header. | ||
var addNonceHeader = true; | ||
for (var headerName in headers) { | ||
if (headers.hasOwnProperty(headerName)) { | ||
if (headerName.toLowerCase() === 'x-wp-nonce') { | ||
addNonceHeader = false; | ||
break; | ||
} | ||
if (headerName.toLowerCase() === 'x-wp-nonce') { | ||
return next(options); | ||
} | ||
} | ||
if (addNonceHeader) { | ||
// Do not mutate the original headers object, if any. | ||
headers = (0, _objectSpread2.default)({}, headers, { | ||
'X-WP-Nonce': usedNonce | ||
}); | ||
} | ||
return next((0, _objectSpread2.default)({}, options, { | ||
headers: headers | ||
headers: (0, _objectSpread2.default)({}, headers, { | ||
'X-WP-Nonce': middleware.nonce | ||
}) | ||
})); | ||
}; | ||
}; | ||
} | ||
middleware.nonce = nonce; | ||
return middleware; | ||
} | ||
var _default = createNonceMiddleware; | ||
exports.default = _default; | ||
//# sourceMappingURL=nonce.js.map |
@@ -0,1 +1,12 @@ | ||
## 3.0.0 (Unreleased) | ||
### Breaking Changes | ||
- A created nonce middleware will no longer automatically listen for `heartbeat.tick` actions. Assign to the new `nonce` middleware property instead. | ||
### New Feature | ||
- The function returned by `createNonceMiddleware` includes an assignable `nonce` property corresponding to the active nonce to be used. | ||
- Default fetch handler can be overridden with a custom fetch handler | ||
## 2.2.7 (2019-01-03) | ||
@@ -2,0 +13,0 @@ |
### WordPress - Web publishing software | ||
Copyright 2011-2018 by the contributors | ||
Copyright 2011-2019 by the contributors | ||
@@ -5,0 +5,0 @@ This program is free software; you can redistribute it and/or modify |
{ | ||
"name": "@wordpress/api-fetch", | ||
"version": "2.2.8", | ||
"version": "3.0.0", | ||
"description": "Utility to make WordPress REST API requests.", | ||
@@ -15,3 +15,4 @@ "author": "The WordPress Contributors", | ||
"type": "git", | ||
"url": "https://github.com/WordPress/gutenberg.git" | ||
"url": "https://github.com/WordPress/gutenberg.git", | ||
"directory": "packages/api-fetch" | ||
}, | ||
@@ -25,6 +26,5 @@ "bugs": { | ||
"dependencies": { | ||
"@babel/runtime": "^7.0.0", | ||
"@wordpress/hooks": "^2.0.5", | ||
"@wordpress/i18n": "^3.1.1", | ||
"@wordpress/url": "^2.3.3" | ||
"@babel/runtime": "^7.3.1", | ||
"@wordpress/i18n": "^3.2.0", | ||
"@wordpress/url": "^2.4.0" | ||
}, | ||
@@ -34,3 +34,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "c59ef56fe16bdcc1fffd70b6e8a2fda4bf9c28fe" | ||
"gitHead": "80d228669adadb8dfcd24b8421517fed3be2d474" | ||
} |
@@ -79,2 +79,4 @@ # API Fetch | ||
The function returned by `createNonceMiddleware` includes a `nonce` property corresponding to the actively used nonce. You may also assign to this property if you have a fresh nonce value to use. | ||
**Root URL middleware** | ||
@@ -89,2 +91,25 @@ | ||
### Custom fetch handler | ||
The `api-fetch` package uses `window.fetch` for making the requests but you can use a custom fetch handler by using the `setFetchHandler` method. The custom fetch handler will receive the `options` passed to the `apiFetch` calls. | ||
**Example** | ||
The example below uses a custom fetch handler for making all the requests with [`axios`](https://github.com/axios/axios). | ||
```js | ||
import apiFetch from '@wordpress/api-fetch'; | ||
import axios from 'axios'; | ||
apiFetch.setFetchHandler( ( options ) => { | ||
const { url, path, data, method } = options; | ||
return axios( { | ||
url: url || path, | ||
method, | ||
data, | ||
} ); | ||
} ); | ||
``` | ||
<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> |
163
src/index.js
@@ -41,102 +41,117 @@ /** | ||
const middlewares = []; | ||
const middlewares = [ | ||
userLocaleMiddleware, | ||
namespaceEndpointMiddleware, | ||
httpV1Middleware, | ||
fetchAllMiddleware, | ||
]; | ||
function registerMiddleware( middleware ) { | ||
middlewares.push( middleware ); | ||
middlewares.unshift( middleware ); | ||
} | ||
function apiFetch( options ) { | ||
const raw = ( nextOptions ) => { | ||
const { url, path, data, parse = true, ...remainingOptions } = nextOptions; | ||
let { body, headers } = nextOptions; | ||
const defaultFetchHandler = ( nextOptions ) => { | ||
const { url, path, data, parse = true, ...remainingOptions } = nextOptions; | ||
let { body, headers } = nextOptions; | ||
// Merge explicitly-provided headers with default values. | ||
headers = { ...DEFAULT_HEADERS, ...headers }; | ||
// Merge explicitly-provided headers with default values. | ||
headers = { ...DEFAULT_HEADERS, ...headers }; | ||
// The `data` property is a shorthand for sending a JSON body. | ||
if ( data ) { | ||
body = JSON.stringify( data ); | ||
headers[ 'Content-Type' ] = 'application/json'; | ||
// The `data` property is a shorthand for sending a JSON body. | ||
if ( data ) { | ||
body = JSON.stringify( data ); | ||
headers[ 'Content-Type' ] = 'application/json'; | ||
} | ||
const responsePromise = window.fetch( | ||
url || path, | ||
{ | ||
...DEFAULT_OPTIONS, | ||
...remainingOptions, | ||
body, | ||
headers, | ||
} | ||
); | ||
const checkStatus = ( response ) => { | ||
if ( response.status >= 200 && response.status < 300 ) { | ||
return response; | ||
} | ||
const responsePromise = window.fetch( | ||
url || path, | ||
{ | ||
...DEFAULT_OPTIONS, | ||
...remainingOptions, | ||
body, | ||
headers, | ||
throw response; | ||
}; | ||
const parseResponse = ( response ) => { | ||
if ( parse ) { | ||
if ( response.status === 204 ) { | ||
return null; | ||
} | ||
); | ||
const checkStatus = ( response ) => { | ||
if ( response.status >= 200 && response.status < 300 ) { | ||
return response; | ||
} | ||
throw response; | ||
}; | ||
return response.json ? response.json() : Promise.reject( response ); | ||
} | ||
const parseResponse = ( response ) => { | ||
if ( parse ) { | ||
if ( response.status === 204 ) { | ||
return null; | ||
} | ||
return response; | ||
}; | ||
return response.json ? response.json() : Promise.reject( response ); | ||
return responsePromise | ||
.then( checkStatus ) | ||
.then( parseResponse ) | ||
.catch( ( response ) => { | ||
if ( ! parse ) { | ||
throw response; | ||
} | ||
return response; | ||
}; | ||
const invalidJsonError = { | ||
code: 'invalid_json', | ||
message: __( 'The response is not a valid JSON response.' ), | ||
}; | ||
return responsePromise | ||
.then( checkStatus ) | ||
.then( parseResponse ) | ||
.catch( ( response ) => { | ||
if ( ! parse ) { | ||
throw response; | ||
} | ||
if ( ! response || ! response.json ) { | ||
throw invalidJsonError; | ||
} | ||
const invalidJsonError = { | ||
code: 'invalid_json', | ||
message: __( 'The response is not a valid JSON response.' ), | ||
}; | ||
if ( ! response || ! response.json ) { | ||
return response.json() | ||
.catch( () => { | ||
throw invalidJsonError; | ||
} | ||
} ) | ||
.then( ( error ) => { | ||
const unknownError = { | ||
code: 'unknown_error', | ||
message: __( 'An unknown error occurred.' ), | ||
}; | ||
return response.json() | ||
.catch( () => { | ||
throw invalidJsonError; | ||
} ) | ||
.then( ( error ) => { | ||
const unknownError = { | ||
code: 'unknown_error', | ||
message: __( 'An unknown error occurred.' ), | ||
}; | ||
throw error || unknownError; | ||
} ); | ||
} ); | ||
}; | ||
throw error || unknownError; | ||
} ); | ||
} ); | ||
}; | ||
let fetchHandler = defaultFetchHandler; | ||
const steps = [ | ||
raw, | ||
fetchAllMiddleware, | ||
httpV1Middleware, | ||
namespaceEndpointMiddleware, | ||
userLocaleMiddleware, | ||
...middlewares, | ||
].reverse(); | ||
/** | ||
* Defines a custom fetch handler for making the requests that will override | ||
* the default one using window.fetch | ||
* | ||
* @param {Function} newFetchHandler The new fetch handler | ||
*/ | ||
function setFetchHandler( newFetchHandler ) { | ||
fetchHandler = newFetchHandler; | ||
} | ||
const runMiddleware = ( index ) => ( nextOptions ) => { | ||
const nextMiddleware = steps[ index ]; | ||
const next = runMiddleware( index + 1 ); | ||
return nextMiddleware( nextOptions, next ); | ||
function apiFetch( options ) { | ||
const steps = [ ...middlewares, fetchHandler ]; | ||
const createRunStep = ( index ) => ( workingOptions ) => { | ||
const step = steps[ index ]; | ||
if ( index === steps.length - 1 ) { | ||
return step( workingOptions ); | ||
} | ||
const next = createRunStep( index + 1 ); | ||
return step( workingOptions, next ); | ||
}; | ||
return runMiddleware( 0 )( options ); | ||
return createRunStep( 0 )( options ); | ||
} | ||
apiFetch.use = registerMiddleware; | ||
apiFetch.setFetchHandler = setFetchHandler; | ||
@@ -143,0 +158,0 @@ apiFetch.createNonceMiddleware = createNonceMiddleware; |
@@ -1,50 +0,27 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { addAction } from '@wordpress/hooks'; | ||
function createNonceMiddleware( nonce ) { | ||
function middleware( options, next ) { | ||
const { headers = {} } = options; | ||
const createNonceMiddleware = ( nonce ) => { | ||
let usedNonce = nonce; | ||
/** | ||
* This is not ideal but it's fine for now. | ||
* | ||
* Configure heartbeat to refresh the wp-api nonce, keeping the editor | ||
* authorization intact. | ||
*/ | ||
addAction( 'heartbeat.tick', 'core/api-fetch/create-nonce-middleware', ( response ) => { | ||
if ( response[ 'rest-nonce' ] ) { | ||
usedNonce = response[ 'rest-nonce' ]; | ||
} | ||
} ); | ||
return function( options, next ) { | ||
let headers = options.headers || {}; | ||
// If an 'X-WP-Nonce' header (or any case-insensitive variation | ||
// thereof) was specified, no need to add a nonce header. | ||
let addNonceHeader = true; | ||
for ( const headerName in headers ) { | ||
if ( headers.hasOwnProperty( headerName ) ) { | ||
if ( headerName.toLowerCase() === 'x-wp-nonce' ) { | ||
addNonceHeader = false; | ||
break; | ||
} | ||
if ( headerName.toLowerCase() === 'x-wp-nonce' ) { | ||
return next( options ); | ||
} | ||
} | ||
if ( addNonceHeader ) { | ||
// Do not mutate the original headers object, if any. | ||
headers = { | ||
...headers, | ||
'X-WP-Nonce': usedNonce, | ||
}; | ||
} | ||
return next( { | ||
...options, | ||
headers, | ||
headers: { | ||
...headers, | ||
'X-WP-Nonce': middleware.nonce, | ||
}, | ||
} ); | ||
}; | ||
}; | ||
} | ||
middleware.nonce = nonce; | ||
return middleware; | ||
} | ||
export default createNonceMiddleware; |
@@ -34,2 +34,3 @@ /** | ||
const callback = ( options ) => { | ||
expect( options ).toBe( requestOptions ); | ||
expect( options.headers[ 'X-WP-Nonce' ] ).toBe( 'existing nonce' ); | ||
@@ -36,0 +37,0 @@ }; |
@@ -186,2 +186,36 @@ /** | ||
} ); | ||
it( 'should not use the default fetch handler when using a custom fetch handler', () => { | ||
const customFetchHandler = jest.fn(); | ||
apiFetch.setFetchHandler( customFetchHandler ); | ||
apiFetch( { path: '/random' } ); | ||
expect( window.fetch ).not.toHaveBeenCalled(); | ||
expect( customFetchHandler ).toHaveBeenCalledWith( { | ||
path: '/random?_locale=user', | ||
} ); | ||
} ); | ||
it( 'should run the last-registered user-defined middleware first', () => { | ||
// This could potentially impact other tests in that a lingering | ||
// middleware is left. For the purposes of this test, it is sufficient | ||
// to ensure that the last-registered middleware receives the original | ||
// options object. It also assumes that some built-in middleware would | ||
// either mutate or clone the original options if the extra middleware | ||
// had been pushed to the stack. | ||
expect.assertions( 1 ); | ||
const expectedOptions = {}; | ||
apiFetch.use( ( actualOptions, next ) => { | ||
expect( actualOptions ).toBe( expectedOptions ); | ||
return next( actualOptions ); | ||
} ); | ||
apiFetch( expectedOptions ); | ||
} ); | ||
} ); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
135388
3
1756
114
- Removed@wordpress/hooks@^2.0.5
Updated@babel/runtime@^7.3.1
Updated@wordpress/i18n@^3.2.0
Updated@wordpress/url@^2.4.0