فایل OpenAPI
توصیف ماشینخوان هر دو سطح، برای ساختن کلاینت، تست، و دادن به یک ابزار.
هر دو سطح روبهمشتری در یک فایل ماشینخوان توصیف شدهاند: ۴۱ مسیر، ۴۸ عملیات و ۶۵ اسکیما، با نسخهٔ OpenAPI 3.1.1.
دانلود
curl -O https://segmentic.net/openapi.json
فایل با هر بیلد سایت از نو ساخته میشود، از همان مخزنی که خود API در آن است. یعنی نسخهای که دانلود میکنید همیشه همان چیزی است که این صفحهها توصیفش میکنند، نه یک کپی دستی که یک بار بهروز شده و بعد جا مانده.
فایل دومی با پسوند .yaml نداریم و لازم هم نیست. JSON زیرمجموعهٔ YAML 1.2 است، پس هر ابزاری که YAML میخواهد همین فایل را بدون تغییر قبول میکند.
چه چیزی داخلش هست
هر مسیری که یک مشتری صدا میزند، روی هر دو میزبان:
- میزبان ورود داده
https://in.segmentic.net: رویداد، بچ، ثبت دستگاه، وبپوش، پیامرسان، صندوق پیام، پیام درونسایتی، وبهوک ورودی، و چهار مسیری که خودمان داخل پیامها میگذاریم. - میزبان مدیریتی
https://api.segmentic.net: هویت کلید، توانمندیها، شمای رویداد و ویژگی، مخاطب، سگمنت، کمپین، ورود داده سمت سرور، خروجی، گزارش قیف و ماندگاری، و پیام تراکنشی.
هر عملیات اینها را دارد: خلاصه، اسکیمای کامل درخواست و پاسخ با نام واقعی فیلدها، و همهٔ کدهای وضعیت با بدنهٔ خطایشان. توضیح را هم همه دارند جز POST /v1/messenger/unlink، و دستکم یک نمونهٔ واقعی که از تستهای خود پروژه برداشته شده را هم همه دارند جز شش عملیاتی که پشت چهار مسیریاند که خودمان داخل پیامها میگذاریم.
دو طرح احراز هویت تعریف شده و هیچکدام پیشفرض کل سند نیستند، پس ۳۹ عملیات از ۴۸ عملیات دقیقا یکی را اعلام میکند:
| نام در فایل | چیست | کجا |
|---|---|---|
writeKey | http با scheme: bearer. کلید نوشتن، wk_seg_ بهعلاوهٔ ۴۳ کاراکتر | مسیرهای میزبان ورود داده |
managementKey | http با scheme: bearer. کلید API، sk_seg_ بهعلاوهٔ ۴۳ کاراکتر | مسیرهای میزبان مدیریتی |
نه عملیات دیگر security: [] دارند: GET /v1/status، POST /v1/hooks/{source}/{token}، POST /v1/bounce/{local}، و شش عملیاتی که پشت چهار مسیریاند که خودمان داخل پیامها میگذاریم.
سه شکل خطا هم در components هست، چون سرور واقعا سه شکل دارد: IngestError تخت با status و message روی میزبان ورود داده، و PublicError تودرتو و FlatError و FlatCodedError روی میزبان مدیریتی. هر پاسخ به آن یکی اشاره میکند که واقعا برمیگردد.
دو میزبان در یک سند
یک نکتهٔ ساختاری که اگر ندانید گیجکننده است.
هر دو میزبان مسیرهایی زیر پیشوند /v1 دارند و یک سند OpenAPI کلیدهای paths را با رشته میسازد. پس هر دو سطح یک نقشهٔ paths مشترک دارند و هر عملیات آرایهٔ servers خودش را با دقیقا یک عضو حمل میکند، بهعلاوهٔ برچسبی که میگوید مال کدام سطح است.
تنها استثنا GET /v1/status است که واقعا روی هر دو میزبان وجود دارد، پس یک عملیات است با هر دو server.
اگر ابزارتان اولین server سند را برای همهچیز به کار میبرد، نصف درخواستها به میزبان اشتباه میروند. ابزارهایی که servers سطح عملیات را میخوانند (نسخههای امروزی openapi-generator، Postman، Insomnia، Bruno، Kiota) درست کار میکنند.
ساختن کلاینت
npx @hey-api/openapi-ts -i https://segmentic.net/openapi.json -o src/segmentic
npx @openapitools/openapi-generator-cli generate \
-i https://segmentic.net/openapi.json \
-g go \
-o ./segmentic-client
کلاینتی که از این سند ساخته میشود دو کلاس احراز هویت دارد، چون سند دو تا دارد. کلید wk_seg_ را به عملیات ورود داده بدهید و کلید sk_seg_ را به عملیات مدیریتی. برعکسش کامپایل میشود و در زمان اجرا 401 میگیرد.
دادن به یک ابزار
Postman و Insomnia و Bruno هر سه از روی نشانی مستقیم ایمپورت میکنند: در واردکردن، گزینهٔ نشانی را بزنید و https://segmentic.net/openapi.json را بدهید. متغیرهای محیط را خودتان بسازید، چون کلید در سند نیست و نباید باشد.
برای تست قرارداد، schemathesis روی سطح ورود داده مستقیم کار میکند:
schemathesis run https://segmentic.net/openapi.json \
--base-url https://in.segmentic.net \
--header "Authorization: Bearer wk_seg_..."
این کار روی حساب واقعی رویداد واقعی مینویسد. یک اپ جدا با کلید جدا بسازید، وگرنه دادهٔ آزمایشی با دادهٔ واقعی شما قاطی میشود و برگرداندنش کار سختی است.
چه چیزی داخلش نیست
- API خود پنل. آن سطح برای مشتری نیست، پایدار نیست، و هر هفته عوض میشود. آنچه اینجا هست همان چیزی است که قول پایداریاش داده شده.
- هیچ مسیری برای ساختن کلید. آن مسیرها روی شنوندهٔ دیگریاند که از بیرون آدرسپذیر نیست. کلید را از پنل بگیرید؛ در راهاندازی سریع توضیح داده شده.
- قاعدههایی که با تایپ بیان نمیشوند. اینکه
context.screenپذیرفته و هیچجا ذخیره نمیشود، اینکه تایماستمپ قدیمیتر از سی روز رویPOST /v1/eventsبیسروصدا به لبهٔ بازه چسبانده میشود، اینکهformatناشناخته در خروجیگرفتن بهndjsonتبدیل میشود: اینها درdescriptionهر فیلد نوشتهاند و هیچ اسکیمایی نمیتواند اجرایشان کند. کلاینت تولیدشده جلوی هیچکدام را نمیگیرد. - محتوای
specدر خروجیگرفتن.POST /v1/exportsاین فیلد را دستنخورده رد میکند و هیچچیز داخلش را اعتبارسنجی نمیکند. کلیدهایش برای هرkindفرق میکند و هیچ سندی در این مخزن آنها را نشمرده است. این یک شکاف واقعی است، نه سهو در فایل. - صفحهبندی، چون کار نمیکند و سند هم همین را میگوید.
limitفقط رویGET /v1/exportsخوانده میشود،cursorهیچجا، وhas_moreهمیشهfalseاست. دو مسیر فهرست بیصدا روی ۲۰۰ سطر بریده میشوند، مرتبشده بر اساس تازگی ویرایش، و هیچچیزی در پاسخ نمیگوید بقیه هم وجود دارند.
چهار مسیر هم داخل فایل هستند ولی شما صدایشان نمیزنید: پیکسل باز شدن، صفحهٔ لغو اشتراک، مرکز ترجیحات و ریدایرکت لینک کوتاه. اینها نشانیهاییاند که ما داخل پیام میگذاریم و یک نرمافزار ایمیل یا یک گوشی بازشان میکند. در فایل security: [] دارند، یعنی «کلید نمیخواهد»، نه «باز است»: امضای داخل نشانی، خودش اعتبارنامه است. رفتارشان در رضایت و سقف توضیح داده شده.
نکتهٔ صفحهبندی یکی از دو چیزی است که در توضیح info خود سند هم نوشته شده. دیگری این است که شکل خطا روی میزبان مدیریتی یکنواخت نیست: یازده مسیر از هندلرهای پنل استفاده میکنند و {"error": "یک رشته"} برمیگردانند نه پاکت کددار. کلاینتتان باید error را قبل از خواندن error.code هم رشته و هم شیء در نظر بگیرد. جزئیات در کدهای خطا.
اگر API عوض شد
قانون ۷ مخزن میگوید تغییر در این دو سطح، مستنداتش را در همان تغییر میبرد، و یک بررسی در CI این را میسنجد: مسیری که ثبت شود و در مرجع نباشد بیلد را قرمز میکند، جز همان چهار نشانی داخل پیام که بالا آمد و چهار تای دیگر که اسکریپت اسمشان را میبرد. جهت دیگر روی نمونهٔ کد سنجیده میشود نه روی نثر، چون صفحه اجازه دارد بگوید فلان مسیر وجود ندارد و چند صفحه هم بهدرستی همین را میگویند. قاعدهٔ دقیقش در نسخهبندی و تغییرها است. چون این فایل هم از همان مخزن ساخته میشود، نمیتواند از مرجع جا بماند. شرح کامل در نسخهبندی و تغییرها.