=== WP REST API Idempotent Requests === Contributors: TimothyBlynJacobs Tags: rest-api Requires at least: 4.7 Tested up to: 4.8 Stable tag: 1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Allow REST API clients to safely retry requests in case of network errors without risk of the request being processed twice. == Description == When a network error is encountered, API clients should be able to retry a request without a risk of their request being processed twice. WP API Idempotence adds support for clients to include an idempotency key that uniquely identifies that request. If the server detects that a request with the same key has already been processed or is currently being processed, the response for the initial request will be returned. For Example: ` { "title": "My Important Post", "content": "This will only go out once!", "status": "draft", "idempotency_key": "1ced64e9-9537-4b7b-9919-444d9e15e201" } ` = Configuration = * Idempotency key can either be passed in the request header or the request body. * The idempotency key name can be customized. * Change the HTTP methods the idempotency key is supported for. Defaults to `POST`, `PUT`, `PATCH`. A sample request interface is included to demonstrate the selected configuration. = Developers = The plugin includes two actions to modify the dependency injection container (DIC) and insert custom services. The `wp_api_idempotence_initialize_container_builder` action allows you to modify the Dependency Injection builder itself and the `wp_api_idempotence_initialize_container` action allows you to override dependencies. For example: ` add_action( 'wp_api_idempotence_initialize_container', function( $container ) { $container->set( '_dataStore', DI\object( 'YourName\CustomDataStore' ) ); } ); ` Under the hood, the plugin is made up of a `DataStore`, `RequestHasher`, `ResponseSerializer` and `RequestPoller`. The `DataStore` is primarily responsible for retrieving or storing an idempotent request. By default, requests are stored in a custom database table. This could be substituted for a custom driver by implementing the `DataStore` interface. For example a Redis server. The `RequestHasher` produces a unique hash for a `WP_REST_Request` object. This hash is based off of the contents of the request, not for the object via `spl_object_hash` or similar. This can also be substituted by implementing the `RequestHasher` interface. The `ResponseSerializer` converts a `WP_REST_Response` or `WP_Error` object back and forth from a string representation. The default JSON serializer supports filtering the serialization process using the `wp_api_idempotence_serialized_response_data` and `wp_api_idempotence_attach_serialized_response_data` filters. See `src/ResponseSerializer/Filtered.php`. The entire serializer can be substituted by implementing the `ResponseSerializer` interface. Finally, the `RequestPoller` class polls the data store for a response if it is determined that an idempotent request is currently being processed when another request with the same key arrives. By default, the data store is polled every seconds a maximum of 15 times to try and retrieve a response object. If no response is found, an error with code `rest_duplicate_idempotency_key` will be returned. This can be adjusted by overwriting the `poll.sleepSeconds` and `poll.maxQueries` in the DIC. The `RequestPoller` can also be entirely subsituted by implementing the `RequestPoller` interface. = Contributing = This plugin is hosted on [GitHub](https://github.com/iron-bound-designs/wp-api-idempotence). Issues and pull requests are welcomed. == Installation == 1. Upload the plugin files to the `/wp-content/plugins/wp-api-idempotence` directory, or install the plugin through the WordPress plugins screen directly. 2. Activate the plugin through the 'Plugins' screen in WordPress 3. Use the Settings -> WP API Idempotence screen to modify the idempotency key location or name 4. Ensure the plugin is working by using the "Sample Requests" section. == Changelog == = 1.0 = * Initial version.