外部プログラムの呼び出し
外部プログラムは「サンドボックス環境」の外で実行されるため、コンピュータ上の他のプログラム、ファイル、データにアクセスして操作する権限を持ち、一定のセキュリティリスクがあります。使用者は呼び出されるプログラムの安全性を必ず確認してください。
外部プログラムは、「外部プログラムディレクトリ」下に保存されているコードファイルで、Javaプログラムのアーカイブファイルjarパッケージのほか、他のプログラムのコードソースファイルを使用できます。拡張子が .jar、.py、.php、.js、.bsh、.go、.sh、.rb、.lua、.rs、.py
などのファイルをサポートしています。以下の方法で「外部プログラムディレクトリ」をすぐに開くことができます。
外部プログラムを呼び出すとき、Apidogはサブプロセスを起動し、その中でコマンドライン実行方式でユーザー指定の外部プログラムを実行し、最後にサブプロセスの標準出力(stdout)を呼び出しの戻り値として取得します。プロセス全体で、コアロジックはユーザーが外部プログラム内で実装し、apidog は主に以下の3ステップの作業を行います:
ユーザー指定のパラメータからコマンド文字列を組み立てる
コマンドを実行する
結果を返す
これらのステップのうち、呼び出し方法の原理を理解するのは最初のステップです。Apidogが使用するコマンド結合公式は以下の通りです: 「コマンドプレフィックス + Scriptパス + パラメータリスト」になります。
その中で、「コマンドプレフィックス」 はプログラムファイルの拡張子から推測されます。「Scriptパス」と「パラメータリスト」はユーザーが呼び出し時に指定します。
例: スクリプトpm.execute('com.apidog.Base64EncodeDemo.jar', ['abc','bcd'])
、 実際に実行されるコマンドはjava -jar "com.apidog.Base64EncodeDemo.jar" "abc" "bcd"
になります。両者の変換関係は図のようになります:
プログラムの拡張子とコマンドプレフィックスの関係:
言語 | コマンドプレフィックス | Script拡張子 |
---|---|---|
Java | java -jar | .jar |
Python | python | .py |
PHP | php | .php |
JavaScript | node | .js |
BeanShell | java bsh.Interpreter | .bsh |
Go | go run | .go |
Shell | sh | .sh |
Ruby | ruby | .rb |
Lua | lua | .lua |
Rust | cargo run | .rs |
API
pm.executeAsync
pm.executeAsync(filePath, args, options)
filePath
string 外部プログラムのパスargs
string[] パラメータ。jarパッケージ内の指定されたメソッドを呼び出す場合は、JSON.stringify を使用して変換されます。それ以外の場合、文字列型ではない型は暗黙的に文字列型に自動変換されます。options
Objectcommand
string 外部プログラムの実行コマンド。「コマンドプレフィックス」の最初の部分が実行コマンドです。必須ではありません。デフォルトは自動的に推測された値(上記の「コマンドプレフィックス」表を参照)ですが、任意のプログラムにカスタマイズできます。cwd
string サブプロセスのワーキングディレクトリ。必須ではありません。デフォルトは「外部プログラムディレクトリ」です。env
Record<string, string> サブプロセスの環境変数。必須ではありません。デフォルトは {} です。windowsEncoding
string Windows システムで使用するエンコーディング形式。必須ではありません。デフォルトは"cp936"
です。className
string jar パッケージ内で呼び出すクラス名を指定します。例:"com.apidog.Utils"
。必須ではありません。jarパッケージ内の指定されたメソッドの呼び出しを参照してください。method
string jar パッケージ内で呼び出すメソッド名を指定します。例:"add"
。必須ではありません(className
が値を持つ場合は必須)。jarパッケージ内の指定されたメソッドの呼び出し を参照してください。paramTypes
string[] jar パッケージ内で呼び出すメソッドのパラメータ型を指定します。例:["int", "int"]
。必須ではありません。デフォルトはパラメータから自動的に推論します。jarパッケージ内の指定されたメソッドの呼び出し を参照してください。
戻り値: Promise
command
パラメータの使用場面:
Apidogはデフォルトで .py
ファイルを python
で実行しますが、コンピュータに python3 がすでにインストールされている場合は、command
を python3
に指定できます。
pm.executeAsync('./demo.py', [], { command: 'python3' }).then(res => {
console.log('result: ', res);
});
pm.execute
pm.executeAsync を使用することをおすすめします。詳細は《コードの移行説明》を参照してください。
pm.execute(filePath, args, options)
filePath
string 外部プログラムのパスargs
string[] パラメータ。jarパッケージ内の指定されたメソッドを呼び出す場合は、JSON.stringify を使用して変換されます。それ以外の場合、文字列型ではない型は暗黙的に文字列型に自動変換されます。options
ObjectwindowsEncoding
string Windows システムで使用するエンコーディング形式。必須ではありません。デフォルトは"cp936"
です。className
string jar パッケージ内で呼び出すクラス名を指定します。例:"com.apidog.Utils"
。必須ではありません。jarパッケージ内の指定されたメソッドの呼び出し を参照してください。method
string jar パッケージ内で呼び出すメソッド名を指定します。例:"add"
。必須ではありません(className
が値を持つ場合は必須)。jarパッケージ内の指定されたメソッドの呼び出し を参照してください。paramTypes
string[] jar パッケージ内で呼び出すメソッドのパラメータ型を指定します。例:["int", "int"]
。必須ではありません。デフォルトはパラメータから自動的に推論します。jarパッケージ内の指定されたメソッドの呼び出し を参照してください。
戻り値: string
実行とログ
プログラムの実行時に、実行されたコマンドの内容がコンソールに出力されます(内容は参考用)。実行結果が期待されたものと異なる場合、コマンドの内容をコピーしてShell/CMD
に貼り付け、デバッグを実行できます。
コンソールには、プログラム実行プロセスの「標準出力(stdout)」と「標準エラー出力(stderr)」も出力されます。「標準出力」のすべての内容(最後の改行を除く)が、プログラムの最終的な実行結果となります。
歴史的な理由から、pm.execute は「標準エラー出力」に内容がある場合にプログラムの実行が失敗したと判断します。これにより、一部のプログラムが warning や error 情報を出力した場合に、実行が失敗することがあります。pm.executeAsync は終了コードを使用して、プログラムの実行が成功したかどうかを判断するように変更されています。
外部プログラムの入力と出力
パラメータ
ユーザー指定の外部プログラムがコマンドライン実行方式で実行されるため、外部プログラムはコマンドラインパラメータから実行時に渡されたパラメータのみを取得できます。
例えば、スクリプト pm.executeAsync('add.js', [2, 3])
を実行すると、実際のコマンドは node add.js 2 3
となります。外部スクリプト add.js 内でパラメータを取得するには、以下のようにします:
let a = parseInt(process.argv[1]); // 2
let b = parseInt(process.argv[2]); // 3
プログラミング言語によって、コマンドラインパラメータの取得方法は異なります。詳細は各言語のドキュメントを参照してください。 コマンドラインパラメータの型はすべて文字列なので、必要に応じて型変換が必要です。
戻り値
前述のとおり、Apidogはプログラム呼び出しの結果として標準出力(stdout)の内容を使用するため、標準出力に内容を出力することで結果を返すことができます。
例えば、スクリプト const result = await pm.executeAsync('add.js', [2, 3])
の場合、以下のように出力して変数 result に割り当てることができます:
console.log(parseInt(process.argv[1]) + parseInt(process.argv[2]));
プログラミング言語によって、標準出力(stdout)への出力方法は異なります。詳細は各言語のドキュメントを参照してください。 戻り値の型は文字列なので、必要に応じて型変換が必要です。 戻り値の末尾にある改行は自動的に削除されます。 jar パッケージ内の指定されたメソッドを呼び出す場合、呼び出されたメソッドの戻り値が最終的な戻り値として優先されます。
エラーのスロー
現在のタスクを失敗させて実行を終了するには、エラーをスローします。例:
throw Error("Execution failed");
プログラミング言語によって、エラーのスロー方法は異なります。詳細は各言語のドキュメントを参照してください。 JavaScript のコード console.error('Error') はエラーのスローではなく、標準エラー出力(stderr)への出力です。他の言語も同様に注意が必要です。
デバッグ情報
pm.executeAsync
は終了コードを使用してプログラムの成功/失敗を判断するため、標準エラー出力(stderr)を使用してデバッグ情報を出力できます。プログラムの実行に影響しません。
例:
console.warn("debug info");
console.error("error info");
pm.executeAsync インターフェイスのみがこの方法でのデバッグ情報の出力をサポートしています。 プログラミング言語によって、標準エラー出力(stderr)への出力方法は異なります。詳細は各言語のドキュメントを参照してください。
pm.execute から pm.executeAsync への移行
pm.executeAsync
の戻り値が Promise
型なので、古いコードの execute
をそのまま executeAsync
に置き換えることはできません。しかし、async/await
を使用することで、最小限の変更でコードを移行できます。
Apidogはトップレベルの await
をサポートしています。
具体的な方法は以下の通りです:
execute
をexecuteAsync
に変更する- 関数呼び出しの前に
await
キーワードを追加する
// 変更前
const result = pm.execute("add.js", [3, 4]);
pm.environment.set("result", result);
// 変更後
const result = await pm.executeAsync("add.js", [3, 4]);
pm.environment.set("result", result);
Jarパッケージ内の指定メソッドの呼び出し
この機能は、反射を使って直接呼び出せるJarパッケージのみをサポートし、Spring Bootのような内部ランタイムによる反射呼び出しを行うJarパッケージはサポートしていません。
外部プログラムがJarパッケージの場合、デフォルトではJar内のMainクラスのmainメソッドが呼び出されます。パラメータoptions.className
に値が指定されている場合は、デフォルトの動作を無視して、Jar内の指定されたメソッドを呼び出します。
Jar内の指定メソッドの呼び出しは、他の外部プログラムの呼び出しとは異なります。apidogは、ビルトインの実行器を使用して、反射によりJar内のメソッドを検索して呼び出します。また、呼び出されたメソッドが戻り値を持つ場合、その戻り値(文字列に変換)を最終的な戻り値として返します。それ以外の場合は、他の呼び出し方式と同様に、標準出力(stdout)の内容を戻り値として返します。
例:
await pm.executeAsync('./scripts/jar-1.0-SNAPSHOT.jar', ['hello', 'world'], {
className: 'com.apidog.Test',
method: 'combine',
paramTypes: ['String', 'String']
})
実際に呼び出されるコマンドは:
java -jar "<app-dist>/assets/JarExecuter-1.1.0-jar-with-dependencies.jar" ./scripts/jar-1.0-SNAPSHOT.jar "com.apidog.Test.combine(String,String)" "\"hello\"" "\"world\""
ここで、<app-dist>/assets/JarExecuter-1.1.0-jar-with-dependencies.jar
は、ビルトインの実行器で、ユーザープログラム ./scripts/jar-1.0-SNAPSHOT.jar
から反射によりメソッドcom.apidog.Test.combine(String,String)
を検索し、パラメータ(JSON文字列形式)"hello"
、"world"
を使用して呼び出します。
paramTypes
はオプションのフィールドで、空の場合はデフォルトでパラメータから型を推測します。整数は "int"
、浮動小数点数は "double"
、ブール値は "boolean"
、文字列は "String"
、配列は最初の要素の型から推測します。例えば、[3]
は "int[]"
、[3.14]
は "double[]"
などです。自動推測の型が、呼び出しメソッドのパラメータの型と一致しない場合は、 paramTypes
の値を手動で指定する必要があります。 paramTypes
配列でサポートされている要素の値は、 "Number"
、 "int"
、 "Integer"
、 "long"
、 "Long"
、 "short"
、 "Short"
、 "float"
、 "Float"
、 "double"
、 "Double"
、 "boolean"
、 "Boolean"
、 "String"
、 "Number[]"
、 "int[]"
、 "Integer[]"
、 "long[]"
、 "Long[]"
、 "short[]"
、 "Short[]"
、 "float[]"
、 "Float[]"
、 "double[]"
、 "Double[]"
、 "boolean[]"
、 "Boolean[]"
、 "String[]"
です。
したがって、上の例では paramTypes
パラメータを省略できます。
await pm.executeAsync('./scripts/jar-1.0-SNAPSHOT.jar', ['hello', 'world'], {
className: 'com.apidog.Test',
method: 'combine'
})
例
1. php プログラム
スクリプトの内容:
const param1 = { a: 1, b: 2 }
const resultString = await pm.executeAsync('test.php', [JSON.stringify(param1)])
const result = JSON.parse(resultString)
console.log('実行結果:', result) // 実行結果:{ a: 2, b: 4 }
test.php のコード:
<?php
$param = json_decode($argv[1]);
$result = [];
foreach($param as $key=>$value) {
$result[$key] = $value * 2;
}
echo json_encode($result);
2. jar プログラム
スクリプトの内容:
const result = await pm.executeAsync('com.apidog.utils.jar', [3, 5], {
className: 'com.apidog.utils.Utils',
method: 'add',
paramTypes: ['Integer', 'Integer']
})
console.log('実行結果:', result) // 実行結果:8
com.apidog.utils.jar パッケージのコード:
package com.apidog.utils;
public class Utils {
public Integer add(Integer a, Integer b) {
return a + b;
}
};
よくある質問
1. 一部のプログラムはプロジェクトの設定ファイルが必要で、見つからないとエラーになる
例: rust と go
rust:
could not find `Cargo.toml` in `<...>/ExternalPrograms` or any parent directory
go:
go.mod file not found in current directory or any parent directory; see 'go help modules'
解決策: pm.executeAsyncインターフェースを使用し、cwd
を指定
2. MacOSにはビルトインのPython3があるが、Python2はない
pm.executeAsyncインターフェースを使用し、パラメータ command
の値を "python3"
に設定
3. xxxコマンドが見つからない
対応するプログラムをインストールし、必要なディレクトリをオペレーティングシステムの PATH に追加。Java のインストールはドキュメントを参照。
4. 一部のWindowsシステムで外部スクリプトを参照すると、日本語が文字化けする
windowsEncoding
パラメータの値を 'utf-8'
に設定
var result = pm.execute(`hello.go`, [], { windowsEncoding: 'utf-8' })