feat(web): add static file serving and update API routes
- Implement embedded static file serving for frontend assets - Update API routes to use '/api' prefix - Add web handler for static file serving with proper content types - Modify .gitignore and README to reflect new web/dist directory structure
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ go.work.sum
|
|||||||
|
|
||||||
/frp_client
|
/frp_client
|
||||||
/configs
|
/configs
|
||||||
/dist
|
/web/dist
|
||||||
agent.md
|
agent.md
|
||||||
super-frpc
|
super-frpc
|
||||||
super-frpc.exe
|
super-frpc.exe
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ Create a `config.json` file in the project root:
|
|||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
**You have to put the compiled frontend in the `web/dist` directory before building the backend.**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go build -o super-frpc.exe
|
go build -o super-frpc.exe
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -4,49 +4,50 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"super-frpc/frpLogger"
|
"super-frpc/frpLogger"
|
||||||
"super-frpc/utils"
|
"super-frpc/handlers"
|
||||||
"super-frpc/postLog"
|
"super-frpc/postLog"
|
||||||
"super-frpc/session"
|
"super-frpc/session"
|
||||||
"super-frpc/handlers"
|
"super-frpc/utils"
|
||||||
|
"super-frpc/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupRoutes() {
|
func setupRoutes() {
|
||||||
systemLogHandler := postLog.NewLogSocketHandler(postLog.GetLogBroadcaster())
|
systemLogHandler := postLog.NewLogSocketHandler(postLog.GetLogBroadcaster())
|
||||||
http.HandleFunc("/system/getLogs", systemLogHandler.Handle)
|
http.HandleFunc("/api/system/getLogs", systemLogHandler.Handle)
|
||||||
http.HandleFunc("/system/getStatus", GetStatusHandler)
|
http.HandleFunc("/api/system/getStatus", GetStatusHandler)
|
||||||
http.HandleFunc("/system/getSoftwareInfo", GetSoftwareInfoHandler)
|
http.HandleFunc("/api/system/getSoftwareInfo", GetSoftwareInfoHandler)
|
||||||
http.HandleFunc("/system/settings/get", handlers.GetSettingsHandler)
|
http.HandleFunc("/api/system/settings/get", handlers.GetSettingsHandler)
|
||||||
http.HandleFunc("/system/settings/set", handlers.SetSettingsHandler)
|
http.HandleFunc("/api/system/settings/set", handlers.SetSettingsHandler)
|
||||||
|
|
||||||
http.HandleFunc("/register", handlers.RegisterHandler)
|
http.HandleFunc("/api/register", handlers.RegisterHandler)
|
||||||
http.HandleFunc("/login", handlers.LoginHandler)
|
http.HandleFunc("/api/login", handlers.LoginHandler)
|
||||||
http.HandleFunc("/logout", handlers.LogoutHandler)
|
http.HandleFunc("/api/logout", handlers.LogoutHandler)
|
||||||
|
|
||||||
http.HandleFunc("/userMgr/create", handlers.CreateUserHandler)
|
http.HandleFunc("/api/userMgr/create", handlers.CreateUserHandler)
|
||||||
http.HandleFunc("/userMgr/remove", handlers.RemoveUserHandler)
|
http.HandleFunc("/api/userMgr/remove", handlers.RemoveUserHandler)
|
||||||
http.HandleFunc("/userMgr/list", handlers.ListUserHandler)
|
http.HandleFunc("/api/userMgr/list", handlers.ListUserHandler)
|
||||||
http.HandleFunc("/userMgr/modify", handlers.ModifyUserHandler)
|
http.HandleFunc("/api/userMgr/modify", handlers.ModifyUserHandler)
|
||||||
http.HandleFunc("/userMgr/modifyType", handlers.ModifyUserTypeHandler)
|
http.HandleFunc("/api/userMgr/modifyType", handlers.ModifyUserTypeHandler)
|
||||||
|
|
||||||
http.HandleFunc("/sessionMgr/list", handlers.ListActiveSessionsHandler)
|
http.HandleFunc("/api/sessionMgr/list", handlers.ListActiveSessionsHandler)
|
||||||
http.HandleFunc("/sessionMgr/remove", handlers.RemoveSessionHandler)
|
http.HandleFunc("/api/sessionMgr/remove", handlers.RemoveSessionHandler)
|
||||||
|
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/create", handlers.CreateInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/create", handlers.CreateInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/delete", handlers.DeleteInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/delete", handlers.DeleteInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/modify", handlers.ModifyInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/modify", handlers.ModifyInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/list", handlers.ListInstancesHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/list", handlers.ListInstancesHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/start", handlers.StartInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/start", handlers.StartInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/stop", handlers.StopInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/stop", handlers.StopInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/restart", handlers.RestartInstanceHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/restart", handlers.RestartInstanceHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/status", handlers.GetInstanceStatusHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/status", handlers.GetInstanceStatusHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/getInfo", handlers.GetInstanceInfoHandler)
|
http.HandleFunc("/api/frpcAct/instanceMgr/getInfo", handlers.GetInstanceInfoHandler)
|
||||||
http.HandleFunc("/frpcAct/instanceMgr/logs", frpLogger.NewInstanceLogHandler(session.ValidateTokenFromMap).ServeHTTP)
|
http.HandleFunc("/api/frpcAct/instanceMgr/logs", frpLogger.NewInstanceLogHandler(session.ValidateTokenFromMap).ServeHTTP)
|
||||||
http.HandleFunc("/frpcAct/proxyMgr/create", handlers.CreateProxyHandler)
|
http.HandleFunc("/api/frpcAct/proxyMgr/create", handlers.CreateProxyHandler)
|
||||||
http.HandleFunc("/frpcAct/proxyMgr/modify", handlers.ModifyProxyHandler)
|
http.HandleFunc("/api/frpcAct/proxyMgr/modify", handlers.ModifyProxyHandler)
|
||||||
http.HandleFunc("/frpcAct/proxyMgr/delete", handlers.DeleteProxyHandler)
|
http.HandleFunc("/api/frpcAct/proxyMgr/delete", handlers.DeleteProxyHandler)
|
||||||
http.HandleFunc("/frpcAct/proxyMgr/list", handlers.ListProxiesHandler)
|
http.HandleFunc("/api/frpcAct/proxyMgr/list", handlers.ListProxiesHandler)
|
||||||
|
|
||||||
http.HandleFunc("/", NotFoundHandler)
|
http.HandleFunc("/", web.ServeStatic)
|
||||||
|
|
||||||
postLog.Info("Routes setup successfully")
|
postLog.Info("Routes setup successfully")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed dist/*
|
||||||
|
var StaticFiles embed.FS
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var staticFS http.FileSystem
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
subFS, err := fs.Sub(StaticFiles, "dist")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
staticFS = http.FS(subFS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ServeStatic(w http.ResponseWriter, r *http.Request) {
|
||||||
|
urlPath := r.URL.Path
|
||||||
|
|
||||||
|
if urlPath == "/" || urlPath == "/index.html" || strings.HasPrefix(urlPath, "/assets/") {
|
||||||
|
if urlPath == "/" {
|
||||||
|
urlPath = "/index.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := strings.TrimPrefix(urlPath, "/")
|
||||||
|
f, err := staticFS.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
serveIndexHTML(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
stat, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
serveIndexHTML(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.IsDir() {
|
||||||
|
serveIndexHTML(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentType(w, path.Ext(filePath))
|
||||||
|
http.ServeContent(w, r, filePath, stat.ModTime(), f.(http.File))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serveIndexHTML(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveIndexHTML(w http.ResponseWriter) {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
w.Header().Set("Cache-Control", "no-cache")
|
||||||
|
data, _ := StaticFiles.ReadFile("dist/index.html")
|
||||||
|
w.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setContentType(w http.ResponseWriter, ext string) {
|
||||||
|
switch ext {
|
||||||
|
case ".html":
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
case ".css":
|
||||||
|
w.Header().Set("Content-Type", "text/css; charset=utf-8")
|
||||||
|
case ".js":
|
||||||
|
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
|
||||||
|
case ".json":
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
case ".png":
|
||||||
|
w.Header().Set("Content-Type", "image/png")
|
||||||
|
case ".jpg", ".jpeg":
|
||||||
|
w.Header().Set("Content-Type", "image/jpeg")
|
||||||
|
case ".gif":
|
||||||
|
w.Header().Set("Content-Type", "image/gif")
|
||||||
|
case ".svg":
|
||||||
|
w.Header().Set("Content-Type", "image/svg+xml")
|
||||||
|
case ".ico":
|
||||||
|
w.Header().Set("Content-Type", "image/x-icon")
|
||||||
|
case ".woff":
|
||||||
|
w.Header().Set("Content-Type", "font/woff")
|
||||||
|
case ".woff2":
|
||||||
|
w.Header().Set("Content-Type", "font/woff2")
|
||||||
|
case ".ttf":
|
||||||
|
w.Header().Set("Content-Type", "font/ttf")
|
||||||
|
case ".eot":
|
||||||
|
w.Header().Set("Content-Type", "application/vnd.ms-fontobject")
|
||||||
|
default:
|
||||||
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user