用Golang和Chi路由器服务SPA进入一个循环

kokeuurv  于 2023-06-27  发布在  Go
关注(0)|答案(1)|浏览(75)

我试图用Golang服务SPA,解决404错误成了一个挑战。

  • 在init()函数中,我将index.html文件缓冲到内存中。
  • 我创建了一个indexHandler,它返回缓冲的索引文件。
  • 我调用router.NotFound()函数中的indexHandler,以便将路由返回给SPA。
  • 我用FileServer提供其余的静态文件。

问题是它似乎处于循环中,当我试图在浏览器中访问应用程序时,它会无限期地重新加载自己。

package main

import (
    "log"
    "net/http"
    "os"
    "path/filepath"
    "time"

    "github.com/go-chi/chi/v5"
    "github.com/go-chi/chi/v5/middleware"

    "github.com/joho/godotenv"
)

var indexBuffer []byte

func main() {   
    r := chi.NewRouter()
    
    r.Use(middleware.RequestID)
    r.Use(middleware.RealIP)
    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)

    fs := http.FileServer(http.Dir(os.Getenv("FRONTEND_PATH")))
    r.Handle("/app/static/*", http.StripPrefix("/app/static/", fs))

    apiRouter := chi.NewRouter()
    apiRouter.Get("/cargas", handlerCargas)

    r.Mount("/app/api", apiRouter)

    r.NotFound(indexHandler)

    log.Fatal(http.ListenAndServe(":8000", r))
}

func init() {
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Erro ao ler .env verifique!")
    }

    indexBuffer, err = os.ReadFile(filepath.Join(os.Getenv("FRONTEND_PATH"), "index.html"))
    if err != nil {
        log.Fatal("Erro ao tentar bufferizar a index na init().")
    }
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html")
    w.Write(indexBuffer)
}

我希望index.html由indexHandler提供服务,其余文件由FileServer提供服务,未找到页面的错误由SPA处理。

bvk5enib

bvk5enib1#

我在这里找到了解决办法
我修改了我的代码并使用了FileServer,如下所示:

// FileServer para SPA
func FileServerSPA(r chi.Router, public string, static string) {

    if strings.ContainsAny(public, "{}*") {
        panic("FileServer does not permit URL parameters.")
    }

    root, _ := filepath.Abs(static)
    if _, err := os.Stat(root); os.IsNotExist(err) {
        panic("Static Documents Directory Not Found")
    }

    fs := http.StripPrefix(public, http.FileServer(http.Dir(root)))

    if public != "/" && public[len(public)-1] != '/' {
        r.Get(public, http.RedirectHandler(public+"/", 301).ServeHTTP)
        public += "/"
    }

    r.Get(public+"*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        file := strings.Replace(r.RequestURI, public, "/", 1)
        if _, err := os.Stat(root + file); os.IsNotExist(err) {
            http.ServeFile(w, r, path.Join(root, "index.html"))
            return
        }
        fs.ServeHTTP(w, r)
    }))
}

在main()中:

// ...
// after all the endpoints of the api

frontendPath := os.Getenv("FRONTEND_PATH")
FileServerSPA(r, "/app", frontendPath)

log.Fatal(http.ListenAndServe(":8000", r))

希望有帮助

相关问题