PYTHON
Ensuring Idempotency for API Requests with a Unique Key
Learn to implement idempotency for your API endpoints using a unique request key, preventing duplicate processing of requests even when clients retry.
from flask import Flask, request, jsonify, g
import uuid
import time
app = Flask(__name__)
# In a real application, this would be a persistent store (e.g., Redis, database)
# Storing (idempotency_key -> response_data) for a short period
idempotency_store = {}
IDEMPOTENCY_EXPIRY_SECONDS = 3600 # 1 hour
def get_idempotent_response(idempotency_key):
record = idempotency_store.get(idempotency_key)
if record and (time.time() - record['timestamp'] < IDEMPOTENCY_EXPIRY_SECONDS):
return record['response']
return None
def store_idempotent_response(idempotency_key, response_data):
idempotency_store[idempotency_key] = {
'timestamp': time.time(),
'response': response_data
}
@app.route('/create_resource', methods=['POST'])
def create_resource():
idempotency_key = request.headers.get('X-Idempotency-Key')
if not idempotency_key:
return jsonify({"error": "X-Idempotency-Key header is required"}), 400
# 1. Check if this request has been processed recently
cached_response = get_idempotent_response(idempotency_key)
if cached_response:
print(f"Returning cached response for idempotency key: {idempotency_key}")
return jsonify(cached_response)
# 2. Process the request (simulate creation)
try:
data = request.get_json()
if not data or 'name' not in data:
return jsonify({"error": "Name is required"}), 400
# Simulate database operation
new_resource_id = str(uuid.uuid4())
resource_data = {"id": new_resource_id, "name": data['name'], "status": "created"}
print(f"Resource created: {resource_data}")
# 3. Store the successful response
store_idempotent_response(idempotency_key, resource_data)
return jsonify(resource_data), 201
except Exception as e:
# Handle potential errors during processing, don't cache errors for idempotency
return jsonify({"error": str(e)}), 500
# if __name__ == '__main__':
# app.run(debug=True)
How it works: This Python Flask snippet illustrates how to implement idempotency for API endpoints, particularly for mutation operations like creating resources. Clients send a unique `X-Idempotency-Key` header with their request. The server first checks if a response for that key is already cached. If so, it returns the cached response, preventing duplicate processing. If not, it proceeds to process the request (e.g., create a resource) and then stores the successful response with the idempotency key before sending it back. This ensures that even if a client retries a request due to network issues, the operation is performed only once.