Apidog 允许你从 Javascript 环境中执行外部程序(脚本、JAR、二进制文件)。这使你能够利用 Java、Python、PHP、Go、Shell 等语言中的现有代码。外部程序在 Apidog 沙箱之外运行,并且拥有对你系统的完整访问权限。请确保你信任正在执行的代码。
支持的语言#
| 语言 | 扩展名 | 命令前缀 |
|---|
| Java | .jar | java -jar |
| Python | .py | python |
| Node.js | .js | node |
| PHP | .php | php |
| Go | .go | go run |
| Shell | .sh | sh |
| Ruby | .rb | ruby |
| Lua | .lua | lua |
如何调用外部程序#
1.
打开外部程序目录:点击脚本编辑器中的文件夹图标,打开应放置外部脚本的目录。 2.
通过脚本执行:使用 pm.executeAsync 调用程序。 API 参考#
pm.executeAsync#
args string[] 参数。调用 jar 包中的指定方法时,将使用 JSON.stringify 进行转换。除此之外,非 string 类型会被隐式转换为 string。
command string 外部程序的执行命令,“命令前缀”的第一部分就是执行命令。可选,默认值会自动推断(见上方“命令前缀”表),也可以自定义为任意程序。
cwd string 子进程的工作目录。可选,默认是“外部程序目录”。
env Record<string, string> 子进程的环境变量。可选,默认是 {}。
windowsEncoding string Windows 系统上使用的编码。可选,默认是 "cp936"。
className string 指定要在 jar 包中调用的类名,例如 "com.apidog.Utils"。
method string 指定要在 jar 包中调用的方法名,例如 "add"。
paramTypes string[] 指定要在 jar 包中调用的方法的参数类型,例如 ["int", "int"]。
默认情况下,Apidog 使用 python 来执行 .py 文件。如果计算机上已经安装了 python3,可以将 command 指定为 python3。 pm.execute#
pm.execute(filePath, args, options)args string[] 参数。调用 jar 包中的指定方法时,将使用 JSON.stringify 进行转换。除此之外,非 string 类型会被隐式转换为 string。
windowsEncoding string Windows 系统上使用的编码。可选,默认是 "cp936"。
className string 指定要在 jar 包中调用的类名,例如 "com.apidog.Utils"。
method string 指定要在 jar 包中调用的方法名,例如 "add"。
paramTypes string[] 指定要在 jar 包中调用的方法的参数类型,例如 ["int", "int"]。
执行与日志#
执行程序时,已执行的命令会打印在控制台中(仅供参考)。如果结果不符合预期,你可以复制该命令并粘贴到 Shell/CMD 中进行调试。控制台还会打印已执行进程的“标准输出(stdout)”和“标准错误输出(stderr)”。stdout 内容 (不包括末尾的换行符)将作为执行的最终结果。由于历史原因,当 stderr 中存在内容时,pm.execute 会将执行视为失败。这会导 致某些程序在输出警告或错误消息时失败。pm.executeAsync 改为使用进程的退出码来判断执行是否失败。
外部程序的输入与输出#
由于指定的外部程序通过命令行执行,它只能通过命令行参数获取传入的参数。例如,在脚本 pm.executeAsync('add.js', [2, 3]) 中,实际执行的命令是 node add.js 2 3。要在外部脚本 add.js 中获取参数:1.
不同编程语言获取命令行参数的方式不同,请参考对应语言的文档。
2.
命令行参数的类型始终是 string,需要根据实际类型进行转换。
返回值#
如上所述,Apidog 使用 stdout 内容作为程序执行结果。因此,将内容打印到 stdout 即可返回结果。例如,在脚本 const result = await pm.executeAsync('add.js', [2, 3]) 中,可以通过以下方式返回结果:1.
不同编程语言打印到 stdout 的方式不 同,请参考对应语言的文档。
2.
返回类型是 string,需要根据实际类型进行转换。
4.
调用 jar 包中的指定方法时,被调用方法的返回值将作为最终返回值。
抛出错误#
2.
在 JavaScript 中,console.error('Error') 只会打印到 stderr,而不会抛出错误。使用其他语言时也请注意这一点。
调试信息#
由于 pm.executeAsync 使用退出码而不是 stderr 来判断是否成功,因此可以使用 stderr 打印调试信息,而不影响执行。1.
只有 pm.executeAsync 支持这种打印调试信息的方式。
2.
不同编程语言打印到 stderr 的方式不同,请参考对应文档。
从 pm.execute 迁移到 pm.executeAsync#
由于 pm.executeAsync 的返回值是 Promise 类型,因此不能直接将 execute 改为 executeAsync。但你可以使用 async/await 以最小改动进行迁移。Apidog 版本 2.3.24 或更高版本(CLI 版本 1.2.38 或更高版本)支持顶层 await。
1.
将 execute 改为 executeAsync
调用 .jar 包中的指定方法#
此功能要求 Apidog 版本为 2.1.39 或更高版本。它仅支持通过反射调用 jar,不支持像 Spring Boot 这样使用内部运行时反射的 jar。
默认情况下,调用 jar 会调用 Main 类中的 main 方法。如果指定了 options.className,它将覆盖默认行为,改为调用 jar 中的指定方法。调用 jar 中的指定方法与其他外部程序不同。Apidog 会使用内置执行器,通过反射在 jar 中查找该方法并调用它。如果被调用的方法有返回值,它会在转换为字符串后作为最终返回值。否则,其工作方式与其他调用相同,使用 stdout 内容作为返回值。其中 <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 可以省略:1. PHP 程序#
2. Jar 程序#
常见问题#
1. 某些程序需要项目配置文件,缺失时会报错#
could not find `Cargo.toml` in `<...>/ExternalPrograms` or any parent directory
go.mod file not found in current directory or any parent directory; see 'go help modules'
解决方案:使用 pm.executeAsync 并指定 cwd。2. MacOS 内置 Python 3,但没有 Python 2#
使用 pm.executeAsync 并将 command 设置为 "python3"。3. Command xxx not found#
安装对应程序,并将必要目录添加到系统 PATH。有关 Java 安装,请参阅 docs。4. 在某些 Windows 系统上调用外部脚 本时输出乱码#
将 windowsEncoding 设置为 'utf-8'