likes
comments
collection
share

让Curl成为你的前后端测试联调神器

作者站长头像
站长
· 阅读数 16

联调的烦恼

前端开发人员的工作中除了要写代码,还要与后端、测试等等不同的角色协作沟通。代码写多了,熟能生巧,效率自然就提上来了。而协作沟通有时候就是很难沟通,大家都是牛马,说着牛头不对马嘴的话,效率很难提高。

举例子,测试人员给你提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的形式记录下指定接口请求的内容

让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&param2=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
评论
请登录