理解和掌握 Apifox 前后置操作——“脚本”篇

理解和掌握 Apifox 前后置操作——“脚本”篇

当你打开 Apifox 中某个接口的“修改”或“运行”页面时,会看到"前置操作"和"后置操作"这两个选项卡。在这些选项卡中,除了常见的设置环境变量、数据库操作等功能外,还有一个"自定义脚本"选项。

理解和掌握 Apifox 前后置操作——“脚本”篇


这个功能允许你编写 JavaScript 代码,在接口请求发送前或响应接收后执行特定的逻辑。


前置脚本会在请求真正发出之前运行,可以动态修改请求的参数、头部信息或请求体内容。


后置脚本则在接口返回响应后立即执行,通常用来处理响应数据、提取需要的信息或进行结果验证。

认识前后置脚本的工作原理


接口测试的完整流程:准备请求数据 → 发送请求 → 接收响应 → 处理响应数据。前置脚本就在第一步和第二步之间执行,后置脚本则在第三步和第四步之间执行。

apifox前后置脚本的工作原理


在 Apifox 中,这些脚本使用 JavaScript 语言编写。你不需要是 JavaScript 专家,因为 Apifox 提供了丰富的内置方法和对象,让脚本编写变得相对简单。最常用的对象包括 pm(提供各种实用方法)、pm.request(操作请求相关数据)和 pm.response(处理响应相关数据)。

前置脚本的典型应用场景


前置脚本最常见的用途是处理接口的签名加密逻辑。很多 API 为了保证安全性,都会要求客户端对请求参数进行签名验证。这个过程通常包括参数排序、字符串拼接、加密计算等步骤。


以一个常见的签名流程为例,假设接口要求按以下步骤生成签名:将所有请求参数按键名排序,拼接成查询字符串格式,再加上密钥进行 MD5 加密。你可以在前置脚本中这样实现:

const CryptoJS = require('crypto-js');

// ---------- 签名生成函数 ----------
function generateSignature(params, secretKey) {
    // 按参数名排序
    const sortedKeys = Object.keys(params).sort();
    // 拼接参数字符串 key=value&key=value
    const paramString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
    // 加上密钥
    const stringToSign = paramString + '&key=' + secretKey;
    // 生成 MD5 签名并返回
    return CryptoJS.MD5(stringToSign).toString();
}

// ---------- 获取环境变量 ----------
const appId = pm.environment.get('app_id');
const secretKey = pm.environment.get('secret_key');

if (!appId || !secretKey) {
    console.error('请先在环境变量中配置 app_id 和 secret_key');
} else {
    // ---------- 准备请求参数 ----------
    const params = {
        appId: String(appId),                            // 应用 ID
        timestamp: String(Math.floor(Date.now() / 1000)), // 秒级时间戳
        nonce: Math.random().toString(36).substring(2, 15) // 随机字符串
    };

    // ---------- 生成签名 ----------
    params.signature = generateSignature(params, secretKey);

    // ---------- 输出调试信息 ----------
    console.log('请求参数:', params);

    // ---------- 将参数添加到请求查询参数 ----------
    Object.keys(params).forEach(key => {
        pm.request.url.query.upsert({ key: key, value: params[key] });
    });
}
apifox签名加密


除了 MD5 签名,前置脚本还可以处理更复杂的加密算法,比如 HMAC-SHA256、RSA 签名等。对于需要对请求体进行签名的场景,你可以获取请求体内容进行处理:

const CryptoJS = require('crypto-js');

// 获取请求 body
const requestBody = pm.request.body?.raw || '';

// 时间戳(秒级)
const timestamp = Math.floor(Date.now() / 1000).toString();

// 拼接签名字符串
const secretKey = pm.environment.get('secret_key') || '';
const appSecret = pm.environment.get('app_secret') || '';
const signString = requestBody + timestamp + secretKey;

// 生成 HMAC-SHA256 签名(hex 或 Base64 可根据接口要求调整)
const signature = CryptoJS.HmacSHA256(signString, appSecret).toString(); 

// 输出调试信息
console.log('requestBody:', requestBody);
console.log('timestamp:', timestamp);
console.log('signature:', signature);

// 添加到请求头
pm.request.headers.upsert({ key: 'X-Timestamp', value: timestamp });
pm.request.headers.upsert({ key: 'X-Signature', value: signature });


前置脚本还经常用于处理动态 Token 的获取和设置。某些接口需要短期有效的访问令牌,你可以在脚本中检查 Token 是否过期,必要时重新获取:

// 获取 token 过期时间(单位与 currentTime 保持一致)
const tokenExpiry = Number(pm.environment.get('token_expiry')) || 0;
const currentTime = Date.now(); // 毫秒单位,如果 tokenExpiry 是秒需 /1000

if (!tokenExpiry || currentTime > tokenExpiry) {
    console.log('Token已过期,需要重新获取');
    // TODO: 在这里添加获取新 token 的逻辑,并更新环境变量
    // pm.environment.set('access_token', newToken);
    // pm.environment.set('token_expiry', newExpiryTime);
}

const token = pm.environment.get('access_token');
if (token) {
    pm.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + token });
    console.log('使用 token:', token);
}

后置脚本的核心价值


后置脚本的主要作用是处理响应数据。最典型的应用是提取响应中的数据并保存到环境变量中,供后续接口使用,还有就是处理一些解密逻辑。


假设登录接口返回的响应格式如下:

{
    "code": 200,
    "message": "success",
    "data": {
        "token": "eyJhbGciOiJIUzI1NiIs...",
        "userId": 12345
    }
}


你可以用后置脚本提取 token 和 userId:

const responseJson = pm.response.json();
if (responseJson.code === 200) {
    pm.environment.set('jwt_token', responseJson.data.token);
    pm.environment.set('user_id', responseJson.data.userId);
}


这样,后续需要认证的接口就可以直接使用这些环境变量了。


后置脚本还可以进行响应断言,验证接口返回的数据是否符合预期:

pm.test("响应状态码应该是200", function () {
    pm.response.to.have.status(200);
});

pm.test("响应应该包含token", function () {
    const jsonData = pm.response.json();
    pm.expect(jsonData.data).to.have.property('token');
});


如果要进行解密操作的话,可以参考帮助文档里的 JS 类库 模块,里面有相当多的使用示例。

脚本编写的实用技巧

自定义脚本的右边有一些简单的代码片段,你可以根据需要进行选择。

apifox脚本


写脚本的时候也可以根据帮助文档的 pm 脚本 API 来写,或者将你的需求丢给 AI,让 AI 来帮你写脚本,这样更快一些。

调试脚本的方法


脚本编写过程中难免会遇到问题,Apifox 提供了控制台功能帮助调试。你可以使用 console.log() 输出变量值:

const token = pm.environment.get('jwt_token');
console.log('当前token:', token);

const responseJson = pm.response.json();
console.log('响应数据:', responseJson);


这些输出会显示在 Apifox 的控制台中,方便你查看脚本的执行情况。

apifox调试脚本的方法


当脚本出现错误时,控制台也会显示具体的错误信息。常见的错误包括语法错误、变量未定义、JSON 解析失败等。根据错误提示,你可以快速定位和修复问题。

脚本使用的最佳实践


编写脚本时,有几个实践建议值得注意。首先是错误处理,始终要考虑可能出现的异常情况:

try {
    const responseJson = pm.response.json();
    if (responseJson && responseJson.data) {
        pm.environment.set('user_token', responseJson.data.token);
    }
} catch (error) {
    console.log('JSON解析失败:', error.message);
}


其次是脚本的可维护性,对于复杂的逻辑,建议将其封装成函数:

function extractUserInfo(response) {
    try {
        const data = response.json();
        return {
            userId: data.data.userId,
            userName: data.data.userName,
            userRole: data.data.role
        };
    } catch (error) {
        console.log('提取用户信息失败:', error);
        return null;
    }
}

const userInfo = extractUserInfo(pm.response);
if (userInfo) {
    pm.environment.set('current_user_id', userInfo.userId);
    pm.environment.set('current_user_name', userInfo.userName);
}


最后是性能考虑,避免在脚本中执行过于复杂的计算或大量的循环操作,这可能会影响测试的执行速度。


通过合理使用前后置脚本,你可以让 Apifox 的接口测试变得更加智能和高效。从简单的参数设置到复杂的数据处理,脚本功能为接口测试提供了无限可能。随着对这些功能的深入了解和实践,你会发现接口测试不再是重复性的手工操作,而是可以高度自动化的智能流程。

订阅
qrcode

订阅

随时随地获取 Apifox 最新动态