在开发环境中运行reactjs应用程序时,我的重定向工作完美(
npm run dev
),正确重定向到主页。但是当我在 golang 上提供相同的应用程序时,在npm run build
之后,重定向不起作用。
应用程序.jsx
import {
Route,
createBrowserRouter,
createRoutesFromElements,
RouterProvider,
Navigate,
} from "react-router-dom";
import HomePage from "./pages/Home/HomePage";
import MainLayout from "./layouts/MainLayout";
import { useGlobal } from "./GlobalState";
import PodPage from "./pages/Pods/PodPage";
const App = () => {
const { isClusterConnected } = useGlobal();
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route path="/" element={<MainLayout />}>
<Route
index
element={
isClusterConnected ? <Navigate to="/pods" /> : <HomePage />
}
/>
<Route path="*" element={<Navigate to="/" replace />} />
<Route
path="/pods"
element={!isClusterConnected ? <Navigate to="/" /> : <PodPage />}
/>
</Route>
</>
)
);
return <RouterProvider router={router} />;
};
export default App;
但是在golang上运行相同,在构建react应用程序并将其嵌入到golang中之后,如果我在url中有路径,localhost:8080可以工作,那么它总是给出404,但是当我在localhost:8080 / pods或/不存在时刷新它给出 404 错误。
main.go
//go:embed dist/*
var distFS embed.FS
func main() {
r := mux.NewRouter()
k8sApiRouter := r.PathPrefix("/api/k8s").Subrouter()
r.HandleFunc("/api/k8s/set-client", api.Setk8sClient).Methods("POST")
r.HandleFunc("/api/k8s/cluster-connected", api.ClusterConnected).Methods("GET")
r.HandleFunc("/api/k8s/disconnect", api.SetClientSetToNil).Methods("GET")
r.HandleFunc("/execute", executeCommand)
k8sApi.RegisterK8sRouters(k8sApiRouter)
// Serve your ReactJS frontend (assuming it's in a "build" directory)
// Create a subdirectory in the embedded file system
subFS, err := fs.Sub(distFS, "dist")
if err != nil {
fmt.Println("Failed to locate embedded files:", err)
return
}
r.PathPrefix("/").Handler(http.FileServer(http.FS(subFS)))
handler := config.CORS.Handler(r)
port := ":8080"
fmt.Println("Server started on " + port)
http.Handle("/", handler)
http.ListenAndServe(port, nil)
}
func executeCommand(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
return
}
if r.Method != "POST" {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
cmd, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading command", http.StatusBadRequest)
return
}
output, err := exec.Command("sh", "-c", string(cmd)).CombinedOutput()
if err != nil {
http.Error(w, "Failed to execute command", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
w.Write(output)
}
这里有明显的 404 问题,假设我的 React 应用程序运行 localhost:3000,如果我在任何路径上刷新,它会将我带到主页。但是当我在 golang 中提供 React 应用程序时,转到 localhost:8080 它可以工作,以编程方式导航也可以工作,但是当我单击刷新浏览器按钮时,它给出 404,在 localhost:8080 上刷新将我带到主页,但其中的任何路径给出 404
我在 golang 中尝试过这个
// Custom NotFound handler
r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusSeeOther)
})
不确定修复是否在 React 应用程序或 golang 项目中。
为了解决这个问题,您需要修改处理程序来检查文件是否存在,并在文件不存在时提供index.html。这是 Go 服务器代码的更新版本:
//go:embed dist/*
var distFS embed.FS
func main() {
r := mux.NewRouter()
// Create a subdirectory in the embedded file system
subFS, err := fs.Sub(distFS, "dist")
if err != nil {
fmt.Println("Failed to locate embedded files:", err)
return
}
// Serve static files and index.html for frontend routes
r.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
filePath := path.Clean(r.URL.Path)
if filePath == "/" {
filePath = "index.html"
} else {
filePath = strings.TrimPrefix(filePath, "/")
}
file, err := subFS.Open(filePath)
if os.IsNotExist(err) || filePath == "index.html" {
http.ServeFile(w, r, "dist/index.html")
return
} else if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
defer file.Close()
http.FileServer(http.FS(subFS)).ServeHTTP(w, r)
})
handler := config.CORS.Handler(r)
port := ":8080"
fmt.Println("Server started on " + port)
http.Handle("/", handler)
http.ListenAndServe(port, nil)
}