پرش به مطلب اصلی

تعریف اپی‌آی سفارشی

شناسهٔ شما: 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 محدود است، پیش از آنکه به اینجا برسد.

آنچه هرگز انجام نمی‌دهد​

اپی‌آی سفارشی دسترسی را گسترده نمی‌کند. توابع رکورد اسکریپت از همان دری می‌گذرند که صفحه‌های خود پلتفرم و به‌عنوان فراخوان اجرا می‌شوند، پس مجوز او روی آن جدول و سیاست دادهٔ پشت آن تعیین می‌کنند چه چیزی برمی‌گردد. قرارداد سفارشی نمایی پایدار به سامانهٔ بیرونی می‌دهد، نه نمایی بزرگ‌تر.