如何在 Apifox 中调用其他语言(Java、PHP、Python、Go 等)
在一些特定场景下,比如需要在 Apifox 中对文件进行读写、加密、转换格式或者进行其它业务的操作时,仅使用 Apifox 内置的 JS 类库可能无法满足业务需求,这时,就可以借助「外部程序」作为解决方案。
外部程序是保存在「外部程序目录」下的代码文件,可以是 Java 程序归档文件 jar 包,也可以是其他程序的代码源文件,例如 .jar
、.py
、.php
、.js
等后缀的文件。文件需要放到「外部程序目录」下,这个目录可以在页面右上角的「设置->外部程序」中打开。
使用「外部程序」时需要注意两点:
- Apifox 版本必须是 2.3.25 或以上才支持调用外部程序。
- 外部程序是在「沙盒环境」以外运行的,这意味着它有权限访问你电脑上的其他程序、文件和数据,所以要确保外部程序是安全的。
调用「外部程序」的语法
在 Apifox 中调用外部程序可以使用pm.executeAsync()
方法,其语法如下,可将其写在接口的「前置/后置操作」中:
await pm.executeAsync(filePath, args, options)
其内各项参数表示如下,更具体的可参考帮助文档里的解释。
- filePath (string): 外部程序路径。
- args (string[]): 传递给外部程序的参数,数组中每个字符串代表一个参数。其中,非 string 类型会隐式转换为 string 类型。
- options (Object): 其他选项设置,包括:
- command (string): 外部程序的执行命令。非必填,如果不填会自动推断。
- cwd (string): 子进程工作目录。非必填,默认为「外部程序目录」。
- env (Record): 子进程环境变量。非必填,默认为 {}。
- windowsEncoding (string): Windows 系统用使用的编码格式。非必填,默认为 "cp936"。
- className (string): 调用 jar 包中的类名,非必填,详见 jar 包中的方法。
- method (string): 调用 jar 包中的方法名,当 className 有值时为必填项。
- paramTypes (string[]): 指定 jar 包中方法参数的类型,默认根据参数自动推断。
在调用外部程序时,Apifox 会启动一个子进程,在里面以命令行的方式运行你指定的外部程序,然后,会把子进程的标准输出(stdout)作为外部程序的返回值。
这么说可能有点绕,简单讲就是 Apifox 会根据pm.executeAsync()
方法里的参数生成一个命令,然后用命令去执行这个外部程序,并捕获输出的结果。例如:脚本pm.executeAsync('add.py', ['2', '3'])
的实际执行命令为python add.py 2 3
。
举个更具体的例子。
假设你有一个 Python 脚本,用于计算两个数字的和。现在,你想在 Apifox 中调用这个外部的 Python 脚本,就可以使用pm.executeAsync()
方法,具体如下。
步骤 1:准备外部程序
首先,你需要创建一个 Python 文件并将其放到「外部程序目录」下,例如add.py
,在脚本中,你一般需要处理传入的参数,并生成相应的输出。
# add.py
import sys
# 从命令行参数中获取两个数字
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
# 计算两个数字的和
result = num1 + num2
# 将结果打印到标准输出(stdout)
print(result)
处理传入的参数
外部程序在 Apifox 中是以命令行的方式执行的,所以外部程序只能从命令行中获取到传入的参数。
上述脚本中的 sys.argv
是 Python 用于获取命令行参数的方法。例如使用pm.executeAsync('add.py', [2, 3])
调用外部脚本,其实际执行命令为python add.py 2 3
,则在外部脚本add.py
中,获取参数的方式为:
# 从命令行参数中获取两个数字
num1 = int(sys.argv[1]) // 2
num2 = int(sys.argv[2]) // 3
每种编程语言获取命令行参数的方式与该语言的语法相关联,不同的编程语言会有不同的机制来处理命令行参数,举例来说:
- 在 Python 中,你可以使用
sys.argv
列表来访问命令行参数。 - 在 JavaScript 中,如果你在 Node.js 环境下运行脚本,你可以使用
process.argv
来获取命令行参数。 - 在 Java 中,命令行参数可以通过
args[]
参数传递给main()
方法。
生成相应的输出
Apifox 不会捕获函数的返回值(return),而是依赖于程序的标准输出(stdout)。
上述脚本里的print()
作为 Python 的标准输出(stdout),将计算结果输出到控制台或终端,Apifox 会捕获到这个输出结果,所以你将结果打印出来就可以将其返回。其它编程语言如 JavaScript 的console.log()
、Java 的 System.out.println()
也作为标准输出,具体取决于每种编程语言的语法。
外部程序建议先进行单独测试,确保其可以独立运行并产生预期结果,然后再在 Apifox 中调用,例如使用命令行python add.py 2 3
运行这个文件,就会打印出结果。
其它类型的外部程序,比如要将一个图片文件转成 Base64、读取或保存图片文件、将 Word、PDF 等文件进行加密或者其它一系列你需要的操作,都建议先手动运行程序并检查输出。
步骤 2:在前置/后置操作中调用
外部程序准备好以后,你可以在 Apifox 的「前置/后置操作」中创建一个自定义脚本,然后使用 pm.executeAsync()
方法来调用「步骤一」中的外部程序。以下是一个示例:
// 使用 pm.executeAsync 调用 Python 脚本
async function callPythonScript() {
// 外部程序的路径为 add.py
const scriptPath = 'add.py';
// 传递给 Python 脚本的参数,例如两个数字 2 和 3
const args = ['2', '3'];
try {
// 调用 Python 脚本,并等待结果
const result = await pm.executeAsync(scriptPath, args);
console.log('Result:', result);
} catch (error) {
console.error('Error:', error);
}
}
// 调用函数开始执行
callPythonScript();
这个示例可以简化成下面这样的:
// 外部程序路径,传递参数
const result = await pm.executeAsync('add.py', ['2', '3'])
console.log('Result:', result);
传递的参数除了常量/固定值以外,你还可以通过变量的方式进行传递,例如:
// 读取环境变量的值
const scriptPath = pm.environment.get('scriptPath')
const arg1 = pm.environment.get('arg1')
const arg2 = pm.environment.get('arg2')
const result = await pm.executeAsync(scriptPath, [arg1, arg2])
console.log('Result:', result);
Apifox 会根据你提供的参数拼接出一个命令字符串,比如这个例子中pm.executeAsync('add.py', ['2', '3'])
方法拼接成的命令就是:
python add.py 2 3
这跟你在本地运行这个add.py
文件时使用的命令相一致。
当你在 Apifox 中发送请求时,会执行这个 JavaScript 脚本,并通过生成的命令调用外部程序 add.py
,以获取外部程序的输出结果,如下图所示:
在 Apifox 中获取到的返回结果为 String 类型,你可根据实际需要进行类型转换。结果获取到之后,可将结果存储到环境变量中,以供取用,语法参考如下:
pm.environment.set('变量名', '变量值');
常见问题
1.macOS 提示找不到 Python 命令
在 macOS 系统上,默认安装了 Python 3 而不是 Python 2,要执行 Python 脚本,可使用pm.executeAsync()
方法并设置参数command
值为"python3"
来确保使用正确的 Python 版本,例如:
await pm.executeAsync('demo.py', [], { command: 'python3' })
2.部分 Windows 系统返回中文乱码
可设置 windowsEncoding
参数值为 'utf8'
,例如:
await pm.executeAsync('demo.js', [], { windowsEncoding: 'utf8' })
总结
本文仅简要介绍怎么在 Apifox 中调用外部程序,并讲解了基本的语法。想要进一步了解,可以访问 Apifox 帮助文档的调用其它编程语言模块,如果有遇到什么问题,也可以在用户群向我们反馈!
想了解更多关于 Apifox 最佳实践,可前往 Apifox 帮助文档查看。如果使用中有任何问题或建议,欢迎随时在用户群反馈给我们。