vue.js - 无法使用 NoRoute 功能为 vue.js SPA 应用程序提供服务
问题描述
我有一个项目正在建立一个在同一个 docker 容器中同时托管 api 和 SPA vue.js 应用程序的 gin-server:
code
├── main.go
├── Routes
│ └── Routes.go
├── Controllers
│ ├── Controllers.go
│ ...
└── web
├── src
│ └── App.vue
├── dist
├── public
...
当前端托管在开发人员 js 服务器中时,前端运行良好,并且单独的 api 也运行良好,但是当我在 gin-server 中托管 vue.js 应用程序时,后端 gin 路由器以常规“/”路由显示我的应用程序,但给出尝试访问由 VueRouter 管理的子路由时,我出现 404。我希望能够将不属于 api 的任何内容路由到 VueRouter,我的代码基于一些指南,还尝试解决我在产品中发现但没有运气的问题:
这是我的 Routes.go:
package Routes
import (
"path"
"strings"
"devops-portal/Controllers"
"github.com/gin-gonic/gin"
"net/http"
"github.com/gobuffalo/packr/v2"
)
//SetupRouter ... Configure routes
func SetupRouter() *gin.Engine {
r := gin.Default()
webFiles := packr.New("web app", "../web/dist")
r.Use(StaticServe("/", webFiles))
grp1 := r.Group("/api/v1")
{
grp1.GET("request", Controllers.GetRequests)
grp1.POST("create-request", Controllers.CreateRequest)
grp1.GET("request/:id", Controllers.GetRequestByID)
grp1.PUT("request/:id", Controllers.UpdateRequest)
grp1.DELETE("request/:id", Controllers.DeleteRequest)
}
r.NoRoute(func(c *gin.Context){
c.File("../web/dist/index.html")
})
return r
}
func ReturnPublic() gin.HandlerFunc {
return func(context *gin.Context) {
method := context.Request.Method
if method == "GET" {
context.File("./public")
} else {
context.Next()
}
}
}
func exists(fs *packr.Box, prefix string, filepath string) bool {
if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
name := path.Join("/", p)
if fs.HasDir(name) {
index := path.Join(name, "index.html")
if !fs.Has(index) {
return false
}
} else if !fs.Has(name) {
return false
}
return true
}
return false
}
// StaticServe serves the web app
func StaticServe(urlPrefix string, fs *packr.Box) gin.HandlerFunc {
fileserver := http.FileServer(fs)
if urlPrefix != "" {
fileserver = http.StripPrefix(urlPrefix, fileserver)
}
return func(c *gin.Context) {
if exists(fs, urlPrefix, c.Request.URL.Path) {
fileserver.ServeHTTP(c.Writer, c.Request)
c.Abort()
}
}
}
VueRouter - web/src/router/index.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Auth from '@okta/okta-vue'
Vue.use(Auth, {
issuer: 'https://xxxxx.okta.com/',
client_id: 'xxxxxxxxxxxxxxxx',
redirect_uri: 'http://localhost:3000/implicit/callback',
scope: 'openid profile email',
pkce: true
})
Vue.use(VueRouter)
const routes = [
{ path: '/login', name: 'Login', component: () => import('../views/Login.vue')},
{ path: '/', name: 'Home', component: () => import('../views/requests.vue'), meta: { requiresAuth: true }},
{ path: '/requests', name: 'Requests', component: () => import('../views/requests.vue'), meta: { requiresAuth: true }},
{ path: '/implicit/callback', component: Auth.handleCallback() }
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach(Vue.prototype.$auth.authRedirectGuard());
export default router
我可以使用 OKTA 配置身份验证,问题是当 OKTA 服务器重定向到回调 url 时,它是 /implicit/callback... 它只提供 404 而不是提供 vue 路由。
解决方案
对于遇到此问题的任何人,我都可以通过删除从问题中复制的所有中间件并简单地使用 gin-static 中间件来解决我的问题:
r := gin.Default()
r.Use(static.Serve("/", static.LocalFile("./web/dist", true)))
grp1 := r.Group("/api/v1")
{
grp1.GET("request", Controllers.GetRequests)
grp1.POST("create-request", Controllers.CreateRequest)
grp1.GET("request/:id", Controllers.GetRequestByID)
grp1.PUT("request/:id", Controllers.UpdateRequest)
grp1.DELETE("request/:id", Controllers.DeleteRequest)
}
r.NoRoute(func(c *gin.Context){
c.File("./web/dist/index.html")
})
推荐阅读
- c# - 如何删除选项卡标题并拉伸 TabControl 以便不显示空白?
- c# - 检测链接是否为可下载文件
- r - 如何在 Rstudio (stargazer) 中创建具有描述性统计的表?
- laravel - 如何在 Laravel Mix 中使用 purgeCss
- sql - 在 where 子句中唯一
- libreoffice - 当我选择表格 [Libreoffice] 时,无法点击 PDF 导出时的目录链接
- python - matplotlib 中的逐步线图
- docker - 什么是“清单 blob 未知:注册表未知的 blob”错误
- python - (没有名为 __main__ 的模块)在 bashrc 中使用别名时
- c++ - C++ 警告:并非所有控制路径都返回值