Postman Pre-request Script 详细讲解与高级技巧

一、基础概念

1.1 什么是Pre-request Script?

  • 在发送请求之前自动执行的JavaScript代码

  • 执行时机:在请求发送到服务器之前

  • 主要用途:准备请求数据、设置环境变量、生成签名等

1.2 基本结构

复制代码
// 示例:简单的pre-request脚本
pm.environment.set("timestamp", Date.now());
console.log("请求即将发送:", pm.request.url.toString());

二、核心功能详解

2.1 变量操作

复制代码
// 设置环境变量
pm.environment.set("api_key", "your-api-key-123");
pm.environment.set("timestamp", new Date().getTime());

// 设置全局变量
pm.globals.set("base_url", "https://api.example.com");

// 设置集合变量
pm.collectionVariables.set("version", "v1");

// 获取变量
let token = pm.environment.get("access_token");
let baseUrl = pm.globals.get("base_url");

// 取消设置变量
pm.environment.unset("temp_token");

2.2 请求修改

复制代码
// 修改请求头
pm.request.headers.add({
    key: "X-Custom-Header",
    value: "custom-value"
});

// 修改URL参数
const url = new URL(pm.request.url.toString());
url.searchParams.set("timestamp", Date.now());
pm.request.url = url.toString();

// 修改请求体(仅适用于raw body)
if (pm.request.body && pm.request.body.mode === "raw") {
    const rawBody = JSON.parse(pm.request.body.raw);
    rawBody.timestamp = new Date().toISOString();
    pm.request.body.raw = JSON.stringify(rawBody);
}

2.3 条件逻辑

复制代码
// 根据环境执行不同操作
const env = pm.environment.get("env");
if (env === "production") {
    pm.request.headers.add({
        key: "Authorization",
        value: "Bearer " + pm.environment.get("prod_token")
    });
} else {
    pm.request.headers.add({
        key: "Authorization",
        value: "Bearer " + pm.environment.get("dev_token")
    });
}

三、高级"骚操作"

3.1 动态签名生成

复制代码
// HMAC SHA256签名示例
const CryptoJS = require("crypto-js");

function generateSignature(secret, method, path, body, timestamp) {
    const stringToSign = `${method}\n${path}\n${timestamp}\n${body}`;
    return CryptoJS.HmacSHA256(stringToSign, secret).toString(CryptoJS.enc.Hex);
}

// 使用示例
const secret = pm.environment.get("api_secret");
const method = pm.request.method;
const path = new URL(pm.request.url.toString()).pathname;
const body = pm.request.body?.raw || "";
const timestamp = Date.now();

const signature = generateSignature(secret, method, path, body, timestamp);

pm.request.headers.add({
    key: "X-Signature",
    value: signature
});
pm.request.headers.add({
    key: "X-Timestamp",
    value: timestamp.toString()
});

3.2 请求链与依赖处理

复制代码
// 获取前一个请求的响应数据
const previousResponse = pm.getGlobal("previous_response");
if (previousResponse) {
    const data = JSON.parse(previousResponse);
    pm.environment.set("session_id", data.session_id);
}

// 设置本次请求完成后的回调
pm.sendRequest({
    url: "https://auth.example.com/token",
    method: "POST",
    header: { "Content-Type": "application/json" },
    body: {
        mode: "raw",
        raw: JSON.stringify({
            grant_type: "client_credentials",
            client_id: pm.environment.get("client_id"),
            client_secret: pm.environment.get("client_secret")
        })
    }
}, function (err, response) {
    if (!err) {
        const token = response.json().access_token;
        pm.environment.set("access_token", token);
        
        // 继续发送主请求
        pm.request.headers.add({
            key: "Authorization",
            value: `Bearer ${token}`
        });
    }
});

3.3 数据加密

复制代码
// AES加密示例
const CryptoJS = require("crypto-js");

function encryptData(data, key) {
    const encrypted = CryptoJS.AES.encrypt(
        JSON.stringify(data),
        key
    ).toString();
    return encrypted;
}

// 加密请求体
const requestBody = {
    data: "sensitive information",
    timestamp: new Date().toISOString()
};

const encryptedBody = encryptData(
    requestBody,
    pm.environment.get("encryption_key")
);

pm.request.body = {
    mode: "raw",
    raw: JSON.stringify({ payload: encryptedBody })
};

3.4 随机数据生成

复制代码
// 生成随机数据
function generateRandomString(length) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
}

function generateRandomEmail() {
    return `test${Date.now()}@example.com`;
}

// 使用示例
pm.environment.set("random_email", generateRandomEmail());
pm.environment.set("order_id", `ORD${Date.now()}${Math.floor(Math.random() * 1000)}`);

3.5 性能测试相关

复制代码
// 记录请求开始时间
pm.environment.set("request_start_time", Date.now());

// 在Tests脚本中计算耗时
// Tests脚本中可以这样计算:
// const startTime = pm.environment.get("request_start_time");
// const endTime = Date.now();
// console.log(`请求耗时: ${endTime - startTime}ms`);

3.6 工作流控制

复制代码
// 条件跳过请求
const skipRequest = pm.environment.get("skip_request");
if (skipRequest === "true") {
    // 设置请求为不发送
    pm.request.headers.add({
        key: "X-Skip-Request",
        value: "true"
    });
    // 或者通过抛出错误停止
    // throw new Error("跳过此请求");
}

// 最大重试次数控制
let retryCount = pm.environment.get("retry_count") || 0;
if (retryCount >= 3) {
    throw new Error("已达到最大重试次数");
}
pm.environment.set("retry_count", retryCount + 1);

3.7 文件操作模拟

复制代码
// 模拟文件上传
const fileContent = "This is a test file content";
const fileName = `test_${Date.now()}.txt`;

// 创建FormData
const formdata = new FormData();
formdata.append("file", new Blob([fileContent]), fileName);
formdata.append("description", "Test file upload");

// 注意:Postman中文件上传通常通过界面操作
// 这里主要展示如何生成相关数据

3.8 缓存控制

复制代码
// 生成ETag
function generateETag(data) {
    const CryptoJS = require("crypto-js");
    return CryptoJS.MD5(JSON.stringify(data)).toString();
}

// 检查缓存
const cachedData = pm.environment.get("cached_data");
const cacheKey = pm.environment.get("cache_key");

if (cachedData && cacheKey === pm.request.url.toString()) {
    // 设置If-None-Match头
    pm.request.headers.add({
        key: "If-None-Match",
        value: generateETag(cachedData)
    });
}

四、实用技巧

4.1 调试技巧

复制代码
// 使用console.log调试
console.log("当前环境:", pm.environment.name);
console.log("请求URL:", pm.request.url.toString());
console.log("请求方法:", pm.request.method);
console.log("所有头信息:", pm.request.headers);

// 使用try-catch捕获错误
try {
    // 可能出错的代码
    const data = JSON.parse(pm.environment.get("config"));
} catch (error) {
    console.error("解析配置出错:", error.message);
    // 设置默认值
    pm.environment.set("config", "{}");
}

4.2 性能优化

复制代码
// 避免重复计算
if (!pm.environment.get("cached_timestamp")) {
    const timestamp = Date.now();
    pm.environment.set("cached_timestamp", timestamp);
    pm.environment.set("cached_timestamp_expiry", timestamp + 5000); // 5秒缓存
}

4.3 最佳实践

复制代码
// 1. 使用函数组织代码
function setupAuth() {
    // 认证逻辑
}

function addCommonHeaders() {
    // 添加公共头
}

function validateRequest() {
    // 请求验证
}

// 2. 模块化执行
setupAuth();
addCommonHeaders();
validateRequest();

// 3. 清理临时变量
pm.environment.unset("temp_variable");

五、注意事项

  1. 执行顺序:Pre-request Script在每次请求前都会运行

  2. 性能影响:复杂脚本可能延迟请求发送

  3. 错误处理:脚本错误会导致请求失败

  4. 变量作用域:注意环境变量、全局变量的区别

  5. 安全性:不要在脚本中硬编码敏感信息

六、实际应用场景

  1. API签名认证:自动生成签名

  2. 数据准备:生成测试数据

  3. 请求转换:修改请求格式

  4. 条件测试:根据不同场景设置不同参数

  5. 工作流管理:控制请求执行顺序

  6. 性能监控:记录请求时间戳

  7. 缓存管理:实现客户端缓存逻辑

这些高级技巧可以大大提升Postman的自动化测试能力,特别是在复杂的API测试场景中。

相关推荐
虫小宝2 小时前
企业微信客户联系API在Java微服务中的幂等性设计与重试机制
java·微服务·企业微信
txinyu的博客2 小时前
Reactor 模型全解析
java·linux·开发语言·c++
IMPYLH2 小时前
Lua 的 Package 模块
java·开发语言·笔记·后端·junit·游戏引擎·lua
sunnyday04262 小时前
API安全防护:签名验证与数据加密最佳实践
java·spring boot·后端·安全
henujolly2 小时前
useeffect和uselayouteffect
前端·javascript·react.js
间彧2 小时前
java类的生命周期及注意事项
java
Ulyanov2 小时前
Python射击游戏开发实战:从系统架构到高级编程技巧
开发语言·前端·python·系统架构·tkinter·gui开发
会飞的小新2 小时前
Java 应用程序已被安全阻止 —— 原因分析与解决方案
java·安全
点云SLAM2 小时前
C++依赖注入(Dependency Injection DI)vs单例设计模式(Singleton)
开发语言·c++·单例模式·设计模式·日志配置·依赖注入di·大项目系统