تعریف اپیآی سفارشی
شناسهٔ شما: custom-api@1
شمای ماشینخوان: custom-api.schema.json
تعریف متعارف یک اپیآی سفارشی (بخش ۶.۹): قراردادی HTTP نسخهدار که یک محیط برای سامانههای بیرون از پلتفرم منتشر میکند، متعلق به یک راهحل است و در بستهٔ آن سفر میکند. یک تعریف، بیتوجه به اینکه از مرکز کنترل مدیریت آمده باشد یا از یک فراخوانی API، یک دستیار هوش مصنوعی یا ورود یک راهحل، یکسان اعتبارسنجی میشود.
ساختار
| فیلد | نوع | الزامی | یادداشت |
|---|---|---|---|
logicalName | رشته | بله | با پیشوند ناشر، بهصورت snake_case کوچک. در همهٔ نسخهها ثابت است. |
displayName | رشته | بله | خلاصهٔ عملیات در سند OpenAPI. |
publisherPrefix | رشته | بله | بخشی از نشانی ارائهشده نیز هست. |
version | عدد صحیح | بله | ۱ تا ۹۹۹. بهصورت بخش v{version} در مسیر ارائه میشود. |
route | رشته | بله | زیر بخش نسخه، بدون اسلش ابتدایی. بخش داخل آکولاد یک پارامتر مسیر است. |
verb | رشته | بله | Get، Post، Put، Patch، Delete. |
script | رشته | بله | کد BS Lang که این اپیآی اجرا میکند. یک پیادهسازی هست و همین است. |
requiredScope | رشته | بله | دامنهای که ثبت برنامهٔ فراخوان باید داشته باشد. |
description | رشته یا null | خیر | توضیح عملیات در سند OpenAPI. |
requestSchema | شیء یا null | خیر | یک JSON Schema که در هر فراخوانی بررسی میشود. برای روش بدون بدنه رد میشود. null یعنی نامهای getInput خودِ اسکریپت قرارداد است (در OpenAPI منتشر میشود؛ در فراخوانی درگاه، فهرستی بسته). |
responseSchema | شیء یا null | خیر | یک JSON Schema که در سند OpenAPI منتشر میشود. |
responseContentType | رشته | خیر | application/json، text/plain یا text/html — آنچه قرارداد معمولاً با آن پاسخ میدهد و آنچه سند OpenAPI منتشر میکند. |
isEnabled | بولی | خیر | تعریف غیرفعال ذخیره و صادر میشود و خطای ۴۰۴ برمیگرداند. |
هویت یک جفت است
(logicalName, version) هویت اپیآی است و (publisherPrefix, version, verb, route) نشانی آن.
par_approve_invoice نسخهٔ ۱ و ۲ یک قرارداد در دو سن هستند و کنار هم پاسخ میدهند تا شریک
یکپارچهسازی مهاجرت کند — پس تعریف دومی که هم نام و هم نسخه را داشته باشد تکراری است، و تعریفی که
همان نام را با نسخهٔ تازه داشته باشد نسخهٔ بعدی است. دو تعریف هرگز نمیتوانند یک نشانی را با هم
داشته باشند، هر نامی که داشته باشند.
نشانی ارائهشده
/api/{publisherPrefix}/v{version}/{route}
امروز زیر یک محیط در دسترس است — /environments/{environmentId}/api/par/v1/invoices — چون نشانهٔ
اعتبارنامهٔ کارخواه نام مستأجر را میگوید نه یکی از محیطهای او. شکل عمومی کوتاهتر با دروازه میآید که یک نام میزبان را به یک محیط نگاشت میکند.
چه چیزی اجرا میشود
یک چیز: script. تعریف یک مسیر را نام میبرد و کد BS Langای که به آن پاسخ میدهد، و چیز
دیگری برای انتخاب نیست. درخواست را با getInput میخواند، با setOutput یا setBody پاسخ
میدهد، وضعیت و نوع محتوا را با setStatus و setContentType انتخاب میکند، سرآیندها را با
setHeader میگذارد، با توابع رکورد به جدولهای دیگر میرسد و با throwValidationError رد میکند.
پیشتر میان چهار گونهٔ پیادهسازی انتخاب میکرد — عملیات مستقیم روی جدول، یک جریان خودکارسازی، یک تابع، و یک پیام سفارشی خط لوله. سهتای آنها قابل تعری ف بودند ولی هرگز اعزام نمیشدند، پس فراخوانی ۵۰۱ میگرفت که میگفت منتظر کدام تکرار است، و تنها چهارمی اجرا میشد. آن رفته است. قراردادی که رفتارش کد خود سازنده است، توضیحش سادهتر، نسخهبندیاش سادهتر، و تنها یکی از آن چهارتاست که میتواند چیزی را بیان کند که پلتفرم پیشبینی نکرده بود — و دیگر ۵۰۱ در کار نیست، چون گونهٔ وصلنشدهای نمانده که آن را تولید کند.
منطقی که ارزش اشتراک میان دو اپیآی را دارد یک اسکریپت راهحل است که با نام وارد میشود، نه گونهٔ پنجم.
قاعدههایی که یک شما نمیتواند بیان کند
هنگام ذخیرهٔ تعریف، افزون بر شمای بالا بررسی میشوند:
responseContentTypeاعلامشده از آنهایی باشد که پلتفرم میتواند ارائه کند.- مسیر
Read،UpdateیاDeleteبخش{id}را اعلام کند — تنها جایی که شناسهٔ رکورد میتواند از آن بیاید. - روش بدون بدنه شمای درخواست ندارد. روش دارای بدنه میتواند آن را null بگذارد.
- شماهای درخواست و پاسخ بهعنوان JSON Schema کامپایل شوند.
- اسکریپت بهعنوان BS Lang تجزیه شود و هر ماژولی که وارد میکند به یک اسکریپت راهحل برسد.
نمونه
{
"logicalName": "par_create_invoice",
"displayName": "Create an invoice",
"publisherPrefix": "par",
"description": "Creates an invoice from a validated body.",
"version": 1,
"route": "invoices",
"verb": "Post",
"requestSchema": {
"type": "object",
"additionalProperties": false,
"required": ["par_name", "par_amount"],
"properties": {
"par_name": { "type": "string", "maxLength": 200 },
"par_amount": { "type": "number", "exclusiveMinimum": 0 }
}
},
"responseContentType": "application/json",
"requiredScope": "modelapps.write",
"isEnabled": true,
"script": "var id = createRecord('par_invoice', {
par_name: getInput('par_name'),
par_amount: getInput('par_amount')
});
setOutput('id', id);"
}
بدنه پیش از اجرای اسکریپت با requestSchema بررسی میشود، پس getInput شکلی را میخواند که
از پیش اعتبارسنجی شده، نه شکلی که هر اسکریپت باید خودش از آن دفاع کند.
یک ورودی میتواند شیء یا فهرست باشد
getInput هر چه آن ویژگی نگه دارد به اسکریپت میدهد — رشته، عدد، بولین، یا یک شیء یا
آرایه که یکجا منتقل میشود و اسکریپت با عضو (f.fileName) و با length() در آن حرکت
میکند. پس قراردادی که ورودی ساختاریافتهای را در requestSchema خود توصیف میکند، واقعاً
میتواند آن را بخواند:
"par_document": {
"type": "object",
"additionalProperties": false,
"required": ["fileName", "contentType", "contentBase64"],
"properties": {
"fileName": { "type": "string", "maxLength": 260 },
"contentType": { "type": "string", "maxLength": 200 },
"sizeBytes": { "type": "integer" },
"contentBase64": { "type": "string", "maxLength": 5600000 }
}
}
تا پیش از دور ۱۰ درگاهها، یک شیء بهصورت متن خام JSON میرسید، که BS Lang راهی برای تجزیهاش ندارد — پس سازندهای که شکل دلخواهش را اعلام میکرد وضع بدتری از کسی داشت که آن را به چند ویژگی جدا میشکاند، که عکس هدف یک طرحواره است. عمق تودرتو به محدودیت ۶۴ سطحی خود تجزیهگر JSON محدود است، پیش از آنکه به اینجا برسد.
آنچه هرگز انجام نمیدهد
اپیآی سفارشی دسترسی را گسترده نمیکند. توابع رکورد اسکریپت از همان دری میگذرند که صفحههای خود پلتفرم و بهعنوان فراخوان اجرا میشوند، پس مجوز او روی آن جدول و سیاست دادهٔ پشت آن تعیین میکنند چه چیزی برمیگردد. قرارداد سفارشی نمایی پایدار به سامانهٔ بیرونی میدهد، نه نمایی بزرگتر.