0%

gin 部署前后端分离项目

最近在写一个自己的小项目 GONEList,技术栈是 gin+vue。准备在部署的时候,如何使用 gin 来同时部署前后端?
把前端使用 / 进行挂载,后端监听其他的路由,这样会遇到问题,默认的路由规则不允许同时挂载到 staticfs 到根和监听其他路由
在 google 之后 issue 里面找到 gin 的一个库 gin-contrib/static 来解决,直接调用即可

背景

前端是 Sillywa 使用 vue+iView 写的 gonelist-web,由于 Golang 的跨平台特性,在发布的时候想要尽量减少部署的难度,于是想用 gin 来同时路由前端生成的 dist 文件夹。

根据官方文档上的 router.StaticFS() 来进行的话会遇到报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
router.StaticFS("/", http.Dir("my_file_system"))
router.Run(":8080")
}
build-fail

static-middleware

由于 gin 本身的路由会发生冲突,gin-contrib/static 使用中间件的方式判断是否存在该静态文件,使用起来非常简单,下面是例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
)

func main() {
router := gin.Default()
router.Use(static.Serve("/", static.LocalFile("./dist/", false)))

router.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})

router.Run(":8080")
}

fileserver 是一个 Handler,判断 fs 中是否有请求的文件,如果有则使用 fileserver 将文件写入到 gin 的 writer 里面返回,否则就不处理,中间件处理结束之后就会去匹配对应的 api。戳我跳转代码

1
2
3
4
5
6
7
8
9
10
11
12
13
// Static returns a middleware handler that serves static files in the given directory.
func Serve(urlPrefix string, fs ServeFileSystem) gin.HandlerFunc {
fileserver := http.FileServer(fs)
if urlPrefix != "" {
fileserver = http.StripPrefix(urlPrefix, fileserver)
}
return func(c *gin.Context) {
if fs.Exists(urlPrefix, c.Request.URL.Path) {
fileserver.ServeHTTP(c.Writer, c.Request)
c.Abort()
}
}
}

参考资料

如果对您有帮助,请我喝杯咖啡?