前文
在刚毕业时,由于没工作成天在家做白日梦,做一做便想到了一个好用的小工具,平常后端在使用postman测试自己的api是否有问题时,会一直复制贴上,久了会造成版面凌乱,且没有一个collection去管理。于是我便想到了,如果我可以用一个小程式去自动生成一个postman可以import的格式的话,那是不是会比较方便呢?
也因此这款小工具诞生了。
这款小工具是采取开源的方式,欢迎大家提出意见,甚至是fork,改成自己想要的版本!
接下来会开始介绍这款小工具的逻辑,其实也很简单啦!就只是运用了regex来做捕捉而已。
(由于这是我第一次尝试制作开源的程式,因此长得很简陋,请大家的眼睛见谅(´゚д゚`) )
github连结
Rudy1021/goToPost (github.com)
安装方式
直接执行下列指令:
curl -sSfL https://raw.githubusercontent.com/Rudy1021/GoToPost/master/install.sh | sh
接着在环境变数里面设定:
alias gtp="$GOPATH/bin/gtp"
该指令须在GOPATH指令底下
使用方式
先cd到router.go的文件夹,接着输入gtp -p 127.0.0.1:8888 collectionName
gtp
-t 转换成thunder-client
-p 转换成postman
程式码介绍 - regex
首先我们必须要先理解gin中可以使用的route的格式有什么:
- "example/Select"
- "/example/Select"
- group
(就我目前所知)这几种是比较常会使用到的route名称,而我的regex则是会无论他有没有/ 我都会抓,在最后放进json时会再检查一次他前面是否有/ 。
程式码讲解
首先会先搜寻:
g1 := router.Group("api")
这一种类型,也就是上文提到的Group,会使用下列的regex去做捕捉:
(.+)\s:=\s\w+\.Group\(\"(.+)\"\)
由于每个人对于变数的命名不太一样,只有Group是固定的,因此在这里我选择把.Group给直接写出来,这样才能提高准确率。
这里会捕捉前缀(g1)以及Group的名称(api)
捕捉g1的原因是为了在接下来使用regex时,可以在捞到该url时,可以直接植入group的名称。
接下来会先判断group的长度是否!=0 若等于便表示这个route.go并没有使用group这个东西,若有则会继续进行For回圈的程式码。
groupRouter := group[2]
reForGroupWithActionsAndName := regexp.MustCompile(group[1] + `\.([A-Z]+)\s*\("([^"]+)",\s*([^)]+)\)`)
matchesWithGroup := reForGroupWithActionsAndName.FindAllStringSubmatch(string(content), -1)
groupRouter会取得Group的名称(api)
而reForGroupWithActionsAndName则会取得url的路径
(很抱歉本人的命名很烂😅)
再来会使用For回圈去把matchesWithGroup做遍历
for _, route := range matchesWithGroup {
if len(route) == 4 {
httpMethods := route[1]
apiRoutes := route[2]
handler := route[3]
if apiRoutes[0:1] != "/" {
apiRoutes = "/" + apiRoutes
}
request := models.RequestOfThunder{}
request.Method = httpMethods
request.Url = baseUrl + "/" + groupRouter + apiRoutes
request.Name = handler
request.SortNum = 10000
request.Created = now
request.Modified = now
request.Headers = []string{}
request.Params = []string{}
request.Tests = []string{}
exportJson.Requests = append(exportJson.Requests, request)
}
}
(此处以Thunder-client为例)
这个httpMethods是看Http Methods是哪一个(Http Methods就是GET、POST、PUT、DELETE)。
apiRoutes就是这个api的url后面是什么。
handler则是他这个func是哪个package的 Ex:Example.GET 最后会把它当成Name。
其他的就只是单纯固定的值,因为我没有用到,所以我才会用成固定的,如果有需要用到的朋友请修改这里即可。
如果没有Group的话,其实也是执行差不多的程式码:
reForActionsWithName := regexp.MustCompile(`\.([A-Z]+)\s*\("([^"]+)",\s*([^)]+)\)`)
matchForActionsWithName := reForActionsWithName.FindAllStringSubmatch(string(content), -1)
这里跟上面一样,会捞api的url,并且在捞完以后使用For回圈将资料放进json里面。
Thunder-client介绍
这是一款我在vs code中看到的一个套件,他比起postman来说比较轻便一些,只是他在上个月底变更了一些条约,导致现在一个collection只能够放30个api,因此这个以后也不会再维护了,大家就当看看就好!
Postman程式码不一样的地方
由于postman对于json的定义比较详细一点,因此这里我就说一下有什么不同的地方:
urlRegex := regexp.MustCompile(`^(https?://)?([^:/]+)(:\d+)?`)
urlMatch := urlRegex.FindStringSubmatch(baseUrl)
host := ""
protocol := ""
port := ""
if len(urlMatch) == 4 {
protocol = urlMatch[1]
host = urlMatch[2]
port = urlMatch[3]
if protocol == "" {
protocol = "http://"
}
if port != "" {
port = port[1:] // Remove the leading ":"
}
} else {
fmt.Println("Invalid URL format:", baseUrl)
}
由于postman需要http(s)://,另外他的port也是分开的
Ex: http://127.0.0.1:8888
会被postman分开成
protocol=http
host=127.0.0.1
port=8888
所以这里需要先将输入的ip转换成postman可以使用的格式。
for _, routes := range matchForActionsWithName {
if len(routes) == 4 {
httpMethods := routes[1]
apiRoutes := routes[2]
handler := routes[3]
if apiRoutes[0:1] != "/" {
apiRoutes = "/" + apiRoutes
}
fullURL := baseUrl + apiRoutes
path := strings.Split((apiRoutes), "/")
postmanItem := models.Item{}
postmanItem.Name = handler
postmanItem.Request.Method = httpMethods
postmanItem.Request.Headers = []string{}
postmanItem.Response = []string{}
postmanItem.Request.Url.Raw = fullURL
postmanItem.Request.Url.Protocol = protocol
postmanItem.Request.Url.Host = strings.Split(host, ".")
postmanItem.Request.Url.Path = path
postmanItem.Request.Url.Port = port
exportJson.Item = append(exportJson.Item, postmanItem)
}
}
(上面是postman所需要的其他东西,因为我没有用到,所以我将这些都设定成固定的值)
在转换完成以后,只要在postman或是thunder-client中import,就可以直接使用了!
后记
这是我第一次自己写小工具并且自己写文章,所以文笔有些不好的地方请见谅😓。
这个项目虽然两周前就做完了,但懒病发作的我一直没有动力去写教学推广文章,但想着:这周六就是我生日了,想送给自己一个特别的礼物,便趁着上班时间把文章做完了🤣。
感谢看完这篇文章的各位,未来如果我有好主意也会继续发文章的!