آزمایش API از ویندوز؛ متن فارسی و درخواستهای واقعی
در این درس ۷ بخش
نوشتن سرور بدون استفادهکردن از آن، بخش بزرگی از خطاها را پنهان میکند. اکنون نقش مشتری را از PowerShell بازی میکنیم: یک کار فارسی میسازیم، شناسهٔ پاسخ را میخوانیم و همان کار را تغییر میدهیم. سرور درس قبل در ترمینال اول باید روشن بماند و دستورهای این درس در ترمینال دوم اجرا شوند. برای این تمرین نصب Postman ضروری نیست؛ ابزار داخلی ویندوز مسیر درخواست و پاسخ را بهخوبی نشان میدهد.
درخواست با مقدار واقعی ساخته میشود
در مثال کامل زیر، ابتدا یک hashtable میسازیم، آن را با ConvertTo-Json به متن JSON تبدیل میکنیم و سپس بایتهای UTF-8 میفرستیم. این روش از تفاوت پیشفرض رمزگذاری نسخههای PowerShell برای متن فارسی فاصله میگیرد. Content-Type نیز صریح است. ارسال مستقیم hashtable به Body الزاماً قرارداد JSON را تولید نمیکند؛ مشاهدهٔ یک شیء در محیط PowerShell با ارسال همان قالب روی شبکه یکسان نیست. شکل داده را در هر مرز بشناسید.
دستورهای کامل مشتری در demo.ps1
$base = 'http://127.0.0.1:3000'
Invoke-RestMethod -Uri "$base/health" -TimeoutSec 5
$json = @{ title = 'مرور مستندات Node.js' } | ConvertTo-Json -Compress
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
$created = Invoke-RestMethod -Uri "$base/tasks" -Method Post `
-ContentType 'application/json; charset=utf-8' -Body $bytes -TimeoutSec 5
$created.task
$taskId = $created.task.id
Invoke-RestMethod -Uri "$base/tasks/$taskId" -TimeoutSec 5
$update = @{ done = $true } | ConvertTo-Json -Compress
Invoke-RestMethod -Uri "$base/tasks/$taskId" -Method Patch `
-ContentType 'application/json; charset=utf-8' `
-Body ([System.Text.Encoding]::UTF8.GetBytes($update)) -TimeoutSec 5
$listing = Invoke-RestMethod -Uri "$base/tasks" -TimeoutSec 5
$listing.tasks | Format-Table id, title, done
try {
Invoke-RestMethod -Uri "$base/missing" -TimeoutSec 5 -ErrorAction Stop
} catch {
if ($null -ne $_.Exception.Response) {
Write-Output ('HTTP ' + [int]$_.Exception.Response.StatusCode)
} else {
Write-Output $_.Exception.Message
}
}
میتوانید همین دستورها را در ترمینال اجرا کنید. اگر آنها را در demo.ps1 ذخیره کردید، اجرای فایل تابع سیاست اسکریپت محیط شماست؛ برای انجام تمرین نیازی به کاهش ExecutionPolicy نیست. در PowerShell 7 فایل UTF-8 مناسب است. اگر از Windows PowerShell 5.1 استفاده میکنید و فایل دارای متن فارسی را ذخیره و بازخوانی میکنید، در VS Code گزینهٔ Save with Encoding و UTF-8 with BOM را انتخاب کنید. این نکته دربارهٔ خواندن منبع اسکریپت است؛ Body همچنان با بایتهای UTF-8 ساخته میشود.
خروجی را با رفتار قرارداد تطبیق دهید
پاسخ ساخت، شیئی با task دارد و task شامل id، عنوان بدون فاصلهٔ اضافی و done:false است. پس از PATCH، done باید True دیده شود و عنوان تغییر نکند. شناسه را از پاسخ همان اجرا میگیریم؛ کپیکردن شناسهٔ نمونه از یک متن آموزشی معمولاً ۴۰۴ ایجاد میکند. اجرای دوبارهٔ بخش ساخت، کار تازهای میسازد و در این API تضمین جلوگیری از ساخت تکراری وجود ندارد. بنابراین هنگام آزمایش، تعداد کارهای پیش و پس از یک دستور را نیز نگاه کنید.
Invoke-RestMethod پاسخ JSON را برای نمایش به شیء PowerShell تبدیل میکند. Format-Table فقط ابزار نمایش است؛ خروجی قالببندیشده را دوباره بهعنوان بدنهٔ درخواست نفرستید. شکل Task در سرور boolean واقعی دارد و در PowerShell باید $true بفرستیم. رشتهٔ "true" ممکن است روی صفحه مشابه به نظر برسد، اما از نظر قرارداد نوع دیگری است. همین اختلاف کوچک از مشکلات رایج ارتباط مشتری و سرور است و باید در آزمون منفی دیده شود.
خطای HTTP با قطع اتصال فرق دارد
در بخش try/catch، مسیر missing باید پاسخ HTTP 404 داشته باشد. اگر سرور خاموش باشد، ممکن است اصلاً Response موجود نباشد و با خطای اتصال روبهرو شوید. به همین دلیل پیش از خواندن StatusCode، وجود Response بررسی میشود. دریافت ۴۰۴ ثابت میکند یک سرور پاسخ داده، ولی نتیجهٔ درخواستی موفق نبوده است. دریافتنکردن پاسخ میتواند از پورت اشتباه، فرایند خاموش یا مسئلهٔ شبکه باشد؛ با تغییر دادهٔ title حل نمیشود.
مرورگر، curl و ابزارهای اختیاری
نشانی /health یا /tasks را میتوان در نوار آدرس مرورگر باز کرد؛ این کار GET میفرستد و برای ساخت POST کافی نیست. در Windows PowerShell نام curl ممکن است alias باشد؛ اگر قصد استفاده از برنامهٔ واقعی curl را دارید، curl.exe بنویسید. برای همین دوره Invoke-RestMethod را روش اصلی نگه میداریم تا تفاوت quoting در shellها باعث سردرگمی نشود. نصب ابزار بیشتر قبل از شناخت درخواست، مشکل اصلی را حل نمیکند؛ در تیمی که از ابزار مشخصی استفاده میکند بعداً همان را اضافه کنید.
اگر در آینده رابط مرورگری جداگانه روی پورت دیگری بسازید، با سیاست origin مرورگر روبهرو میشوید؛ موفقیت PowerShell به معنی مجازبودن همان درخواست از هر صفحهٔ وب نیست. سرور این پروژه CORS پیاده نکرده است. افزودن Access-Control-Allow-Origin بهتنهایی احراز هویت نمیسازد و درخواستهای غیرمرورگری را محدود نمیکند. در این مرحله صفحهٔ ناشناس را برای آزمایش به سرور وصل نکنید؛ مشتری محلی و دادهٔ ساختگی برای یادگیری کافی است.
تمرین و پاسخ راهنما
یک کار دوم بسازید، ولی این بار در PATCH مقدار done را متن بفرستید. پاسخ مورد انتظار ۴۲۲ است و مقدار قبلی done باید false بماند. سپس سرور را متوقف و دوباره شروع کنید و GET /tasks بگیرید؛ فهرست باید خالی شود، چون ذخیرهسازی دائمی نداریم. معیار تحویل، ثبت روش، مسیر، نوع بدنه، وضعیت پاسخ و اثر واقعی هر درخواست است. فقط عکس یک جدول پرشده نشان نمیدهد که رد ورودی و مرز ذخیرهسازی را فهمیدهاید.
مرجع رسمی
Invoke-RestMethod و Body/ContentType: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod
ویرایش و ترمینال VS Code: https://code.visualstudio.com/docs/terminal/basics
تألیف و مثالهای اختصاصی: تحریریه درسآوند.
متن درسهای عمومی را بدون ورود بخوانید.