Blog | G5 Cyber Security

HTTPS Request Duplication: Prevention & Detection

TL;DR

Yes, an HTTPS request can be sent twice (or more) under certain conditions. This usually happens due to network issues or client-side retries. While the server should handle duplicate requests gracefully (idempotency is key), it’s important to understand how this can occur and implement safeguards.

Why Requests Get Sent Twice

Several scenarios can lead to an HTTPS request being sent multiple times:

How to Prevent Duplicate Requests

  1. Idempotency: Design your API endpoints to be idempotent. This means that making the same request multiple times has the same effect as making it once. GET, HEAD, PUT and DELETE are naturally idempotent. For POST requests (which aren’t), use a unique identifier for each operation.
  2. Client-Side Prevention:
    • Disable Submit Button After Click: Prevent the user from clicking the submit button multiple times by disabling it after the first click.
    • Use JavaScript to Track Submissions: Use JavaScript to track whether a form has been submitted and prevent further submissions until you receive a response from the server.
  3. Server-Side Detection & Handling: Implement logic on your server to detect and handle duplicate requests.
    • Unique Request IDs: Generate a unique ID for each request (e.g., using a UUID) and include it in the request headers or body. Store these IDs (temporarily) on the server. If you receive a request with an already-seen ID, reject it or ignore it.
    • Token-Based Prevention: Use anti-CSRF tokens to prevent duplicate form submissions. These are commonly used for security but can also help with duplication.

Detecting Duplicate Requests (Example – Python)

Here’s a simple example of how you might detect duplicate requests using a unique request ID in Python with Flask:

from flask import Flask, request, jsonify
import uuid

app = Flask(__name__)

seen_request_ids = set()

@app.route('/my-endpoint', methods=['POST'])
def my_endpoint():
    request_id = request.headers.get('X-Request-ID')
    if not request_id:
        request_id = str(uuid.uuid4())

    if request_id in seen_request_ids:
        return jsonify({'message': 'Duplicate request'}), 409

    seen_request_ids.add(request_id)

    # Process the request here...
    print('Processing request with ID:', request_id)

    return jsonify({'message': 'Request processed successfully'}), 200

if __name__ == '__main__':
    app.run(debug=True)

In this example:

Important Considerations

Exit mobile version