コンテンツにスキップ

REST API公開

UIとは結合していないアクション処理相当をREST APIとして外部に公開する機能です。
外部からREST APIアプリケーションに対して、REST呼び出しを行うことができるようになります。
REST呼び出しを受けたREST APIアプリケーションは処理を行い返答したり、実行環境のDBにアクセスしたり、外部のREST APIを呼び出して、その結果を返答したりできます。

Tips

作成

REST API定義の作成手順は以下の通りです。

  1. 同じパネル内にある[作成]ボタンから[新規]を選択します。
  2. ダイアログ内にある[Rest API ID]フィールドと[Rest API ラベル]フィールドに情報を入力して、[作成]ボタンをクリックします。
  3. REST APIの設定項目を入力し、[保存]ボタンをクリックします。 REST APIの設定項目は以下の通りです。
項目入力説明
メソッド必須HTTPメソッドを指定します。
次の5種類から1つ選択します。
  • GET: データ取得
  • POST: データ作成
  • PUT: データ更新
  • DELETE: データ削除
  • PATCH: データ部分置換
  • OPTIONS:許可された通信オプションの取得
リソース必須パスセグメントを入力します。
パスパラメータは{xx} のようにカッコで括ってください。
デバッグエンドポイント URLデバッグデプロイしたREST API を呼び出すためのURLです。
https://{ドメイン}/dev/{Rest API ID}/{リソース}
URLを開いたり、クリップボードへコピーすることもできます。
リリースエンドポイント URLリリースデプロイしたREST API を呼び出すためのURLです。
https://{ドメイン}/prod/{Rest API ID}/{リソース}
URLを開いたり、クリップボードへコピーすることもできます。
コンテンツタイプレスポンスヘッダへ初期登録されるタイプを設定します。
コンテンツタイプを設定しても、アクションで上書きすることは可能です。
認証を必要とする必須認証を必要とするかどうかを設定します。
  • Required
  • Not Required(デフォルト)
  1. [アクションエディタ]ボタンをクリックし、アクションエディタを開きます。
  2. アクションボードへ記述、ユーザ関数作成などを行い、[保存]ボタンをクリックします。

Tips

デプロイ

REST API定義をデプロイすることで、REST APIの公開となります。 REST API 定義にある右上の[デプロイ]ボタンをクリックし、デプロイを行います。

Tips

例えば、下記の定義をデプロイします。

  • アプリケーション定義のID「restapi_sample」
  • REST API定義のメソッド「GET」
  • REST API定義のリソース「employee/{id}」

このREST APIが使用しているリソース数は、3つになります。(メソッドはカウント対象外となります。) デプロイした実行環境のリソース合計数は、ルート分も含むので4つになります。

/restapi_sample
/employee
/{id}
GET

この後、下記の定義をデプロイします。

  • アプリケーション定義のID「restapi_sample」
  • REST API定義のメソッド「POST」
  • REST API定義のリソース「calculator」

REST APIのリソースは下記のようになります。 デプロイした実行環境のリソース合計数は、ルート分も含めて5つになります。

/restapi_sample
/calculator
POST
/employee
/{id}
GET

Tips

アクションエディタ

REST APIのアクションスクリプトの記述について、デスクトップやモバイルのアクションと異なる点があります。 ここではできることや注意点について説明します。

オブジェクト

REST APIのアクションスクリプト内で使用できるオブジェクトについて説明します。

オブジェクト説明
$const$constを参照してください。
$fnビルトイン関数を呼び出すことができます。
使用できる関数については、下記の表を参照してください。
$req$reqを参照してください。
$res$resを参照してください。

ビルトイン関数

REST APIのアクションスクリプト内で使用できるビルトイン関数について説明します。

ビルトイン関数説明
$fn.getFile(path)$fn.getFile(path)を参照してください。
$fn.getFileNames(path)$fn.getFileNames(path)を参照してください。
$fn.putFile(path, parameters)$fn.putFile(path, parameters)を参照してください。
$fn.deleteFile(path)$fn.deleteFile(path)を参照してください。
$fn.getUsers(groupName?,option)$fn.getUsers(groupName?,option)を参照してください。
$fn.createUser(param)$fn.createUser(param)を参照してください。
$fn.updateUser(param)$fn.updateUser(param)を参照してください。
$fn.deleteUser(email)$fn.deleteUser(email)を参照してください。
$fn.resetPassword(param)$fn.resetPassword(param)を参照してください。
$fn.getGroups(option)$fn.getGroups(option)を参照してください。
$fn.createGroup(param)$fn.createGroup(param)を参照してください。
$fn.addUsers(param)$fn.addUsers(param)を参照してください。
$fn.removeUsers(param)$fn.removeUsers(param)を参照してください。
$fn.svf.oauth2.token()$fn.svf.oauth2.token()を参照してください。
$fn.svf.oauth2.revoke()$fn.svf.oauth2.revoke()を参照してください。
$fn.svf.artifacts.print()$fn.svf.artifacts.print()を参照してください。
$fn.svf.artifacts.info()$fn.svf.artifacts.info()を参照してください。
$fn.svf.artifacts.download()$fn.svf.artifacts.download()を参照してください。
$fn.svf.actions.status()$fn.svf.actions.status()を参照してください。
$fn.sendMail(param)$fn.sendMail(param)を参照してください。
$fn.csvToObject(csv)$fn.csvToObject(csv)を参照してください。
$fn.getPresignedUrl(path,options)$fn.getPresignedUrl(path,options)を参照してください。
$fn.listUsersByEmail(email,option)$fn.listUsersByEmail(email,option)を参照してください。
$fn.listUsersByName(name,option)$fn.listUsersByName(name,option)を参照してください。

編集

REST API定義のIDとラベルを変更できます。 REST API一覧から編集したいREST APIの[メニュー] - [編集]を選択します。 また、REST API項目も編集を行うことができます。 編集後は[保存]ボタンをクリックします。

削除

REST API定義を削除するには、REST APIの[メニュー] -[削除] を選択します。

コピー

REST API定義をコピーし、指定アプリケーションへ挿入することができます。 REST API一覧からコピーしたいUIの[メニュー]-[コピー]を選択します。

検索

REST APIはパネル上部の検索フィールドからRest APIラベルでフィルタできます。

エクスポート

REST API定義をファイルとしてローカルにダウンロードすることができます。 REST APIの[メニュー]-[エクスポート]を選択することで可能です。

インポート

ローカルにエクスポートしたREST API定義はサービスにアップロードすることができます。 REST APIリスト右上の [作成]ボタンから[インポート]を選択します。 [インポート]ダイアログからREST API定義ファイルを選択して、アップロードを実行します。 インポート可能な定義は、アプリケーションタイプ「REST API」のREST API定義のみです

コミット

ユーザはリポジトリに対してアプリ定義をコミットを行うことができます。

フリー環境にデプロイ済みのサンプルREST API

サンプルREST APIの情報

リソースデバッグエンドポイントURLリリースエンドポイントURLメソッド認証Content-Type[Request]Content-Type[Response]
/employee/{id}https://api.feda9x.webperformer.jp/dev/restapi_sample/employee/{id}https://api.feda9x.webperformer.jp/prod/restapi_sample/employee/{id}GETRequired-application/json
/calculatorhttps://api.feda9x.webperformer.jp/dev/restapi_sample/calculatorhttps://api.feda9x.webperformer.jp/prod/restapi_sample/calculatorPOSTRequiredapplication/jsontext/plain

APIキー

デプロイ環境APIキー
デバッグuarsnOdmlF3Wcth1C8KeaPg4njkheaq7VtAYh0De
リリース0mUykFa2j82t08kA8Xdhe5W4a7THnv8Maq3MtN4v

Tips

リソース: /employee/{id} の仕様

従業員 id をパスパラメータに指定することで、JSON 形式で5名のダミーの従業員情報をJSONで返却します。

[
{
"id": "E001",
"name": "Tom Williams",
"age": 28
},
{
"id": "E002",
"name": "David Campbell",
"age": 39
},
{
"id": "E003",
"name": "Nick Raj",
"age": 21
},
{
"id": "E004",
"name": "Kevin Dean",
"age": 45
},
{
"id": "E005",
"name": "John Smith",
"age": 26
}
]

REST API呼び出し成功時は、HTTPステータス200を返却します。 レスポンスのContent-Typeは、application/jsonです。 レスポンスボディは、id(E001~E005)に該当する従業員の情報のみを返却します。

(GET /employee/E001 の例)

{
"id": "E001",
"name": "Tom Williams",
"age": 28
}

存在しないIDを指定時、HTTPステータス404を返却します。 レスポンスの Content-Type は application/jsonです。 レスポンスボディは以下の通りです。 {“message”: “Employee ID {id} not found.”}

アクション定義

/* Modules */
const util = require("node:util");
/* Consts */
const EMPLOYEES = [
{
id: "E001",
name: "Tom Williams",
age: 28,
},
{
id: "E002",
name: "David Campbell",
age: 39,
},
{
id: "E003",
name: "Nick Raj",
age: 21,
},
{
id: "E004",
name: "Kevin Dean",
age: 45,
},
{
id: "E005",
name: "John Smith",
age: 26,
},
];
/* Class */
class EmployeeService {
constructor() { }
find({ employeeId }) {
return EMPLOYEES.find((e) => e.id === employeeId);
}
}
class Response {
static ok(employee) {
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(employee),
};
}
static notFound({ employeeId }) {
return {
statusCode: 404,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message: util.format($const.MESSAGE_EMPLOYEE_NOT_FOUND, employeeId),
}),
};
}
static internalServerError() {
return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message: $const.MESSAGE_EMPLOYEE_INTERNAL_SERVER_ERROR,
}),
};
}
}
class Api {
constructor() {
this.employeeService = new EmployeeService();
}
execute({ pathParameters }) {
try {
const employeeId = pathParameters?.id;
const employee = this.employeeService.find({ employeeId });
if (!employee) {
return Response.notFound({ employeeId });
}
return Response.ok(employee);
} catch (e) {
console.error(e);
return Response.internalServerError();
}
}
}
/* Instances */
const api = new Api();
/* Main */
const response = api.execute({
pathParameters: $req.pathParameters,
});
$res.statusCode = response.statusCode;
$res.headers = response.headers;
$res.body = response.body;

定数定義

名前データ型
MESSAGE_EMPLOYEE_INTERNAL_SERVER_ERRORStringSystem error.
MESSAGE_EMPLOYEE_NOT_FOUNDStringEmployee ID %s not found.

リソース: /calculator の仕様

arg1とarg2の引数、および、operation (加算または減算) を受けると、計算結果の値を返却します。

  • arg1: -99999999~99999999 までの数値
  • arg2: -99999999~99999999 までの数値
  • operation: plus|minu

リクエストのContent-Typeは、application/jsonです。 リクエストボディは以下の通りです。

例)
{
"arg1": 1234.56,
"arg2": -123.45,
"operation": "plus"
}

成功時、HTTPステータス200を返却します。 レスポンスの Content-Type はtext/plainです。 レスポンスボディは以下の様に計算結果のみを返却します。 例)1111.11

数値(number型)の有効桁数は16桁(JSの仕様でIEEE 754の倍精度。小数含む。)です。 BigNumberに変換して計算します。

arg1, arg2, operation が不正な場合、レスポンスのHTTPステータスは400とします。 レスポンスの Content-Typeは text/plainです。 レスポンスボディは一律以下を返却します。 Input values are incorrect.

アクション定義

/* Consts */
const ARG_MIN = -99999999;
const ARG_MAX = 99999999;
/* Class */
class Calculator {
constructor(type) {
this.type = type;
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
throw new Error("Not implemented.");
}
}
class PlusCalculator extends Calculator {
constructor() {
super("plus");
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
return BigNumber(arg1).plus(BigNumber(arg2));
}
}
class MinusCalculator extends Calculator {
constructor() {
super("minus");
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
return BigNumber(arg1).minus(BigNumber(arg2));
}
}
class CalculatorManager {
/**
* @param {Calculator[]} calculators
*/
constructor(calculators) {
this.calculators = calculators;
}
/**
* @param {string} type
* @returns {Calculator}
*/
getCalculator(type) {
return this.calculators.find((c) => c.type === type);
}
/**
* @returns {string}
*/
getTypes() {
return this.calculators.map((c) => c.type);
}
}
class Response {
/**
* @param {BigNumber} result
*/
static ok(result) {
return {
statusCode: 200,
headers: {
"Content-Type": "text/plain",
},
body: result?.toFixed(),
};
}
static badRequest() {
return {
statusCode: 400,
headers: {
"Content-Type": "text/plain",
},
body: $const.MESSAGE_CALC_BAD_REQUEST,
};
}
static internalServerError() {
return {
statusCode: 500,
headers: {
"Content-Type": "text/plain",
},
body: $const.MESSAGE_CALC_INTERNAL_SERVER_ERROR,
};
}
}
class Api {
constructor() {
this.calcManager = new CalculatorManager([
new PlusCalculator(),
new MinusCalculator()
]);
}
toParams(body) {
try {
return JSON.parse(body);
} catch (e) {
console.error("Invalid request body: ", e);
return null;
}
}
isValid({ type, arg1, arg2 }) {
const allowedTypes = this.calcManager.getTypes();
// type.
if (!allowedTypes.includes(type)) {
return false;
}
// arg1.
if (typeof arg1 !== "number") {
return false;
}
if (arg1 < ARG_MIN || ARG_MAX < arg1) {
return false;
}
// arg2.
if (typeof arg2 !== "number") {
return false;
}
if (arg2 < ARG_MIN || ARG_MAX < arg2) {
return false;
}
return true;
}
/**
* @param {{
* body: string;
* }}
*/
execute({ body }) {
try {
const params = this.toParams(body);
if (!params) {
return Response.badRequest();
}
const type = params.operation;
const arg1 = params.arg1;
const arg2 = params.arg2;
if (!this.isValid({ type, arg1, arg2 })) {
return Response.badRequest();
}
const calculator = this.calcManager.getCalculator(type);
const result = calculator.calculate(arg1, arg2);
return Response.ok(result);
} catch (e) {
console.error(e);
return Response.internalServerError();
}
}
}
/* Instances */
const api = new Api();
/* Main */
const response = api.execute({
body: $req.body,
});
$res.statusCode = response.statusCode;
$res.headers = response.headers;
$res.body = response.body;

定数定義

名前データ型
MESSAGE_CALC_BAD_REQUESTStringInput values are incorrect.
MESSAGE_CALC_INTERNAL_SERVER_ERRORStringSystem error.

ブラウザからRESTを呼び出す場合

RESTAPIをデプロイした場合に 単純リクエストではない場合にプリフライトリクエストが発生します。

そのため、OPTIONSメソッドも追加で用意する必要があります。

OPTIONSメソッドでは、指定された URL またはサーバーの許可されている通信オプションをリクエストします。

アクション定義

const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'origin,x-api-key' ,
}
};
$res= response;
return $res;

Tips

ヘッダー名説明
Access-Control-Allow-Origin指定されたオリジンからのリクエストを行うコードでレスポンスが共有できるかどうかを示します
Access-Control-Allow-Methodsリソースにアクセスするときに利用できる 1 つまたは複数のメソッドを指定します
Access-Control-Allow-Headers実際のリクエストの間に使用できる HTTP ヘッダーを示すために使用されます