{"id":66378,"date":"2017-04-09T05:22:31","date_gmt":"2017-04-09T05:22:31","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wp-rest-api-idempotence\/"},"modified":"2017-04-09T05:22:31","modified_gmt":"2017-04-09T05:22:31","slug":"wp-rest-api-idempotence","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/wp-rest-api-idempotence\/","author":9545473,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0","stable_tag":"1.0","tested":"4.8.28","requires":"4.7","requires_php":"","requires_plugins":"","header_name":"WP REST API - Idempotence","header_author":"Timothy B Jacobs","header_description":"Allow API clients to specify an idempotency key for API requests.","assets_banners_color":"","last_updated":"2017-04-09 05:22:31","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/timothybjacobs.com\/wp-api-idempotence\/","header_author_uri":"https:\/\/timothybjacobs.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":2162,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","changelog","faq"],"tags":[],"upgrade_notice":[],"ratings":{"1":0,"2":0,"3":0,"4":0,"5":0},"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[23853],"plugin_category":[],"plugin_contributors":[89997],"plugin_business_model":[],"class_list":["post-66378","plugin","type-plugin","status-publish","hentry","plugin_tags-rest-api","plugin_contributors-timothyblynjacobs","plugin_committers-timothyblynjacobs"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/wp-rest-api-idempotence.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>When a network error is encountered, API clients should be able to retry a request without a risk of their request being processed twice.\nWP API Idempotence adds support for clients to include an idempotency key that uniquely identifies that request. If the server detects\nthat a request with the same key has already been processed or is currently being processed, the response for the initial request will\nbe returned.<\/p>\n\n<p>For Example:<\/p>\n\n<pre><code>{\n    \"title\": \"My Important Post\",\n    \"content\": \"This will only go out once!\",\n    \"status\": \"draft\",\n    \"idempotency_key\": \"1ced64e9-9537-4b7b-9919-444d9e15e201\"\n}\n<\/code><\/pre>\n\n<h4>Configuration<\/h4>\n\n<ul>\n<li>Idempotency key can either be passed in the request header or the request body.<\/li>\n<li>The idempotency key name can be customized.<\/li>\n<li>Change the HTTP methods the idempotency key is supported for. Defaults to <code>POST<\/code>, <code>PUT<\/code>, <code>PATCH<\/code>.<\/li>\n<\/ul>\n\n<p>A sample request interface is included to demonstrate the selected configuration.<\/p>\n\n<h4>Developers<\/h4>\n\n<p>The plugin includes two actions to modify the dependency injection container (DIC) and insert custom services.<\/p>\n\n<p>The <code>wp_api_idempotence_initialize_container_builder<\/code> action allows you to modify the Dependency Injection builder itself and\nthe <code>wp_api_idempotence_initialize_container<\/code> action allows you to override dependencies. For example:<\/p>\n\n<pre><code>add_action( 'wp_api_idempotence_initialize_container', function( $container ) {\n    $container-&gt;set( '_dataStore', DI\\object( 'YourName\\CustomDataStore' ) );\n} );\n<\/code><\/pre>\n\n<p>Under the hood, the plugin is made up of a <code>DataStore<\/code>, <code>RequestHasher<\/code>, <code>ResponseSerializer<\/code> and <code>RequestPoller<\/code>.<\/p>\n\n<p>The <code>DataStore<\/code> is primarily responsible for retrieving or storing an idempotent request. By default, requests\nare stored in a custom database table. This could be substituted for a custom driver by implementing the <code>DataStore<\/code>\ninterface. For example a Redis server.<\/p>\n\n<p>The <code>RequestHasher<\/code> produces a unique hash for a <code>WP_REST_Request<\/code> object. This hash is based off of the contents of\nthe request, not for the object via <code>spl_object_hash<\/code> or similar. This can also be substituted by implementing the\n    RequestHasher interface.<\/p>\n\n<p>The <code>ResponseSerializer<\/code> converts a <code>WP_REST_Response<\/code> or <code>WP_Error<\/code> object back and forth from a string representation.\nThe default JSON serializer supports filtering the serialization process using the <code>wp_api_idempotence_serialized_response_data<\/code>\nand <code>wp_api_idempotence_attach_serialized_response_data<\/code> filters. See <code>src\/ResponseSerializer\/Filtered.php<\/code>.\nThe entire serializer can be substituted by implementing the <code>ResponseSerializer<\/code> interface.<\/p>\n\n<p>Finally, the <code>RequestPoller<\/code> class polls the data store for a response if it is determined that an idempotent request\nis currently being processed when another request with the same key arrives. By default, the data store is polled\nevery seconds a maximum of 15 times to try and retrieve a response object. If no response is found, an error with code\n    rest_duplicate_idempotency_key will be returned. This can be adjusted by overwriting the <code>poll.sleepSeconds<\/code> and\n    poll.maxQueries in the DIC. The <code>RequestPoller<\/code> can also be entirely subsituted by implementing the <code>RequestPoller<\/code>\ninterface.<\/p>\n\n<h4>Contributing<\/h4>\n\n<p>This plugin is hosted on <a href=\"https:\/\/github.com\/iron-bound-designs\/wp-api-idempotence\">GitHub<\/a>. Issues and pull requests are welcomed.<\/p>\n\n<!--section=changelog-->\n<h4>1.0<\/h4>\n\n<ul>\n<li>Initial version.<\/li>\n<\/ul>\n\n<!--section=faq-->\n<dl>\n<dt>Installation Instructions<\/dt>\n<dd><ol>\n<li>Upload the plugin files to the <code>\/wp-content\/plugins\/wp-api-idempotence<\/code> directory, or install the plugin through the WordPress plugins screen directly.<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress<\/li>\n<li>Use the Settings -&gt; WP API Idempotence screen to modify the idempotency key location or name<\/li>\n<li>Ensure the plugin is working by using the \"Sample Requests\" section.<\/li>\n<\/ol><\/dd>\n\n<\/dl>","raw_excerpt":"Allow REST API clients to safely retry requests in case of network errors without risk of the request being processed twice.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/66378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=66378"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/timothyblynjacobs"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=66378"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=66378"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=66378"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=66378"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=66378"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=66378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}