Apifox 教程:如何实现跨语言调用(Java、PHP、Python、Go 等)

在一些特定场景下,比如需要在 Apifox 中对文件进行读写、加密、转换格式或者进行其它业务的操作时,仅使用 Apifox 内置的 JS 类库可能无法满足业务需求,这时,就可以借助「外部程序」作为解决方案。

外部程序是保存在「外部程序目录」下的代码文件,可以是 Java 程序归档文件 jar 包,也可以是其他程序的代码源文件,例如 .jar、.py、.php、.js 等后缀的文件。文件需要放到「外部程序目录」下,这个目录可以在页面右上角的「设置 -> 外部程序」中打开。

使用「外部程序」时需要注意两点:

  1. Apifox 版本必须是 2.3.25 或以上才支持调用外部程序。
  2. 外部程序是在「沙盒环境」以外运行的,这意味着它有权限访问你电脑上的其他程序、文件和数据,所以要确保外部程序是安全的。

调用「外部程序」的语法

在 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() 方法,具体如下。

准备外部程序

首先,你需要创建一个 Python 文件并将其放到「外部程序目录」下,例如 add.py,在脚本中,你一般需要处理传入的参数,并生成相应的输出。

# add.pyimport sys
# 从命令行参数中获取两个数字num1 = int(sys.argv[1])num2 = int(sys.argv[2])
# 计算两个数字的和result = num1 + num2
# 将结果打印到标准输出(stdout)print(result)

1 处理传入的参数

外部程序在 Apifox 中是以命令行的方式执行的,所以外部程序只能从命令行中获取到传入的参数。

上述脚本中的 sys.argv 是 Python 用于获取命令行参数的方法。例如使用 pm.executeAsync('add.py', [2, 3]) 调用外部脚本,其实际执行命令为 python add.py 2 3,则在外部脚本 add.py 中,获取参数的方式为:

# 从命令行参数中获取两个数字num1 = int(sys.argv[1]) // 2num2 = int(sys.argv[2]) // 3

每种编程语言获取命令行参数的方式与该语言的语法相关联,不同的编程语言会有不同的机制来处理命令行参数,举例来说:

  • 在 Python 中,你可以使用 sys.argv 列表来访问命令行参数。
  • 在 JavaScript 中,如果你在 Node.js 环境下运行脚本,你可以使用 process.argv 来获取命令行参数。
  • 在 Java 中,命令行参数可以通过 args[] 参数传递给 main() 方法。

2 生成相应的输出

Apifox 不会捕获函数的返回值 (return) ,而是依赖于程序的标准输出 (stdout)

上述脚本里的 print() 作为 Python 的标准输出 (stdout) ,将计算结果输出到控制台或终端,Apifox 会捕获到这个输出结果,所以你将结果打印出来就可以将其返回。其它编程语言如 JavaScript 的 console.log()、Java 的 System.out.println() 也作为标准输出,具体取决于每种编程语言的语法。

外部程序建议先进行单独测试,确保其可以独立运行并产生预期结果,然后再在 Apifox 中调用,例如使用命令行 python add.py 2 3 运行这个文件,就会打印出结果。

其它类型的外部程序,比如要将一个图片文件转成 Base64、读取或保存图片文件、将 Word、PDF 等文件进行加密或者其它一系列你需要的操作,都建议先手动运行程序并检查输出。

在前置/后置操作中调用

外部程序准备好以后,你可以在 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' })
相关推荐
Wang's Blog39 分钟前
Webpack: 持久化缓存大幅提升构建性能
前端·缓存·webpack
程序员储物箱41 分钟前
Vue报错:Module not found: Error: Can‘t resolve ‘less-loader‘ in ‘文件地址‘
前端·vue
乐吾乐科技42 分钟前
【国产开源可视化引擎Meta2d.js】锚点
前端·编辑器·web·数据可视化·大屏端
Her...1 小时前
electron教程(一)创建项目
前端·javascript·electron
logstach2 小时前
QML-Grid和OpacityMask
前端·qml
C+ 安口木3 小时前
前端代码规范 - 日志打印规范
前端·代码规范
Jesse_Kyrie3 小时前
配置windows环境下独立浏览器爬虫方案【不依赖系统环境与chrome】
前端·chrome·爬虫·python·scrapy
詩筠4 小时前
SpringBoot实战:轻松实现XSS攻击防御(注解和过滤器)
java·spring boot·后端·xss
鸽鸽程序猿4 小时前
【C语言】分支(选择)和循环语句
c语言·开发语言·学习·程序人生·学习方法·visual studio
fengzhuzhigu4 小时前
Go源码--channel源码解读
开发语言·后端·golang