از مرورگر تا سرور؛ قرارداد HTTP، نشانی و پاسخ JSON
در این درس ۵ بخش
برای فهمیدن برنامهنویسی سمت سرور، ابتدا مسیر یک درخواست را دنبال کنیم. دانشجو در صفحهٔ «کارهای من» دکمهٔ تازهسازی را میزند؛ کد رابط یک درخواست به API میفرستد، برنامهٔ Node.js درخواست را بررسی میکند و دادهٔ مناسب را برمیگرداند. اگر ذخیرهٔ ماندگار لازم باشد، برنامه با پایگاه داده کار میکند. مرورگر نباید رمز اتصال پایگاه داده را داشته باشد. در تمرینهای این دوره، سرور روی رایانهٔ خودتان اجرا میشود؛ هنوز ماشین جداگانه یا خرید VPS لازم ندارید.
نقشها را پیش از انتخاب ابزار مشخص کنید
رابط کاربر مسئول نمایش، گرفتن ورودی و کمک به اصلاح خطاست. سرور مسئول اجرای قوانین قابل اعتماد است؛ مثلاً آیا این کار متعلق به همین حساب است و عنوان آن مجاز است؟ پایگاه داده مسئول نگهداری و بازیابی ماندگار داده در قرارداد خودش است. بررسی طول عنوان در فرم، تجربهٔ کاربری را بهتر میکند؛ همان بررسی در سرور نیز باید مستقل اجرا شود. کاربر میتواند درخواست را بدون فرم و با یک ابزار خط فرمان بفرستد. پنهانبودن دکمه، مجوز دسترسی ایجاد نمیکند.
API قراردادی برای تعامل برنامههاست. HTTP یکی از راههای پیادهسازی این تعامل است، نه تعریف همهٔ APIها. در این دوره از HTTP و JSON استفاده میکنیم تا روش، مسیر، وضعیت و داده را جدا ببینید. چارچوبی مانند Express بخشهایی از کار را آسان میکند، ولی مفاهیم درخواست، پاسخ و اعتماد به ورودی همچنان باقی میمانند. ابتدا توانایی توضیح این قرارداد را بسازید، سپس چارچوب انتخاب کنید.
یک درخواست را به اجزایش بشکنید
GET /tasks?done=false HTTP/1.1
Host: 127.0.0.1:3100
Accept: application/jsonاین نمونه، شکل خوانای یک درخواست HTTP/1.1 است و دستور PowerShell نیست. GET روش درخواست، /tasks مسیر و done=false پارامتر جستوجوست. هدر Accept میگوید کلاینت چه نوع پاسخی میپسندد؛ سرور هنوز باید نوع واقعی پاسخ را اعلام کند. در قرارداد فرضی ما، GET فقط گزارش میگیرد و تغییری در کارها نمیدهد. برای ساخت کار تازه از POST استفاده خواهیم کرد. نوشتن یک عملیات حذف پشت GET میتواند با رفتار مرورگر، پیشخوانی یا ابزارهای واسط ناسازگار شود.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"items":[],"count":0}وضعیت ۲۰۰ میگوید درخواست در این سناریو موفق بوده است؛ آرایهٔ خالی نیز پاسخ معتبر است. JSON متن ساختیافته است، نه شیء زندهٔ جاوااسکریپت: کلیدهای متنی در آن با کوتیشن دوتایی نوشته میشوند و تابع یا undefined ندارد. پس از تجزیهٔ JSON نیز باید شکل داده را بررسی کنید؛ معتبر بودن نحو، معتبر بودن مفهوم را ثابت نمیکند. مثلاً {"title":42} JSON درست است ولی قرارداد عنوان متنی را رعایت نمیکند.
localhost، پورت و مرز دستگاه
در نشانی http://127.0.0.1:3100/health، بخش http طرح ارتباط، 127.0.0.1 نشانی حلقهٔ محلی، 3100 پورت و /health مسیر است. localhost معمولاً به حلقهٔ محلی دستگاه اشاره میکند و ممکن است به IPv4 یا IPv6 نگاشت شود. برای کمکردن ابهام، مثالهای سرور ما صریحاً روی 127.0.0.1 گوش میدهند. اگر همین نشانی را در تلفن باز کنید، به تلفن اشاره میکند؛ قرار نیست خودکار به رایانهٔ ویندوزی متصل شود.
اجرای سرور یعنی یک فرایند زنده منتظر درخواست است. تا وقتی پنجرهٔ ترمینال مشغول اجرای آن است، برگشتن نشانگر خط فرمان را انتظار نداشته باشید. برای ارسال درخواست، ترمینال دوم باز کنید. بستن سرور یا زدن Ctrl+C در ترمینال مربوط، ادامهٔ پاسخگویی را متوقف میکند. صفحهٔ HTML ذخیرهشده روی دیسک، بهتنهایی چنین فرایندی نیست. این تفاوت در خطای «صفحه باز نمیشود» بسیار کمک میکند.
وضعیتها را به تصمیم بعدی وصل کنید
در پروژهٔ نهایی، ۲۰۰ برای خواندن موفق، ۲۰۱ برای ساخت موفق، ۴۰۰ برای JSON یا UTF-8 خراب، ۴۲۲ برای فیلد یا نوع نامعتبر، ۴۰۴ برای مسیر یا منبع پیدانشده و ۴۰۵ برای روش پشتیبانینشده به کار میرود. خطای داخلی غیرمنتظره معمولاً ۵۰۰ است. جزئیات هر API باید مستند باشد؛ صرفاً از نام وضعیت نتیجه نگیرید که کاربر وارد شده است. پاسخ ۲۰۰ به /health فقط زندهبودن همان مسیر را نشان میدهد و صحت کل سامانه، پایگاه داده یا مجوزها را تضمین نمیکند.
بدنهٔ خطا را نیز قابل پیشبینی طراحی کنید. برای نمونه، {"error":"title_required"} اجازه میدهد رابط، پیام فارسی مناسب نشان دهد. نمایش پشتهٔ خطای سرور در پاسخ عمومی، اطلاعات غیرضروری دربارهٔ مسیرها و پیادهسازی آشکار میکند. برای عیبیابی محلی، وضعیت، روش و مسیر را ثبت کنید؛ رمز، توکن و بدنهٔ حاوی اطلاعات شخصی را وارد گزارش عمومی نکنید. در درسهای بعد فرق خطای شبکه و پاسخ HTTP ناموفق را آزمایش میکنیم.
تمرین و پاسخ تشریحی
برای یک کتابخانهٔ فرضی، قرارداد «گرفتن فهرست کتابها» و «افزودن کتاب» را روی کاغذ بنویسید: روش، مسیر، ورودی لازم، وضعیت موفق و یک وضعیت خطا. سپس توضیح دهید چرا آدرس 127.0.0.1 در تلفن، آدرس رایانهٔ شما نیست. هدف این تمرین طراحی پایگاه داده یا ساخت حساب واقعی نیست؛ باید بتوانید یک تعامل ساده را بدون وابستگی به نام نرمافزار توضیح دهید.
پاسخ راهنما: GET /books میتواند {"items":[]} با ۲۰۰ برگرداند؛ POST /books عنوان متنی دریافت کند و پس از ساخت، ۲۰۱ همراه شیء دارای شناسه بدهد. عنوان خالی در این قرارداد ۴۰۰ است. رابط عنوان را بررسی میکند ولی سرور دوباره آن را میسنجد. معیار تحویل، قرارداد قابل فهم برای برنامهنویس دیگری و تمایز واضح میان خطای ورودی، نبود مسیر و قطع ارتباط است. در بازبینی، نشان دهید کدام بخش دادهٔ ماندگار میخواهد و کدام بخش فقط محاسبه است.
MDN، نمای کلی HTTP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Overview
MDN، کدهای وضعیت HTTP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
تألیف و سناریوی آموزشی: تحریریه درسآوند.
متن درسهای عمومی را بدون ورود بخوانید.