سپورٹ ٹکٹ کی ایک API درخواست (request) کی ساخت کو چیک کیے بغیر {"title": 7, "description": "<very large text>", "email": "alice@example.com"} کو قبول کر لیتی ہے۔ بعد میں فارمیٹنگ کا مرحلہ عددی عنوان (numeric title) کی وجہ سے کریش ہو جاتا ہے، جبکہ ایرر ہینڈلر (error handler) جمع کرائی گئی تفصیل اور ای میل کو ریکارڈ کر لیتا ہے۔ حملہ آور کو کسی اکاؤنٹ یا ایکسپلائٹ چین (exploit chain) کی ضرورت نہیں تھی، صرف ایک ایسی درخواست درکار تھی جو API کی حدود کو ایسے ڈیٹا کے ساتھ عبور کر جائے جسے سروس قابلِ اعتماد سمجھتی ہو۔ ہمارا سوال یہ ہے کہ سروس کو ناقص ساخت (malformed)، حد سے بڑے سائز، اور غیر متوقع ان پٹ کو کہاں مسترد کرنا چاہیے اس سے پہلے کہ وہ بزنس لاجک یا لاگز (logs) تک پہنچے۔
اس کورس کے دوران ہم ایک ہی FastAPI سروس استعمال کریں گے۔ POST /tickets ایک نیا ٹکٹ قبول کرتی ہے، GET /tickets/{id} اسے پڑھتی ہے، POST /login صارف کی تصدیق (authenticate) کرتی ہے، اور GET /me تصدیق شدہ صارف کی معلومات واپس کرتی ہے۔ ہر اینڈ پوائنٹ (endpoint) ایسا ڈیٹا وصول کرتا ہے جو کلائنٹ کے کنٹرول میں ہوتا ہے، چاہے کلائنٹ آج ایک قابلِ اعتماد براؤزر ہی کیوں نہ ہو؛ لہذا ہر اینڈ پوائنٹ کو موصول ہونے والے ان پٹ اور اندرونی حالت (internal state) کے درمیان ایک واضح حد (boundary) کی ضرورت ہوتی ہے۔
ان پٹ کی تصدیق وہ حد بندی کا اصول ہے جو صرف اس ڈیٹا کو قبول کرتا ہے جو سروس کے معاہدے (contract) کے مطابق ہو۔ POST /tickets کے لیے، ایک درست درخواست میں مختصر متن پر مبنی عنوان، محدود طوالت کی تفصیل، اور مطلوبہ فارمیٹ میں ای میل شامل ہوتی ہے۔ ناقص ساخت والا JSON اس سے بھی پہلے ناکام ہو جاتا ہے کیونکہ فریم ورک غلط نحو (syntax) سے درخواست کی باڈی (request body) تشکیل نہیں دے سکتا۔ اس کا مفید نتیجہ صرف ‘ایکسپشنز’ (exceptions) میں کمی نہیں ہے۔ مسترد شدہ ان پٹ کبھی بھی ٹکٹ اسٹوریج، ریسپانس رینڈرنگ، یا تشخیصی لاگز (diagnostic logs) تک نہیں پہنچتا جو ذاتی ڈیٹا کو ظاہر کر سکتے ہیں۔
سروس میں تین ایسی حدود (boundaries) ہیں جنہیں تعمیر کے دوران پیشِ نظر رکھنا ضروری ہے: درخواست کی پارسنگ (parsing)، POST /login پر تصدیق (authentication)، اور ریسپانس رینڈرنگ۔ پہلی حد ہمارا نقطہ آغاز ہے کیونکہ ہر غیر تصدیق شدہ درخواست اسی تک پہنچتی ہے۔ آئیے سروس کے اندر کنٹرول شدہ فیلڈز (fields) کے سفر کا جائزہ لیں:
یہ خاکہ ظاہر کرتا ہے کہ title، description اور email سروس کے بیرونی حصے سے آتے ہیں، جبکہ ان-میموری (in-memory) ریپوزٹری کو صرف وہی ڈیٹا موصول ہوتا ہے جو ‘ریکوئسٹ باؤنڈری’ (request boundary) کو عبور کر چکا ہو۔
چونکہ یہ خاکہ کلائنٹ کے ڈیٹا کو ریپوزٹری کے ڈیٹا سے الگ کرتا ہے، اس لیے POST /tickets کو ایسے اصولوں کی ضرورت ہے جن پر ہینڈلر (handler) انحصار کر سکے، بجائے اس کے کہ وہ بعد کے کوڈ میں بکھرے ہوئے مفروضوں پر انحصار کرے۔ یہ کنٹریکٹ مجاز فیلڈز، ان کی اقسام اور حدود کا تعین کرتا ہے۔ مثال کے طور پر، ٹائٹل میں 1 سے 120 تک کیریکٹرز کی اجازت ہو سکتی ہے، جبکہ تفصیل (description) میں 4,000 تک کی گنجائش ہو سکتی ہے۔ حدود (limits) دراصل حفاظتی اقدامات ہیں کیونکہ یہ اسٹوریج، پروسیسنگ، لاگ کے حجم اور ریسپانس کے سائز کو محدود رکھتی ہیں، تاکہ کوئی حملہ آور ان میں غیر معمولی اضافہ نہ کر سکے۔
جب سروس کو کسی ڈیٹا کی ایک معیاری شکل (canonical form) درکار ہو تو ‘نارملائزیشن’ (normalization) کا عمل بھی اسی باؤنڈری کے اندر ہونا چاہیے۔ ہم ٹائٹل کو محفوظ کرنے سے پہلے اس کے اطراف کی اضافی خالی جگہ (whitespace) کو ہٹا سکتے ہیں، لیکن ہمیں کسی غلط ای میل کو خاموشی سے درست نہیں کرنا چاہیے اور نہ ہی بہت طویل تفصیل کو خودکار طریقے سے کاٹنا (truncate) چاہیے۔ درستگی کی کوشش کلائنٹ کے اصل مقصد کو تبدیل کر سکتی ہے؛ جبکہ درخواست کو مسترد کرنے سے کنٹریکٹ کی شرائط واضح رہتی ہیں۔ Pydantic کے فیلڈ ویلیڈیٹرز قبول شدہ اقدار کو تبدیل کر سکتے ہیں، لیکن انہیں حتمی نتیجہ واپس کرنا چاہیے، اور جن اصولوں کو ‘را’ (raw) ان پٹ درکار ہو، انہیں ہر قسم کے ان پٹ کو مدنظر رکھنا چاہیے۔
جب email کی جگہ not-an-email (یعنی غلط فارمیٹ والی ای میل) ہو تو POST /tickets کو کیا جواب دینا چاہیے؟ ہینڈلر کو ٹکٹ 42 نہیں بنانا چاہیے، اور کلائنٹ کو اندرونی ‘ٹریس بیک’ (traceback) کے بجائے غلطی (error) کی ایک مستقل اور واضح شکل درکار ہوتی ہے۔ ذیل میں دیا گیا ریکوئسٹ ماڈل محدود فیلڈز کا اطلاق کرتا ہے اور مسترد شدہ فیلڈ کا ریکارڈ تو رکھتا ہے لیکن خود مسترد شدہ ای میل کو محفوظ نہیں کرتا: