q!
This commit is contained in:
125
proxyserver/get_zero_Info.go
Normal file
125
proxyserver/get_zero_Info.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Host string `yaml:"Host"`
|
||||
Port int `yaml:"Port"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
FolderName string
|
||||
Host string
|
||||
Port int
|
||||
PrefixRoute map[string]bool
|
||||
}
|
||||
|
||||
func GetZeroInfo(rootDir string) (results []*Result) {
|
||||
entries, err := ioutil.ReadDir(rootDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
|
||||
result, err := findFoldersAndExtractInfo(rootDir, entry)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
results = append(results, result)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, error) {
|
||||
var result *Result
|
||||
|
||||
folderName := entry.Name()
|
||||
path := filepath.Join(rootDir, folderName)
|
||||
|
||||
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(path, path)
|
||||
if err != nil {
|
||||
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")
|
||||
|
||||
configContent, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var config Config
|
||||
err = yaml.Unmarshal(configContent, &config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
routesContent, err := ioutil.ReadFile(routesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
PrefixRoute := extractPrefixRouteValues(string(routesContent))
|
||||
|
||||
result = &Result{
|
||||
FolderName: folderName,
|
||||
Host: config.Host,
|
||||
Port: config.Port,
|
||||
PrefixRoute: PrefixRoute,
|
||||
}
|
||||
|
||||
return filepath.SkipDir
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
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 {
|
||||
if strings.Contains(line, "Path:") {
|
||||
path := strings.TrimSpace(strings.TrimPrefix(line, "Path:"))
|
||||
path1 := strings.Split(strings.Trim(path, `"`), "/")[1]
|
||||
path1 = "/" + path1
|
||||
if _, ok := prefixPath[path1]; !ok {
|
||||
prefixPath[path1] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prefixPath
|
||||
}
|
||||
136
proxyserver/main.go
Normal file
136
proxyserver/main.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Backends []*Backend
|
||||
|
||||
func main() {
|
||||
rootDir := "../server" // Change this to your root directory
|
||||
vueBuild := "/home/eson/workspace/fusenpack-vue-created"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Define the static file server that serves the Vue dist folder
|
||||
fs := http.FileServer(http.Dir(vueBuild))
|
||||
|
||||
// Define a handler function for the Vue static assets
|
||||
mux.Handle("/", http.StripPrefix("/", fs))
|
||||
|
||||
results := GetZeroInfo(rootDir)
|
||||
for _, result := range results {
|
||||
fmt.Printf("FolderName: %s, Host: %s, Port: %d, PrefixRoute: %v\n", result.FolderName, result.Host, result.Port, result.PrefixRoute)
|
||||
var routes []string
|
||||
for k := range result.PrefixRoute {
|
||||
routes = append(routes, k)
|
||||
}
|
||||
|
||||
Backends = append(Backends,
|
||||
NewBackend(mux,
|
||||
fmt.Sprintf("http://%s:%d", result.Host, result.Port),
|
||||
routes...))
|
||||
}
|
||||
|
||||
ServerAddress := ":9900"
|
||||
log.Println("listen on ", ServerAddress)
|
||||
log.Fatal(http.ListenAndServe(ServerAddress, mux))
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
HttpAddress string
|
||||
Client *http.Client
|
||||
Handler http.HandlerFunc
|
||||
}
|
||||
|
||||
func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Backend {
|
||||
|
||||
for i, muxPath := range muxPaths {
|
||||
if muxPath[len(muxPath)-1] != '/' {
|
||||
muxPath = muxPath + "/"
|
||||
muxPaths[i] = muxPath
|
||||
}
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
backend := &Backend{
|
||||
HttpAddress: httpAddress,
|
||||
Client: client,
|
||||
}
|
||||
|
||||
handleRequest := func(w http.ResponseWriter, r *http.Request) {
|
||||
targetURL, err := url.Parse(httpAddress + r.URL.Path)
|
||||
if err != nil {
|
||||
http.Error(w, "Error parsing target URL", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析目标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)
|
||||
return
|
||||
}
|
||||
|
||||
// 复制原始请求的 Header
|
||||
for key, values := range r.Header {
|
||||
for _, value := range values {
|
||||
proxyReq.Header.Add(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// 设置 Content-Length 和 Content-Type
|
||||
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)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 复制目标服务器的响应 Header
|
||||
for key, values := range resp.Header {
|
||||
for _, value := range values {
|
||||
w.Header().Add(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// 转发目标服务器的响应状态码和主体
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, err = io.Copy(w, resp.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Error copying proxy response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
for _, muxPath := range muxPaths {
|
||||
mux.HandleFunc(muxPath, handleRequest)
|
||||
}
|
||||
|
||||
return backend
|
||||
}
|
||||
18
proxyserver/main_test.go
Normal file
18
proxyserver/main_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProxy(t *testing.T) {
|
||||
main()
|
||||
}
|
||||
|
||||
func TestCapture(t *testing.T) {
|
||||
rootDir := "../server" // Change this to your root directory
|
||||
results := GetZeroInfo(rootDir)
|
||||
for _, result := range results {
|
||||
fmt.Printf("FolderName: %s, Host: %s, Port: %d, PrefixRoute: %v\n", result.FolderName, result.Host, result.Port, result.PrefixRoute)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user