Συμβόλαια HTTP, χρονικά όρια και ασφαλείς επαναλήψεις — DedSec Project
Επαναλήψεις HTTP — περιορισμένες προσπάθειες και έλεγχος απάντησης Πρόβλημα και κανόνες αποδοχής Μία εφαρμογή που λειτουργεί και χωρίς διαδίκτυο συγχρονίζει έναν κατάλογο όταν υπάρχει…
Επαναλήψεις HTTP — περιορισμένες προσπάθειες και έλεγχος απάντησης
Πρόβλημα και κανόνες αποδοχής
Μία εφαρμογή που λειτουργεί και χωρίς διαδίκτυο συγχρονίζει έναν κατάλογο όταν υπάρχει δίκτυο. Η επανάληψη ενός GET μετά από προσωρινό 429 ή 503 μπορεί να είναι αποδεκτή, αλλά η τυφλή επανάληψη POST που δημιουργεί αγορά ή λογαριασμό μπορεί να προκαλέσει διπλή πράξη. Το παράδειγμα δέχεται τη μεταφορά ως παράμετρο, ώστε οι δοκιμές να προσομοιώνουν κωδικούς HTTP χωρίς πραγματικά αιτήματα. Οι διαδρομές περιορίζονται σε γνωστά σχετικά API, ο αριθμός προσπαθειών έχει ανώτατο όριο και το περιεχόμενο ελέγχεται ακόμη και όταν ο HTTP κωδικός είναι 200.
Εκτελέσιμο εργαστήριο Python 3
Αποθήκευσε ως retry_lab.py και εκτέλεσε python3 retry_lab.py. Οι τεχνητές απαντήσεις επιστρέφουν 503, έπειτα 429 και τέλος 200. Άλλες δοκιμές απορρίπτουν σφάλματα εξουσιοδότησης, εξαντλημένο όριο επαναλήψεων, άκυρη δομή απάντησης και επικίνδυνες διαδρομές.
import re
def fetch_json(send, path, attempts=3):
if not re.fullmatch(r'/api/[a-z-]{1,30}', path):
raise ValueError('invalid API path')
if type(attempts) is not int or not 1 <= attempts <= 5:
raise ValueError('invalid retry budget')
for number in range(1, attempts + 1):
status, value = send('GET', path)
if status == 200:
if not isinstance(value, dict) or not isinstance(value.get('items'), list):
raise ValueError('invalid response schema')
return value['items']
if status not in (429, 503) or number == attempts:
raise RuntimeError(f'HTTP {status} after {number} attempt(s)')
raise AssertionError('unreachable')
def transport(statuses):
received = iter(statuses)
calls = []
def send(method, path):
calls.append((method, path))
return next(received)
return send, calls
send, calls = transport([(503, None), (429, None), (200, {'items': [1, 2]})])
assert fetch_json(send, '/api/items') == [1, 2] and len(calls) == 3
for statuses in ([(401, None)], [(503, None)] * 3, [(200, {'item': 1})]):
send, calls = transport(statuses)
try: fetch_json(send, '/api/items')
except (ValueError, RuntimeError): pass
else: raise AssertionError('bad response accepted')
for path in ('https://example.com/', '/api/../admin', '/api/items?token=secret'):
try: fetch_json(lambda *_: None, path)
except ValueError: pass
else: raise AssertionError('bad path accepted')
print('PASS HTTP: retry budget, auth stop, schema, path validation')
Ερμηνεία και όρια εφαρμογής
Η μεταφορά καλείται μόνο με GET και με αυστηρά ελεγμένη σχετική διαδρομή. Σφάλματα αυθεντικοποίησης όπως το 401 τερματίζουν αμέσως. Οι προσωρινές απαντήσεις 429 και 503 επαναλαμβάνονται μέχρι το επιτρεπόμενο πλήθος. Ακόμη και στο 200, η συνάρτηση επιβεβαιώνει ότι το items είναι λίστα· ανεξέλεγκτο περιεχόμενο μπορεί να χαλάσει την εμφάνιση. Η συγκεκριμένη δοκιμή δεν περιμένει ανάμεσα στις προσπάθειες, για να είναι επαναλήψιμη. Ο πραγματικός πελάτης χρειάζεται εκθετική αναμονή με ανώτατο όριο και μικρή τυχαιότητα, έγκυρο χειρισμό Retry-After, χρονικά όρια σύνδεσης/ανάγνωσης και ανώτατο συνολικό χρόνο. Πρέπει επίσης να χειρίζεται εξαιρέσεις μεταφοράς και ακύρωση, χωρίς καταγραφή κρυφών tokens ή ιδιωτικών απαντήσεων.
Δοκιμές αστοχιών με σαφείς κανόνες
- Πρόσθεσε απαντήσεις 400, 403, 500 και κακοσχηματισμένο 200. Κατέγραψε ποιες αξίζουν επανάληψη και ποιες όχι.
- Πρόσθεσε προσομοιωτή αναμονής ως παράμετρο και επαλήθευσε ότι η καθυστέρηση αυξάνεται χωρίς να ξεπερνά το όριο.
- Προκάλεσε εξαίρεση δικτύου πριν την απάντηση. Αποφάσισε ποιες αποτυχίες GET είναι ασφαλές να επαναληφθούν και πόσες προσπάθειες καταναλώνουν.
- Σχεδίασε ξεχωριστό POST με κλειδί αποφυγής διπλών πράξεων. Εξήγησε γιατί το κλειδί του πελάτη δεν αρκεί αν ο διακομιστής δεν το τηρεί.
Παραδοτέα: PASS, πίνακας κωδικών και προσπαθειών, ασφαλή διαγνωστικά χωρίς μυστικά και τεκμηριωμένη πολιτική χρονικών ορίων.
Πρόσθετη τεχνική ανάλυση
Το πλήθος επαναλήψεων δεν περιορίζει μόνο του την αναμονή. Μοίρασε μία μονοτονική προθεσμία σε προσπάθειες και καθυστερήσεις και εξέτασε αν ο HTTP client περιορίζει χωριστά σύνδεση και ανάγνωση. Το συνολικό όριο έχει ιδιαίτερη αξία σε κινητά όπου οι επανασυνδέσεις καταναλώνουν τον διαθέσιμο χρόνο αλληλεπίδρασης.