change and correct
This commit is contained in:
parent
ea38f85fb7
commit
0a667bea96
17
README.md
17
README.md
|
@ -116,11 +116,7 @@ paths 配置
|
||||||
"servers":[{
|
"servers":[{
|
||||||
"port" : 8080,
|
"port" : 8080,
|
||||||
"name":"test",
|
"name":"test",
|
||||||
"health_check": {
|
|
||||||
"interval": "10s", // 每10秒检查一次
|
|
||||||
"timeout": "5s", // 每次检查5秒超时
|
|
||||||
"retries": 3 // 失败3次才认为是不健康
|
|
||||||
},
|
|
||||||
"paths":[{
|
"paths":[{
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"root": "/home/kingecg/code/gohttp/public/",
|
"root": "/home/kingecg/code/gohttp/public/",
|
||||||
|
@ -133,7 +129,12 @@ paths 配置
|
||||||
"HeaderOrigin",
|
"HeaderOrigin",
|
||||||
"Path /ws /",
|
"Path /ws /",
|
||||||
"RemoveCookie token"
|
"RemoveCookie token"
|
||||||
]
|
],
|
||||||
|
"health_check": {
|
||||||
|
"interval": "10s", // 每10秒检查一次
|
||||||
|
"timeout": "5s", // 每次检查5秒超时
|
||||||
|
"retries": 3 // 失败3次才认为是不健康
|
||||||
|
},
|
||||||
}]
|
}]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
@ -158,6 +159,10 @@ paths 配置
|
||||||
- 返回的response中设置header
|
- 返回的response中设置header
|
||||||
- 反向代理时,修改发送到上游服务器的请求
|
- 反向代理时,修改发送到上游服务器的请求
|
||||||
|
|
||||||
|
命名规则:
|
||||||
|
模块支持的指令,以模块名作为前缀,如:Proxy_Path 是反向代理模块的Path指令。
|
||||||
|
没有前缀的,是全局指令,如:Set-Header 是设置header的指令。
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
|
|
Binary file not shown.
|
@ -77,16 +77,53 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write(server.NewSuccessResult(ret))
|
w.Write(server.NewSuccessResult(ret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stop(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
ctxData := ctx.Value(server.RequestCtxKey("data")).(map[string]interface{})
|
||||||
|
name, ok := ctxData["name"]
|
||||||
|
if ok {
|
||||||
|
serverConf := model.GetServerConfig(name.(string))
|
||||||
|
server.StopServer(name.(string), serverConf.Port)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
data := "stopped"
|
||||||
|
w.Write(server.NewSuccessResult(data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func start(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
ctxData := ctx.Value(server.RequestCtxKey("data")).(map[string]interface{})
|
||||||
|
name, ok := ctxData["name"]
|
||||||
|
if ok {
|
||||||
|
serverConf := model.GetServerConfig(name.(string))
|
||||||
|
server.StartServer(name.(string), serverConf.Port)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
data := "started"
|
||||||
|
w.Write(server.NewSuccessResult(data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var AdminServerMux *server.RestMux
|
var AdminServerMux *server.RestMux
|
||||||
|
|
||||||
func init() {
|
func InitAdminApi(conf *model.HttpServerConfig) {
|
||||||
|
|
||||||
AdminServerMux = server.NewRestMux("/api")
|
AdminServerMux = server.NewRestMux("/api")
|
||||||
|
if conf.AuthType == "jwt" {
|
||||||
AdminServerMux.Use(server.JwtAuth)
|
AdminServerMux.Use(server.JwtAuth)
|
||||||
|
} else if conf.AuthType == "basic" {
|
||||||
|
AdminServerMux.Use(server.BasicAuth)
|
||||||
|
}
|
||||||
|
// AdminServerMux.Use(server.JwtAuth)
|
||||||
AdminServerMux.HandleFunc("GET", "/about", http.HandlerFunc(about))
|
AdminServerMux.HandleFunc("GET", "/about", http.HandlerFunc(about))
|
||||||
postConfigRoute := AdminServerMux.HandleFunc("POST", "/config", http.HandlerFunc(setConfig))
|
postConfigRoute := AdminServerMux.HandleFunc("POST", "/config", http.HandlerFunc(setConfig))
|
||||||
postConfigRoute.Add(server.Parse[model.HttpServerConfig])
|
postConfigRoute.Add(server.Parse[model.HttpServerConfig])
|
||||||
AdminServerMux.HandleFunc("GET", "/config/:id", http.HandlerFunc(getServerConfigure))
|
AdminServerMux.HandleFunc("GET", "/config/:id", http.HandlerFunc(getServerConfigure))
|
||||||
AdminServerMux.HandleFunc("GET", "/status", http.HandlerFunc(getStatus))
|
AdminServerMux.HandleFunc("GET", "/status", http.HandlerFunc(getStatus))
|
||||||
|
AdminServerMux.HandleFunc("Post", "/stop/:name", http.HandlerFunc(stop))
|
||||||
|
AdminServerMux.HandleFunc("Post", "/start/:name", http.HandlerFunc(start))
|
||||||
loginRoute := AdminServerMux.HandleFunc("POST", "/login", http.HandlerFunc(login))
|
loginRoute := AdminServerMux.HandleFunc("POST", "/login", http.HandlerFunc(login))
|
||||||
loginRoute.Add(server.Parse[LoginModel])
|
loginRoute.Add(server.Parse[LoginModel])
|
||||||
// AdminServerMux.Use(server.BasicAuth)
|
// AdminServerMux.Use(server.BasicAuth)
|
||||||
|
|
179
config.json
179
config.json
|
@ -23,6 +23,7 @@
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"name": "admin",
|
"name": "admin",
|
||||||
|
"server":"admin",
|
||||||
"port": 8088,
|
"port": 8088,
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
"password": "admin",
|
"password": "admin",
|
||||||
|
@ -40,183 +41,15 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
|
|
||||||
{
|
{
|
||||||
"port": 3000,
|
"name": "teststatic",
|
||||||
"name": "cloudops",
|
"server":"www.teststatic.com",
|
||||||
|
"port": 8088,
|
||||||
"paths": [
|
"paths": [
|
||||||
|
|
||||||
{
|
|
||||||
"path": "/static",
|
|
||||||
"root": "/home/kingecg/work/angular13/cloudops/static",
|
|
||||||
"default": "index.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"upstreams": [
|
"root": "./example",
|
||||||
"http://localhost:4200"
|
"default": "index.html"
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/ssologin",
|
|
||||||
"upstreams": [
|
|
||||||
"http://localhost:4200"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/themes",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/security",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/relational/assets",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/platform/version",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/patrolrecords",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/standingbook",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/resource",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/config",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/workflow",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/token/check",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/messages",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/cloudops-state/",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/socket.io/",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/v1/stream",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.157:9880"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/thing",
|
|
||||||
"upstreams": [
|
|
||||||
"http://192.168.12.204:1662"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target",
|
|
||||||
"HeaderOrigin",
|
|
||||||
"RemoveCookie token"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path":"/ib",
|
|
||||||
"upstreams": [
|
|
||||||
"http://localhost:8080"
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
"HostSchemas $target",
|
|
||||||
"HeaderOrigin",
|
|
||||||
"RemoveCookie token"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
{
|
||||||
|
"logging": {
|
||||||
|
"appenders": {
|
||||||
|
"out": {
|
||||||
|
"type": "file",
|
||||||
|
"options": {
|
||||||
|
"file": "gohttpd.log"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"categories": {
|
||||||
|
"default": {
|
||||||
|
"appenders": [
|
||||||
|
"out",
|
||||||
|
"stdout"
|
||||||
|
],
|
||||||
|
"level": "debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"name": "admin",
|
||||||
|
"port": 8088,
|
||||||
|
"username": "admin",
|
||||||
|
"password": "admin",
|
||||||
|
"directives": [
|
||||||
|
"Set-Header Access-Control-Allow-Origin *",
|
||||||
|
"Set-Header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS",
|
||||||
|
"Set-Header Access-Control-Allow-Headers Content-Type, Authorization, Content-Length, X-Requested-With"
|
||||||
|
],
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"root": "./adminui",
|
||||||
|
"default": "index.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"port": 3000,
|
||||||
|
"name": "cloudops",
|
||||||
|
|
||||||
|
"paths": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/static",
|
||||||
|
"root": "/home/kingecg/work/angular13/cloudops/static",
|
||||||
|
"default": "index.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"upstreams": [
|
||||||
|
"http://localhost:4200"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/ssologin",
|
||||||
|
"upstreams": [
|
||||||
|
"http://localhost:4200"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/themes",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/security",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/relational/assets",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/platform/version",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/patrolrecords",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/standingbook",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/resource",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/config",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/workflow",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/token/check",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/messages",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/cloudops-state/",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/socket.io/",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/stream",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.157:9880"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/thing",
|
||||||
|
"upstreams": [
|
||||||
|
"http://192.168.12.204:1662"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target",
|
||||||
|
"HeaderOrigin",
|
||||||
|
"RemoveCookie token"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path":"/ib",
|
||||||
|
"upstreams": [
|
||||||
|
"http://localhost:8080"
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
"HostSchemas $target",
|
||||||
|
"HeaderOrigin",
|
||||||
|
"RemoveCookie token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head><body>
|
||||||
|
<h1>Hello World!</h1>
|
||||||
|
<p>Welcome to my website.</p>
|
||||||
|
|
||||||
|
</body></html>
|
|
@ -32,7 +32,8 @@ func (g *GoHttp) Start() {
|
||||||
|
|
||||||
// 设置管理员处理器并使用管理员服务配置
|
// 设置管理员处理器并使用管理员服务配置
|
||||||
adminHandler := server.NewServeMux(conf.Admin)
|
adminHandler := server.NewServeMux(conf.Admin)
|
||||||
adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux))
|
admin.InitAdminApi(conf.Admin)
|
||||||
|
adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux), []string{})
|
||||||
|
|
||||||
// 创建并启动管理员服务器
|
// 创建并启动管理员服务器
|
||||||
g.makeServer(conf.Admin, adminHandler)
|
g.makeServer(conf.Admin, adminHandler)
|
||||||
|
|
1527
gohttpd.log
1527
gohttpd.log
File diff suppressed because it is too large
Load Diff
|
@ -62,7 +62,8 @@ func makeProxy(upstream string, path *model.HttpPath, index int) *httputil.Rever
|
||||||
directiveHandlers := []func(r *http.Request){}
|
directiveHandlers := []func(r *http.Request){}
|
||||||
if len(path.Directives) > 0 {
|
if len(path.Directives) > 0 {
|
||||||
for _, directive := range path.Directives {
|
for _, directive := range path.Directives {
|
||||||
d := strings.Replace(string(directive), "$target", upstream, 1)
|
ndirective := strings.TrimPrefix(directive, "Proxy_")
|
||||||
|
d := strings.Replace(string(ndirective), "$target", upstream, 1)
|
||||||
dh := GetUpdaterFn(d)
|
dh := GetUpdaterFn(d)
|
||||||
if dh != nil {
|
if dh != nil {
|
||||||
directiveHandlers = append(directiveHandlers, dh)
|
directiveHandlers = append(directiveHandlers, dh)
|
||||||
|
@ -106,37 +107,33 @@ func NewProxyHandler(p *model.HttpPath) *ProxyHandler {
|
||||||
}
|
}
|
||||||
ph.proxy = make([]*httputil.ReverseProxy, upstreamCount)
|
ph.proxy = make([]*httputil.ReverseProxy, upstreamCount)
|
||||||
|
|
||||||
// 从配置中获取健康检查参数,如果不存在则使用默认值
|
|
||||||
var interval time.Duration = 10 * time.Second
|
|
||||||
var timeout time.Duration = 5 * time.Second
|
|
||||||
var retries int = 3
|
|
||||||
|
|
||||||
// 使用服务器配置中的健康检查参数
|
|
||||||
config := model.GetConfig()
|
|
||||||
if config != nil && config.Admin != nil && config.Admin.HealthCheck != nil {
|
|
||||||
if config.Admin.HealthCheck.Interval != "" {
|
|
||||||
var err error
|
|
||||||
interval, err = time.ParseDuration(config.Admin.HealthCheck.Interval)
|
|
||||||
if err != nil {
|
|
||||||
interval = 10 * time.Second // 默认值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.Admin.HealthCheck.Timeout != "" {
|
|
||||||
var err error
|
|
||||||
timeout, err = time.ParseDuration(config.Admin.HealthCheck.Timeout)
|
|
||||||
if err != nil {
|
|
||||||
timeout = 5 * time.Second // 默认值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.Admin.HealthCheck.Retries > 0 {
|
|
||||||
retries = config.Admin.HealthCheck.Retries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, upstream := range p.Upstreams {
|
for index, upstream := range p.Upstreams {
|
||||||
ph.proxy[index] = makeProxy(upstream, p, index)
|
ph.proxy[index] = makeProxy(upstream, p, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(p.Upstreams) > 1 && p.HealthCheck != nil {
|
||||||
|
// 只有上游服务器数目大于1时才需要进行健康检查
|
||||||
|
// 从配置中获取健康检查参数,如果不存在则使用默认值
|
||||||
|
var interval time.Duration = 10 * time.Second
|
||||||
|
var timeout time.Duration = 5 * time.Second
|
||||||
|
var retries int = 3
|
||||||
|
if p.HealthCheck.Interval != "" {
|
||||||
|
var err error
|
||||||
|
interval, err = time.ParseDuration(p.HealthCheck.Interval)
|
||||||
|
if err != nil {
|
||||||
|
interval = 10 * time.Second // 默认值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.HealthCheck.Timeout != "" {
|
||||||
|
var err error
|
||||||
|
timeout, err = time.ParseDuration(p.HealthCheck.Timeout)
|
||||||
|
if err != nil {
|
||||||
|
timeout = 5 * time.Second // 默认值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.HealthCheck.Retries > 0 {
|
||||||
|
retries = p.HealthCheck.Retries
|
||||||
|
}
|
||||||
// 使用配置参数创建健康检查器
|
// 使用配置参数创建健康检查器
|
||||||
ph.checker = healthcheck.NewHealthChecker(interval, timeout, retries)
|
ph.checker = healthcheck.NewHealthChecker(interval, timeout, retries)
|
||||||
ph.checker.StartHealthCheck(ph.Upstreams, func(upstream string, healthy bool) {
|
ph.checker.StartHealthCheck(ph.Upstreams, func(upstream string, healthy bool) {
|
||||||
|
@ -148,6 +145,7 @@ func NewProxyHandler(p *model.HttpPath) *ProxyHandler {
|
||||||
logger.Info(fmt.Sprintf("Upstream %s is now healthy", upstream))
|
logger.Info(fmt.Sprintf("Upstream %s is now healthy", upstream))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return ph
|
return ph
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ type HttpPath struct {
|
||||||
Default string `json:"default"`
|
Default string `json:"default"`
|
||||||
Upstreams []string `json:"upstreams"`
|
Upstreams []string `json:"upstreams"`
|
||||||
Directives []string `json:"directives"`
|
Directives []string `json:"directives"`
|
||||||
|
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeaderValueConst string
|
type HeaderValueConst string
|
||||||
|
@ -45,7 +46,7 @@ type HttpServerConfig struct {
|
||||||
AuthType string `json:"auth_type"`
|
AuthType string `json:"auth_type"`
|
||||||
Jwt *JwtConfig `json:"jwt"`
|
Jwt *JwtConfig `json:"jwt"`
|
||||||
// 健康检查配置
|
// 健康检查配置
|
||||||
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
|
|
||||||
// 访问控制配置
|
// 访问控制配置
|
||||||
AllowIPs []string `json:"allow_ips,omitempty"` // 允许访问的IP地址列表
|
AllowIPs []string `json:"allow_ips,omitempty"` // 允许访问的IP地址列表
|
||||||
DenyIPs []string `json:"deny_ips,omitempty"` // 禁止访问的IP地址列表
|
DenyIPs []string `json:"deny_ips,omitempty"` // 禁止访问的IP地址列表
|
||||||
|
|
|
@ -71,7 +71,7 @@ var BasicAuthDirective Directive = func(args ...string) Middleware {
|
||||||
var DirectiveMap = map[string]Directive{
|
var DirectiveMap = map[string]Directive{
|
||||||
"Set-Header": Set_Header,
|
"Set-Header": Set_Header,
|
||||||
"Add-Header": Add_Header,
|
"Add-Header": Add_Header,
|
||||||
"Gzip_Response": Gzip_Response,
|
"Gzip-Response": Gzip_Response,
|
||||||
"Record-Access": DRecordAccess,
|
"Record-Access": DRecordAccess,
|
||||||
"Jwt-Auth": JWTDirective,
|
"Jwt-Auth": JWTDirective,
|
||||||
"Basic-Auth": BasicAuthDirective,
|
"Basic-Auth": BasicAuthDirective,
|
||||||
|
|
|
@ -2,10 +2,12 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
|
@ -30,10 +32,37 @@ func makeMatcher(name string, s *ServerListener) cmux.Matcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sl struct {
|
||||||
|
net.Listener
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *sl) Accept() (net.Conn, error) {
|
||||||
|
if sl.closed {
|
||||||
|
return nil, errors.New("closed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return sl.Listener.Accept()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *sl) Close() error {
|
||||||
|
sl.closed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Conf *model.HttpServerConfig
|
Conf *model.HttpServerConfig
|
||||||
|
Closed bool
|
||||||
*http.Server
|
*http.Server
|
||||||
|
l *sl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) Renew() {
|
||||||
|
s.Server = &http.Server{
|
||||||
|
Handler: s.Handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ServerListener struct {
|
type ServerListener struct {
|
||||||
port int
|
port int
|
||||||
listener cmux.CMux
|
listener cmux.CMux
|
||||||
|
@ -48,28 +77,64 @@ func (s *ServerListener) ServerCount() int {
|
||||||
return len(s.servers)
|
return len(s.servers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerListener) StartServer(name string) error {
|
func (s *ServerListener) StartServer(name string) {
|
||||||
server, ok := s.servers[name]
|
server, ok := s.servers[name]
|
||||||
|
serverName := server.Conf.ServerName
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("No named server")
|
panic("No named server")
|
||||||
}
|
}
|
||||||
|
|
||||||
l := s.listener.Match(makeMatcher(name, s))
|
go func() {
|
||||||
if server.Conf.CertFile != "" && server.Conf.KeyFile != "" {
|
var err error
|
||||||
return server.ServeTLS(l, server.Conf.CertFile, server.Conf.KeyFile)
|
defer func() {
|
||||||
|
l := logger.GetLogger("ServerListener")
|
||||||
|
if err != nil {
|
||||||
|
if err == http.ErrServerClosed {
|
||||||
|
server.Closed = true
|
||||||
|
|
||||||
|
} else {
|
||||||
|
l.Error("Server error:", err)
|
||||||
}
|
}
|
||||||
return server.Serve(l)
|
|
||||||
|
}
|
||||||
|
l.Info("Server stopped:", name)
|
||||||
|
}()
|
||||||
|
if server.Closed {
|
||||||
|
server.Renew()
|
||||||
|
}
|
||||||
|
if server.l == nil {
|
||||||
|
server.l = &sl{
|
||||||
|
Listener: s.listener.Match(makeMatcher(serverName, s)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.Conf.CertFile != "" && server.Conf.KeyFile != "" {
|
||||||
|
err = server.ServeTLS(server.l, server.Conf.CertFile, server.Conf.KeyFile)
|
||||||
|
} else {
|
||||||
|
err = server.Serve(server.l)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// return server.Serve(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerListener) Start() {
|
func (s *ServerListener) StopServer(name string) error {
|
||||||
for name, _ := range s.servers {
|
server, ok := s.servers[name]
|
||||||
go func(name string) {
|
if !ok {
|
||||||
err := s.StartServer(name)
|
return nil
|
||||||
if err != nil {
|
|
||||||
l := logger.GetLogger("ServerListener")
|
|
||||||
l.Error("Start server error:", name, err)
|
|
||||||
}
|
}
|
||||||
}(name)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
return server.Shutdown(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start 方法用于并发启动 ServerListener 中所有注册的服务器。
|
||||||
|
// 它会为每个服务器创建一个新的 goroutine 来启动,以确保各个服务器可以独立运行。
|
||||||
|
func (s *ServerListener) Start() {
|
||||||
|
// 遍历 ServerListener 中所有注册的服务器
|
||||||
|
for name, _ := range s.servers {
|
||||||
|
// 为每个服务器启动一个新的 goroutine 来执行启动操作
|
||||||
|
s.StartServer(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,3 +174,35 @@ func AddServer(name string, server *Server, port int) {
|
||||||
}
|
}
|
||||||
listener.AddServer(name, server)
|
listener.AddServer(name, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddServerWithConfig(conf *model.HttpServerConfig) {
|
||||||
|
mux := NewServeMux(conf)
|
||||||
|
s := &http.Server{
|
||||||
|
Handler: mux,
|
||||||
|
}
|
||||||
|
name := conf.Name
|
||||||
|
port := conf.Port
|
||||||
|
ss := &Server{
|
||||||
|
Server: s,
|
||||||
|
Conf: conf,
|
||||||
|
}
|
||||||
|
AddServer(name, ss, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopServer(name string, port int) {
|
||||||
|
listenStr := fmt.Sprintf(":%d", port)
|
||||||
|
listener, ok := ServerManager[listenStr]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listener.StopServer(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartServer(name string, port int) {
|
||||||
|
listenStr := fmt.Sprintf(":%d", port)
|
||||||
|
listener, ok := ServerManager[listenStr]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listener.StartServer(name)
|
||||||
|
}
|
||||||
|
|
|
@ -46,21 +46,6 @@ func (ml *MiddlewareLink) Add(m Middleware) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (ml *MiddlewareLink) ServeHTTP(w http.ResponseWriter, r *http.Request) bool {
|
|
||||||
// canContinue := true
|
|
||||||
// next := func() {
|
|
||||||
// canContinue = true
|
|
||||||
// }
|
|
||||||
// for e := ml.Front(); e != nil && canContinue; e = e.Next() {
|
|
||||||
// canContinue = false
|
|
||||||
// e.Value.(Middleware)(w, r, next)
|
|
||||||
// if !canContinue {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return canContinue
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (ml *MiddlewareLink) wrap(m Middleware, next http.Handler) http.Handler {
|
func (ml *MiddlewareLink) wrap(m Middleware, next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
m(w, r, next)
|
m(w, r, next)
|
||||||
|
@ -84,6 +69,18 @@ func (ml *MiddlewareLink) WrapHandler(next http.Handler) http.Handler {
|
||||||
}
|
}
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ml *MiddlewareLink) Clone() *MiddlewareLink {
|
||||||
|
ret := NewMiddlewareLink()
|
||||||
|
for e := ml.Back(); e != nil; e = e.Prev() {
|
||||||
|
middleware, ok := e.Value.(Middleware)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ret.Add(middleware)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
func NewMiddlewareLink() *MiddlewareLink {
|
func NewMiddlewareLink() *MiddlewareLink {
|
||||||
ml := &MiddlewareLink{list.New()}
|
ml := &MiddlewareLink{list.New()}
|
||||||
ml.Add(Done)
|
ml.Add(Done)
|
||||||
|
@ -107,8 +104,12 @@ func BasicAuth(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||||
}
|
}
|
||||||
func JwtAuth(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
func JwtAuth(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||||
l := gologger.GetLogger("JwtAuth")
|
l := gologger.GetLogger("JwtAuth")
|
||||||
config := model.GetConfig()
|
config := getServerConfig(r)
|
||||||
jwtConfig := config.Admin.Jwt
|
if config == nil || config.Jwt == nil {
|
||||||
|
http.Error(w, "Jwt config error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jwtConfig := config.Jwt
|
||||||
if jwtConfig.Secret == "" || path.Base(r.URL.Path) == "login" {
|
if jwtConfig.Secret == "" || path.Base(r.URL.Path) == "login" {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
|
@ -178,16 +179,22 @@ func Parse[T any](w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPAccessControl 中间件实现IP访问控制
|
func getServerConfig(r *http.Request) *model.HttpServerConfig {
|
||||||
func IPAccessControl(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
|
||||||
|
|
||||||
// get serverName from request context
|
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
serverName, ok := ctx.Value(RequestCtxKey("serverName")).(string)
|
serverName, ok := ctx.Value(RequestCtxKey("serverName")).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
serverName = ""
|
serverName = ""
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
config := model.GetServerConfig(serverName)
|
config := model.GetServerConfig(serverName)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAccessControl 中间件实现IP访问控制
|
||||||
|
func IPAccessControl(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||||
|
|
||||||
|
// get serverName from request context
|
||||||
|
config := getServerConfig(r)
|
||||||
if config != nil {
|
if config != nil {
|
||||||
allowedIPs := config.AllowIPs
|
allowedIPs := config.AllowIPs
|
||||||
deniedIPs := config.DenyIPs
|
deniedIPs := config.DenyIPs
|
||||||
|
@ -215,6 +222,8 @@ func IPAccessControl(w http.ResponseWriter, r *http.Request, next http.Handler)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
http.Error(w, "Server Config Error", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
|
|
@ -34,7 +34,7 @@ func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
func (route *Route) Match(r *http.Request) bool {
|
func (route *Route) Match(r *http.Request) bool {
|
||||||
l := logger.GetLogger("Route")
|
l := logger.GetLogger("Route")
|
||||||
l.Debug(fmt.Sprintf("matching route: %s %s with %s %s", r.Method, r.URL.Path, route.Method, route.Path))
|
l.Debug(fmt.Sprintf("matching route: %s %s with %s %s", r.Method, r.URL.Path, route.Method, route.Path))
|
||||||
if route.Method != "" && route.Method != r.Method {
|
if route.Method != "" && strings.ToLower(route.Method) != strings.ToLower(r.Method) {
|
||||||
l.Debug("method not match")
|
l.Debug("method not match")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -216,11 +216,26 @@ type ServerMux struct {
|
||||||
wrappedHandler map[string]http.Handler
|
wrappedHandler map[string]http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerMux) Handle(pattern string, handler http.Handler) {
|
func (s *ServerMux) Handle(pattern string, handler http.Handler, directives []string) {
|
||||||
if s.handlers == nil {
|
if s.handlers == nil {
|
||||||
s.handlers = make(map[string]http.Handler)
|
s.handlers = make(map[string]http.Handler)
|
||||||
}
|
}
|
||||||
s.handlers[pattern] = s.directiveHandlers.WrapHandler(handler)
|
nMiddleWareLink := s.directiveHandlers.Clone()
|
||||||
|
for _, directive := range directives {
|
||||||
|
strs := strings.Split(directive, " ")
|
||||||
|
directiveName := strs[0]
|
||||||
|
p := strings.Split(directiveName, "_")
|
||||||
|
if len(p) > 1 {
|
||||||
|
continue // 跳过自定义指令
|
||||||
|
}
|
||||||
|
params := strs[1:]
|
||||||
|
directive, ok := DirectiveMap[directiveName]
|
||||||
|
if ok {
|
||||||
|
nMiddleWareLink.Add(directive(params...))
|
||||||
|
}
|
||||||
|
// nMiddleWareLink.Add(GetDirective(directive))
|
||||||
|
}
|
||||||
|
s.handlers[pattern] = nMiddleWareLink.WrapHandler(handler)
|
||||||
s.paths = append(s.paths, pattern)
|
s.paths = append(s.paths, pattern)
|
||||||
// 自定义比较函数排序s.paths
|
// 自定义比较函数排序s.paths
|
||||||
sort.Slice(s.paths, func(i, j int) bool {
|
sort.Slice(s.paths, func(i, j int) bool {
|
||||||
|
@ -263,23 +278,7 @@ func (s *ServerMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
fhandler.ServeHTTP(w, newRequest)
|
fhandler.ServeHTTP(w, newRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// s.handlers[p].ServeHTTP(w, newRequest)
|
|
||||||
// s.directiveHandlers.ServeHTTP(w, newRequest)
|
|
||||||
// ctx := newRequest.Context()
|
|
||||||
// m := ctx.Value(RequestCtxKey("data")).(map[string]interface{})
|
|
||||||
// _, ok := m["Tg"]
|
|
||||||
// if ok {
|
|
||||||
// wrappedHandler := s.wrappedHandler[p]
|
|
||||||
// if wrappedHandler == nil {
|
|
||||||
// s.wrappedHandler[p] = gzip.DefaultHandler().WrapHandler(s.handlers[p])
|
|
||||||
// wrappedHandler = s.wrappedHandler[p]
|
|
||||||
// }
|
|
||||||
// wrappedHandler.ServeHTTP(w, newRequest)
|
|
||||||
// } else {
|
|
||||||
// s.handlers[p].ServeHTTP(w, newRequest)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.Error(fmt.Sprintf("404: %s", r.URL.Path))
|
l.Error(fmt.Sprintf("404: %s", r.URL.Path))
|
||||||
|
@ -318,18 +317,19 @@ func NewServeMux(c *model.HttpServerConfig) *ServerMux {
|
||||||
// 将指令添加到 ServerMux 的指令处理中间件链中
|
// 将指令添加到 ServerMux 的指令处理中间件链中
|
||||||
s.AddDirective(string(directive))
|
s.AddDirective(string(directive))
|
||||||
}
|
}
|
||||||
if c.AuthType == "jwt" {
|
// if c.AuthType == "jwt" {
|
||||||
s.AddDirective("Jwt-Auth")
|
// s.AddDirective("Jwt-Auth")
|
||||||
}
|
// }
|
||||||
if c.AuthType == "basic" {
|
// if c.AuthType == "basic" {
|
||||||
s.AddDirective("Basic-Auth")
|
// s.AddDirective("Basic-Auth")
|
||||||
}
|
// }
|
||||||
// 遍历配置中的所有 HTTP 路径
|
// 遍历配置中的所有 HTTP 路径
|
||||||
for _, httpPath := range c.Paths {
|
for _, httpPath := range c.Paths {
|
||||||
// 检查路径配置中是否指定了根目录
|
// 检查路径配置中是否指定了根目录
|
||||||
|
var fhandler http.Handler = nil
|
||||||
if httpPath.Root != "" {
|
if httpPath.Root != "" {
|
||||||
// 创建一个新的文件处理程序
|
// 创建一个新的文件处理程序
|
||||||
fileHandler := handler.NewFileHandler(handler.FileHandler{
|
fhandler = handler.NewFileHandler(handler.FileHandler{
|
||||||
WPath: httpPath.Path,
|
WPath: httpPath.Path,
|
||||||
// 设置文件处理程序的根目录
|
// 设置文件处理程序的根目录
|
||||||
Root: httpPath.Root,
|
Root: httpPath.Root,
|
||||||
|
@ -337,18 +337,23 @@ func NewServeMux(c *model.HttpServerConfig) *ServerMux {
|
||||||
Default: httpPath.Default,
|
Default: httpPath.Default,
|
||||||
})
|
})
|
||||||
// 将文件处理程序注册到 ServerMux 中
|
// 将文件处理程序注册到 ServerMux 中
|
||||||
s.Handle(httpPath.Path, fileHandler)
|
|
||||||
// 检查路径配置中是否指定了上游服务器
|
// 检查路径配置中是否指定了上游服务器
|
||||||
} else if len(httpPath.Upstreams) != 0 {
|
} else if len(httpPath.Upstreams) != 0 {
|
||||||
// 创建一个新的代理处理程序
|
// 创建一个新的代理处理程序
|
||||||
proxyHandler := handler.NewProxyHandler(&httpPath)
|
fhandler = handler.NewProxyHandler(&httpPath)
|
||||||
// 将代理处理程序注册到 ServerMux 中
|
// 将代理处理程序注册到 ServerMux 中
|
||||||
s.Handle(httpPath.Path, proxyHandler)
|
// s.Handle(httpPath.Path, proxyHandler)
|
||||||
// 如果既没有指定根目录也没有指定上游服务器
|
// 如果既没有指定根目录也没有指定上游服务器
|
||||||
} else {
|
} else {
|
||||||
// 记录不支持的路径类型错误信息
|
// 记录不支持的路径类型错误信息
|
||||||
l.Error("Not supportted server path type :", httpPath.Path)
|
l.Error("Not supportted server path type :", httpPath.Path)
|
||||||
}
|
}
|
||||||
|
if fhandler != nil {
|
||||||
|
directives := httpPath.Directives
|
||||||
|
s.Handle(httpPath.Path, fhandler, directives)
|
||||||
|
}
|
||||||
|
// s.Handle(httpPath.Path, fhandler)
|
||||||
}
|
}
|
||||||
// 返回初始化好的 ServerMux 实例
|
// 返回初始化好的 ServerMux 实例
|
||||||
return s
|
return s
|
||||||
|
|
Loading…
Reference in New Issue