基于 gorilla/mux 实现路由匹配和请求分发:服务单页面应用
随着前后端分离的大势所趋,后端应用为前端单页面应用(SPA,通常由 Vue、React 等前端框架构建)提供包含数据的 API 接口,然后由前端代码负责路由跳转和渲染变得越来越流行,gorilla/mux
包也对此功能特性提供了开箱支持。
要演示完整的前后端分离单页面应用,需要先初始化前端应用,以基于 Vue.js 构建前端应用为例,使用 Vue CLI 初始化一个名为 gospa
的 Vue 应用,可以在任意目录下创建(需要安装过 Vue CLI 才能执行以下初始化命令):
vue create gospa
cd gospa
yarn serve
启动应用后,可以按照提示在浏览器通过 http://localhost:8080/
访问应用首页:
接下来,我们通过后端实现 HTTP 服务器来托管前端应用和资源访问。
对于单页面应用,只需在首次访问时请求后端入口路由初始化前端资源,后续交互都是通过前端代码调用后端 API 接口完成数据渲染,从用户角度来说,页面不会刷新,所以看起来就像只有一个单页面。因此,我们只需要在后端入口处定义一个返回初始化前端资源的 HTML 模板视图即可(这个 HTML 文档中引入了前端应用入口 JavaScript 文件以及必要的 CSS 文件),在 gospa
应用根目录下新建一个 server.go
,并编写后端实现代码如下:
package main
import (
"github.com/gorilla/mux"
"log"
"net/http"
"os"
"path/filepath"
"time"
)
// spaHandler 实现了 http.Handler 接口,所以可以用来处理 HTTP 请求
// 其中 staticPath 用于定义前端静态资源目录(包含js、css 文件)
// indexPath 用于定义入口视图模板文件,通常是 index.html
type spaHandler struct {
staticPath string
indexPath string
}
// 处理 SPA 应用请求(主要是首次访问时入口 HTML 文档和相关静态资源文件,暂不涉及 API 接口)
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 获取 URL 路径的绝对路径
path, err := filepath.Abs(r.URL.Path)
if err != nil {
// 如果获取失败,返回 400 响应
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 在 URL 路径前加上静态资源根目录
path = filepath.Join(h.staticPath, path)
// 检查对应资源文件是否存在
_, err = os.Stat(path)
if os.IsNotExist(err) {
// 文件不存在返回入口 HTML 文档内容作为响应
http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
return
} else if err != nil {
// 如果期间报错,返回 500 响应
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 一切顺利,则使用 http.FileServer 处理静态资源请求
http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
}
func main() {
router := mux.NewRouter()
spa := spaHandler{staticPath: "dist", indexPath: "index.html"}
router.PathPrefix("/").Handler(spa)
srv := &http.Server{
Handler: router,
Addr: "127.0.0.1:8000",
// 最佳实践:为服务器读写设置超时时间
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}
具体的业务逻辑都已经写在注释里了。
接下来,我们通过 Go Module 管理 Go 依赖:
go mod init gospa
go mod tidy
然后启动这个基于 Go 实现的 HTTP 服务器:
go run server.go
修改 gospa/src/App.Vue
中传入 HelloWorld
组件的 msg
属性如下:
<HelloWorld msg="Welcome to Your Vue.js + Golang SPA App"/>
在 gospa
根目录下运行 yarn build
,将前端资源编译到 dist
目录下,至此我们的项目目录结构如下所示:
第一个红框区域对应的目录就是编译后的前端静态资源和 HTML 视图模板所在目录。
然后在浏览器中访问 http://127.0.0.1:8000
,即可看到如下效果:
之前对 msg
变量值的修改生效,并且基于 Go 实现的 HTTP 服务器可以成功服务 SPA 应用。
3 Comments
请问windows环境下出现这个问题是什么原因 CreateFile dist\D:: The filename, directory name, or volume label syntax is incorrect.
hi 你这边解决了吗?
一楼报错问题, 1、23行 path, err := filepath.Abs(r.URL.Path) 改为 path,err := os.Getwd() 2、31行 path = filepath.Join(h.staticPath, path) 改为 path = filepath.Join(path, h.staticPath, )