让Curl成为你的前后端测试联调神器
联调的烦恼
前端开发人员的工作中除了要写代码,还要与后端、测试等等不同的角色协作沟通。代码写多了,熟能生巧,效率自然就提上来了。而协作沟通有时候就是很难沟通,大家都是牛马,说着牛头不对马嘴的话,效率很难提高。
举例子,测试人员给你提bug时,截图的内容总是不完整的,测试也只看得到页面,无法把当时node中间层与下游服务的调用情况记录下来。前后端技术栈不一样,站位视角不一样,你跟后端在联调接口有问题时,你通过截图+描述发给后端,后端可能还理解不了你说的啥。
工欲善其事,必先利其器。要想提高联调效率,就要注意想一些方式方法,让工具来帮助你,Curl就可以成为你的联调神器。
Curl的介绍
Curl是一种用于与服务器进行数据传输的命令行工具和库。它支持多种协议,包括HTTP、FTP、SMTP等,并提供了丰富的功能来发送请求和接收响应。
- 使用Curl,您可以轻松地在终端中发送各种类型的HTTP请求,如GET、POST、PUT、DELETE等,并获取服务器返回的响应。Curl还支持自定义头部、Cookie、代理等功能,使您能够灵活地配置请求。此外,Curl还支持文件上传和下载,可以方便地处理文件的传输。
- 除了命令行工具,Curl还提供了libcurl库,可以以C/C++等编程语言集成到自己的应用程序中,从而实现更复杂的网络交互操作。Curl具有跨平台的特性,可在Windows、Linux、macOS等操作系统上运行。
总结,Curl是一个强大且方便的工具,可用于进行网络调试、数据传输和自动化任务等操作。
浏览器端使用
当想把浏览器的某个接口请求记录下来时,如果用截图,截图操作麻烦,而且截图内容不完整,谷歌浏览器就自带把接口请求转化为curl的功能,可以很方便地以curl的形式记录下指定接口请求的内容
node中间层curl生成
在node中间层,一个前端页面接口可能聚合调用了很多下游服务,如果其中某一个链路的下游服务调用出问题(比如入参少了一个字段),这个是很难一下子排查出来的,我们看不出来这个前端页面接口在背后(中间层)究竟调用了哪些下游服务及其调用细节。
解决方法就是,我们可以在node中间层实现一个Copy as cURL
的功能。在开发环境和测试环境下,把每一个下游服务的请求调用都转成curl,假如一个前端页面接口聚合了10个下游服务,就把这10个下游服务调用转成10个curl,返回给前端页面。
// demo
const data = fetchData(aRequestOption, bRequestOption)
const aCurl = (new CurlTool(aRequestOption)).getCommand()
const bCurl = (new CurlTool(bRequestOption)).getCommand()
res.json({
code: '0',
data,
// 注意下游服务是不对外暴露的,生产环境下不能返回curl
curl: ['DEV', 'TEST'].includes(process.env.NODE_ENV) ? { aCurl, bCurl } : undefined
})
这样子,测试人员在测试时,就可以通过curl把中间层的下游调用细节记录下来,方便开发人员排查中间层的问题,节省了很多时间。当你跟后端联调接口时,也可以直接甩给后端一个curl,让后端根据curl来看看哪里有问题。
用ts实现一个简易的Copy as cURL功能
下面是完整的代码实现:
interface Option {
url: string
method: string
headers: Record<string, string>
data?: Record<string, any>
query?: Record<string, string>
}
class CurlTool {
constructor (option: Option) {
this.processOption(option)
}
private option: Option
private processOption (option: Option) {
this.option = {
...option,
url: option.url.replace(/\/+$/, ''),
method: option.method.toUpperCase(),
}
}
private processSpecial (content: string) {
if (content.includes(`'`)) {
return '$' + `'${content.replace(/'/g, `\\'`)}'`
}
return `'${content}'`
}
private getMethod () {
return `-X '${this.option.method}'`
}
private getHeaders () {
return Object.entries(this.option.headers).map(([key, val]) => {
const header = this.processSpecial(`${key}: ${val}`)
return `-H ${header}`
}).join(' ')
}
private getBody () {
const hasBody = !!this.option.data && this.option.method !== 'GET'
if (hasBody) {
const body = this.processSpecial(JSON.stringify(this.option.data))
return `-d ${body}`
}
return ''
}
private getQuery () {
if (!this.option.query) {
return ''
}
const content = Object.entries(this.option.query).map(([key, val]) => `${key}=${val}`).join('&')
return `?${content}`
}
private getUrl () {
return this.processSpecial(this.option.url + this.getQuery())
}
getCommand () {
const content = [this.getUrl(), this.getMethod(), this.getBody(), this.getHeaders(), '--compressed'].join(' ')
return `curl ${content}`.trim().replace(/\s{2,}/g, ' ')
}
}
说一下在使用过程中遇到的问题,在curl中,是使用单引号包裹内容的,举例curl -X 'GET' 'https://example.com/api?param1=value1¶m2=value2'
,假如包裹的内容里面也有单引号,那么就需要进行转换一下。
看上面processSpecial
方法的实现,比如curl -X 'GET' 'https://example.com/api?word=women's%20dress
最终需要转换成curl -X 'GET' $'https://example.com/api?word=women\'s%20dress
。
$'xxx'
表示xxx里面的\'
会被解释成特殊字符'
。
转载自:https://juejin.cn/post/7295620562423808039