Skip to content

Commit 9f7fda7

Browse files
committed
feat: add pm.sendRequest() method for sending HTTP requests in pre-scripts
1 parent 9db6a96 commit 9f7fda7

5 files changed

Lines changed: 124 additions & 4 deletions

File tree

docs/SCRIPT_API_REFERENCE_zh.md

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
| `pm.setGlobalVariable(key, value)` | 设置全局变量(实际存储在环境变量中) | `pm.setGlobalVariable('baseUrl', 'https://api.com')` |
4949
| `pm.getGlobalVariable(key)` | 获取全局变量(实际从环境变量读取) | `pm.getGlobalVariable('baseUrl')` |
5050
| `pm.getResponseCookie(name)` | 获取响应中的 Cookie | `pm.getResponseCookie('sessionId')` |
51+
| `pm.sendRequest(options, callback)` | 在脚本中发送额外 HTTP 请求 | `pm.sendRequest({ url: 'https://api.com' }, (err, resp) => {})` |
5152

5253
### 外部数据源对象
5354

@@ -58,6 +59,43 @@
5859
| `pm.es` / `pm.elasticsearch` | Elasticsearch 请求与查询 | `request(options)``query(options)` |
5960
| `pm.influx` / `pm.influxdb` | InfluxDB Flux / InfluxQL 查询与写入 | `query(options)``write(options)``request(options)` |
6061

62+
### pm.sendRequest()
63+
64+
`pm.sendRequest()` 已支持在脚本中主动发起额外 HTTP 请求,适用于前置脚本里刷新 token、拉取签名、预热上下文数据等场景。
65+
66+
回调函数签名为 `(err, response)`
67+
68+
- `err`:请求失败时返回错误对象,包含 `message``name`
69+
- `response`:成功时返回响应包装对象,可使用 `response.code``response.status``response.headers.get()``response.text()``response.json()`
70+
71+
支持的请求格式:
72+
73+
- 直接传 URL 字符串,默认 `GET`
74+
- 传对象:`url``method``header``body`
75+
- `body.mode` 当前支持 `raw``formdata``urlencoded`
76+
77+
示例:
78+
79+
```javascript
80+
pm.sendRequest({
81+
url: 'https://httpbin.org/get?source=easy-postman&from=pre-script',
82+
method: 'GET',
83+
header: {
84+
'X-Debug-Token': pm.environment.get('debugToken') || 'demo-token'
85+
}
86+
}, function (err, response) {
87+
if (err) {
88+
console.error('请求失败:', err.message);
89+
return;
90+
}
91+
92+
const data = response.json();
93+
pm.environment.set('lastHttpbinUrl', data.url || '');
94+
pm.environment.set('lastHttpbinSource', data.args?.source || '');
95+
console.log('httpbin args:', data.args);
96+
});
97+
```
98+
6199
---
62100
63101
## pm.environment - 环境变量
@@ -2244,8 +2282,35 @@ const currentTime = Date.now();
22442282
// 检查 token 是否过期(提前5分钟刷新)
22452283
if (!tokenExpireTime || currentTime > (parseInt(tokenExpireTime) - 300000)) {
22462284
console.log('Token 即将过期或已过期,需要刷新');
2247-
// 在实际环境中,这里应该触发刷新 token 的逻辑
2248-
// 由于不支持 pm.sendRequest,建议在测试流程中手动添加刷新 token 的请求
2285+
pm.sendRequest({
2286+
url: pm.environment.get('authUrl'),
2287+
method: 'POST',
2288+
header: {
2289+
'Content-Type': 'application/json'
2290+
},
2291+
body: {
2292+
mode: 'raw',
2293+
raw: JSON.stringify({
2294+
refreshToken: pm.environment.get('refreshToken')
2295+
})
2296+
}
2297+
}, function (err, response) {
2298+
if (err) {
2299+
console.error('刷新 token 失败:', err.message);
2300+
return;
2301+
}
2302+
2303+
const data = response.json();
2304+
const token = data.accessToken || data.token;
2305+
if (token) {
2306+
pm.environment.set('authToken', token);
2307+
pm.request.headers.upsert({
2308+
key: 'Authorization',
2309+
value: 'Bearer ' + token
2310+
});
2311+
console.log('✓ Token 刷新成功,已更新认证头');
2312+
}
2313+
});
22492314
} else {
22502315
const token = pm.environment.get('authToken');
22512316
if (token) {
@@ -2981,7 +3046,6 @@ pm.environment.set('performanceStats', JSON.stringify(stats));
29813046
- 库代码会被缓存,重复加载不会影响性能
29823047

29833048
8. **不支持的功能**
2984-
-`pm.sendRequest()` - 不支持在脚本中发送 HTTP 请求
29853049
-`pm.iterationData` - 不支持迭代数据(但支持 CSV 数据驱动)
29863050
-`pm.info` - 不支持请求元信息访问
29873051
- ❌ 完整的 Chai.js 断言库

docs/SCRIPT_SNIPPETS_QUICK_REFERENCE.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [获取时间戳](#获取时间戳)
1212
- [添加请求头](#添加请求头)
1313
- [添加查询参数](#添加查询参数)
14+
- [前置脚本发送 HTTP 请求](#前置脚本发送-http-请求)
1415

1516
### 认证相关
1617
- [Bearer Token 认证](#bearer-token-认证)
@@ -126,6 +127,29 @@ pm.request.params.add({
126127
});
127128
```
128129

130+
### 前置脚本发送 HTTP 请求
131+
```javascript
132+
// Pre-request Script
133+
pm.sendRequest({
134+
url: 'https://httpbin.org/get?source=easy-postman&from=pre-script',
135+
method: 'GET',
136+
header: {
137+
'X-Debug-Token': pm.environment.get('debugToken') || 'demo-token'
138+
}
139+
}, function (err, response) {
140+
if (err) {
141+
console.error('请求失败:', err.message);
142+
return;
143+
}
144+
145+
const data = response.json();
146+
pm.environment.set('lastHttpbinUrl', data.url || '');
147+
pm.environment.set('lastHttpbinSource', data.args?.source || '');
148+
console.log('响应状态:', response.code, response.status);
149+
console.log('httpbin args:', data.args);
150+
});
151+
```
152+
129153
---
130154
131155
## 认证相关
@@ -205,7 +229,34 @@ const tokenExpireTime = pm.environment.get('tokenExpireTime');
205229
const currentTime = Date.now();
206230

207231
if (!tokenExpireTime || currentTime > (parseInt(tokenExpireTime) - 300000)) {
208-
console.warn('⚠ Token 即将过期,请手动刷新');
232+
pm.sendRequest({
233+
url: pm.environment.get('authUrl'),
234+
method: 'POST',
235+
header: {
236+
'Content-Type': 'application/json'
237+
},
238+
body: {
239+
mode: 'raw',
240+
raw: JSON.stringify({
241+
refreshToken: pm.environment.get('refreshToken')
242+
})
243+
}
244+
}, function (err, response) {
245+
if (err) {
246+
console.error('刷新失败:', err.message);
247+
return;
248+
}
249+
250+
const data = response.json();
251+
const token = data.accessToken || data.token;
252+
if (token) {
253+
pm.environment.set('authToken', token);
254+
pm.request.headers.upsert({
255+
key: 'Authorization',
256+
value: 'Bearer ' + token
257+
});
258+
}
259+
});
209260
} else {
210261
const token = pm.environment.get('authToken');
211262
pm.request.headers.upsert({

easy-postman-app/src/main/java/com/laker/postman/model/SnippetType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public enum SnippetType {
1515
DYNAMIC_MODIFY_HEADER(Category.PRE_SCRIPT, "snippet.dynamicModifyHeader.title", "snippet.dynamicModifyHeader.desc", "// Get and modify request headers\nif (pm.request && pm.request.headers) {\n // Add custom request header\n pm.request.headers.add({\n key: 'X-Custom-Header',\n value: 'Custom-Value-' + Date.now()\n });\n \n // Add authentication info\n pm.request.headers.add({\n key: 'Authorization',\n value: 'Bearer ' + pm.environment.get('token')\n });\n \n console.log('Dynamically added request headers');\n}\n"),
1616
DYNAMIC_MODIFY_BODY(Category.PRE_SCRIPT, "snippet.dynamicModifyBody.title", "snippet.dynamicModifyBody.desc", "// Dynamically modify formData, urlencoded, formFiles, params\nif (pm.request.formData) {\n pm.request.formData.add({ key: 'extraField', value: 'extraValue' });\n console.log('Added formData field');\n}\nif (pm.request.urlencoded) {\n pm.request.urlencoded.add({ key: 'token', value: pm.environment.get('token') });\n console.log('Added urlencoded field');\n}\nif (pm.request.formFiles) {\n pm.request.formFiles.add({ key: 'file', value: '/path/to/file' });\n console.log('Added formFiles field');\n}\n\n// Note: You need to use related variables or fields in the actual request body/params for it to take effect"),
1717
DYNAMIC_MODIFY_PARAM(Category.PRE_SCRIPT, "snippet.dynamicModifyParam.title", "snippet.dynamicModifyParam.desc", "// Dynamically add to params\n pm.request.params.add({ key: 'timestamp', value: Date.now() });\n "),
18+
SEND_HTTP_REQUEST(Category.PRE_SCRIPT, "snippet.sendHttpRequest.title", "snippet.sendHttpRequest.desc", "// 前置脚本里发送一个可直接测试的 HTTP 请求\npm.sendRequest({\n url: 'https://httpbin.org/get?source=easy-postman&from=pre-script',\n method: 'GET',\n header: {\n 'X-Debug-Token': pm.environment.get('debugToken') || 'demo-token'\n }\n}, function (err, response) {\n if (err) {\n console.error('请求失败:', err.message);\n return;\n }\n\n pm.test('httpbin 请求返回 200', function () {\n pm.expect(response.code).to.equal(200);\n });\n\n var data = response.json();\n pm.environment.set('lastHttpbinUrl', data.url || '');\n pm.environment.set('lastHttpbinSource', data.args && data.args.source ? data.args.source : '');\n\n console.log('响应状态:', response.code, response.status);\n console.log('httpbin url:', data.url);\n console.log('httpbin args:', JSON.stringify(data.args));\n});"),
1819

1920
// Assertion category
2021
ASSERT_STATUS_200(Category.ASSERT, "snippet.assertStatus200.title", "snippet.assertStatus200.desc", "pm.test('Status code is 200', function () {\n pm.response.to.have.status(200);\n});"),

easy-postman-app/src/main/resources/messages_en.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,8 @@ snippet.dynamicModifyBody.title=Pre-Script: Dynamic Modify Body
12821282
snippet.dynamicModifyBody.desc=Dynamically modify request body and all parameters (formData, urlencoded, formFiles)
12831283
snippet.dynamicModifyParam.title=Pre-Script: Dynamic Modify Param
12841284
snippet.dynamicModifyParam.desc=Dynamically add signature, timestamp, etc. to request URL and parameters
1285+
snippet.sendHttpRequest.title=Pre-Script: Send HTTP Request
1286+
snippet.sendHttpRequest.desc=Send an auxiliary HTTP request in pre-script and process the response
12851287
snippet.assertStatus200.title=Assert: Status Code 200
12861288
snippet.assertStatus200.desc=Assert response status code is 200
12871289
snippet.assertBodyContains.title=Assert: Body Contains String

easy-postman-app/src/main/resources/messages_zh.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,8 @@ snippet.dynamicModifyBody.title=前置-动态修改请求体
13371337
snippet.dynamicModifyBody.desc=动态修改请求体和所有参数(formData、urlencoded、formFiles)
13381338
snippet.dynamicModifyParam.title=前置-动态修改请求参数
13391339
snippet.dynamicModifyParam.desc=为请求URL和参数动态添加签名、时间戳等字段
1340+
snippet.sendHttpRequest.title=前置-发送HTTP请求
1341+
snippet.sendHttpRequest.desc=在前置脚本中发送辅助HTTP请求并处理响应
13401342
snippet.assertStatus200.title=断言-状态码为200
13411343
snippet.assertStatus200.desc=断言响应状态码为200
13421344
snippet.assertBodyContains.title=断言-Body包含字符串

0 commit comments

Comments
 (0)