更新
This commit is contained in:
@@ -10,11 +10,13 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Config 结构体用于解析yaml配置文件
|
||||
type Config struct {
|
||||
Host string `yaml:"Host"`
|
||||
Port int `yaml:"Port"`
|
||||
}
|
||||
|
||||
// Result 结构体用于存储解析结果
|
||||
type Result struct {
|
||||
FolderName string
|
||||
Host string
|
||||
@@ -22,6 +24,7 @@ type Result struct {
|
||||
PrefixRoute map[string]bool
|
||||
}
|
||||
|
||||
// GetZeroInfo 遍历指定目录,并解析相关信息
|
||||
func GetZeroInfo(rootDir string) (results []*Result) {
|
||||
entries, err := ioutil.ReadDir(rootDir)
|
||||
if err != nil {
|
||||
@@ -29,21 +32,21 @@ func GetZeroInfo(rootDir string) (results []*Result) {
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
// 只处理目录类型
|
||||
if entry.IsDir() {
|
||||
|
||||
result, err := findFoldersAndExtractInfo(rootDir, entry)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
results = append(results, result)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// findFoldersAndExtractInfo 查找目录并提取信息
|
||||
func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, error) {
|
||||
var result *Result
|
||||
|
||||
@@ -55,6 +58,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 跳过非目录类型
|
||||
if !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
@@ -64,10 +68,12 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 跳过非当前目录的子目录
|
||||
if strings.Contains(relPath, string(os.PathSeparator)) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
// 读取配置文件
|
||||
configPath := filepath.Join(path, "etc", folderName+".yaml")
|
||||
routesPath := filepath.Join(path, "internal", "handler", "routes.go")
|
||||
|
||||
@@ -82,6 +88,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 读取路由文件
|
||||
routesContent, err := ioutil.ReadFile(routesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -89,6 +96,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
|
||||
|
||||
PrefixRoute := extractPrefixRouteValues(string(routesContent))
|
||||
|
||||
// 构建结果
|
||||
result = &Result{
|
||||
FolderName: folderName,
|
||||
Host: config.Host,
|
||||
@@ -106,11 +114,13 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// extractPrefixRouteValues 提取路由前缀
|
||||
func extractPrefixRouteValues(content string) map[string]bool {
|
||||
lines := strings.Split(content, "\n")
|
||||
var prefixPath map[string]bool = make(map[string]bool)
|
||||
|
||||
for _, line := range lines {
|
||||
// 查找包含 "Path:" 的行
|
||||
if strings.Contains(line, "Path:") {
|
||||
path := strings.TrimSpace(strings.TrimPrefix(line, "Path:"))
|
||||
paths := strings.Split(strings.Trim(path, `"`), "/")
|
||||
|
||||
@@ -13,8 +13,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Backend结构体
|
||||
var Backends []*Backend
|
||||
|
||||
// 设置跨域请求
|
||||
func SetCors(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
|
||||
@@ -29,9 +31,11 @@ func SetCors(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// 存储路径的并发安全的Map
|
||||
var pathdict sync.Map = sync.Map{}
|
||||
|
||||
func main() {
|
||||
// 将静态资源路径存储到pathdict
|
||||
pathdict.Store("/css", true)
|
||||
pathdict.Store("/fonts", true)
|
||||
pathdict.Store("/img", true)
|
||||
@@ -39,7 +43,7 @@ func main() {
|
||||
pathdict.Store("/svg", true)
|
||||
pathdict.Store("/favicon.ico", true)
|
||||
|
||||
rootDir := "../server" // Change this to your root directory
|
||||
rootDir := "../server" // 更改为你的根目录
|
||||
vueBuild := "/opt/fusenpack-vue-created"
|
||||
apiURL, err := url.Parse("http://localhost:9900")
|
||||
if err != nil {
|
||||
@@ -48,6 +52,7 @@ func main() {
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// 获取并解析服务信息
|
||||
results := GetZeroInfo(rootDir)
|
||||
|
||||
var allRoutes map[string]bool = make(map[string]bool)
|
||||
@@ -59,20 +64,23 @@ func main() {
|
||||
allRoutes[k] = true
|
||||
}
|
||||
|
||||
// 根据获取的服务信息创建后端服务
|
||||
Backends = append(Backends,
|
||||
NewBackend(mux,
|
||||
fmt.Sprintf("http://%s:%d", result.Host, result.Port),
|
||||
routes...))
|
||||
}
|
||||
|
||||
// Define the static file server that serves the Vue dist folder
|
||||
// 定义用于服务Vue dist文件夹的静态文件服务器
|
||||
fs := http.FileServer(http.Dir(vueBuild))
|
||||
indexHtmlPath := vueBuild + "/index.html"
|
||||
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/api") {
|
||||
// 对/api开头的请求进行反向代理
|
||||
proxy := httputil.NewSingleHostReverseProxy(apiURL)
|
||||
proxy.ServeHTTP(w, r)
|
||||
} else {
|
||||
// 根据请求路径判断是服务静态文件或者是返回index.html
|
||||
idx := strings.Index(r.URL.Path[1:], "/")
|
||||
var prefix string
|
||||
if idx != -1 {
|
||||
@@ -95,6 +103,7 @@ func main() {
|
||||
log.Fatal(http.ListenAndServe(ServerAddress, mux))
|
||||
}
|
||||
|
||||
// 后端服务的类型
|
||||
type Backend struct {
|
||||
HttpAddress string
|
||||
Client *http.Client
|
||||
@@ -102,7 +111,7 @@ type Backend struct {
|
||||
}
|
||||
|
||||
func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Backend {
|
||||
|
||||
// 如果路径最后没有以'/'结尾,则添加'/'
|
||||
for i, muxPath := range muxPaths {
|
||||
if muxPath[len(muxPath)-1] != '/' {
|
||||
muxPath = muxPath + "/"
|
||||
@@ -110,6 +119,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
}
|
||||
}
|
||||
|
||||
// 创建HTTP客户端,设置相关的超时参数和连接数限制
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
@@ -125,23 +135,22 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
},
|
||||
}
|
||||
|
||||
// 创建后端服务对象,包含地址和客户端
|
||||
backend := &Backend{
|
||||
HttpAddress: httpAddress,
|
||||
Client: client,
|
||||
}
|
||||
|
||||
// 创建处理请求的函数
|
||||
handleRequest := func(w http.ResponseWriter, r *http.Request) {
|
||||
// 解析目标URL,包含了查询参数
|
||||
targetURL, err := url.Parse(httpAddress + r.URL.Path)
|
||||
if err != nil {
|
||||
http.Error(w, "Error parsing target URL", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// hasBridge := strings.Contains(r.Header.Get("Access-Control-Request-Headers"), "bridge")
|
||||
|
||||
// 解析目标URL时已经包含了查询参数
|
||||
targetURL.RawQuery = r.URL.RawQuery
|
||||
|
||||
// 创建新的请求
|
||||
proxyReq, err := http.NewRequest(r.Method, targetURL.String(), r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
|
||||
@@ -159,6 +168,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
proxyReq.ContentLength = r.ContentLength
|
||||
proxyReq.Header.Set("Content-Type", r.Header.Get("Content-Type"))
|
||||
|
||||
// 发送请求
|
||||
resp, err := backend.Client.Do(proxyReq)
|
||||
if err != nil {
|
||||
http.Error(w, "Error sending proxy request", http.StatusInternalServerError)
|
||||
@@ -173,10 +183,6 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
}
|
||||
}
|
||||
|
||||
// if hasBridge {
|
||||
// w.Header().Add("Access-Control-Allow-Headers", "Bridge")
|
||||
// }
|
||||
|
||||
// 转发目标服务器的响应状态码和主体
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, err = io.Copy(w, resp.Body)
|
||||
@@ -186,9 +192,11 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个路径注册处理函数
|
||||
for _, muxPath := range muxPaths {
|
||||
mux.HandleFunc(muxPath, handleRequest)
|
||||
}
|
||||
|
||||
// 返回后端服务对象
|
||||
return backend
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user