change and correct

This commit is contained in:
程广 2025-05-30 18:42:53 +08:00
parent ea38f85fb7
commit 0a667bea96
15 changed files with 2052 additions and 301 deletions

5
.hintrc Normal file
View File

@ -0,0 +1,5 @@
{
"extends": [
"development"
]
}

View File

@ -116,11 +116,7 @@ paths 配置
"servers":[{
"port" : 8080,
"name":"test",
"health_check": {
"interval": "10s", // 每10秒检查一次
"timeout": "5s", // 每次检查5秒超时
"retries": 3 // 失败3次才认为是不健康
},
"paths":[{
"path": "/",
"root": "/home/kingecg/code/gohttp/public/",
@ -133,7 +129,12 @@ paths 配置
"HeaderOrigin",
"Path /ws /",
"RemoveCookie token"
]
],
"health_check": {
"interval": "10s", // 每10秒检查一次
"timeout": "5s", // 每次检查5秒超时
"retries": 3 // 失败3次才认为是不健康
},
}]
}]
}
@ -158,6 +159,10 @@ paths 配置
- 返回的response中设置header
- 反向代理时,修改发送到上游服务器的请求
命名规则:
模块支持的指令以模块名作为前缀Proxy_Path 是反向代理模块的Path指令。
没有前缀的是全局指令Set-Header 是设置header的指令。
## Packages
### Server

BIN
__debug_bin1861531173 Executable file

Binary file not shown.

View File

@ -77,16 +77,53 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
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
func init() {
func InitAdminApi(conf *model.HttpServerConfig) {
AdminServerMux = server.NewRestMux("/api")
AdminServerMux.Use(server.JwtAuth)
if conf.AuthType == "jwt" {
AdminServerMux.Use(server.JwtAuth)
} else if conf.AuthType == "basic" {
AdminServerMux.Use(server.BasicAuth)
}
// AdminServerMux.Use(server.JwtAuth)
AdminServerMux.HandleFunc("GET", "/about", http.HandlerFunc(about))
postConfigRoute := AdminServerMux.HandleFunc("POST", "/config", http.HandlerFunc(setConfig))
postConfigRoute.Add(server.Parse[model.HttpServerConfig])
AdminServerMux.HandleFunc("GET", "/config/:id", http.HandlerFunc(getServerConfigure))
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.Add(server.Parse[LoginModel])
// AdminServerMux.Use(server.BasicAuth)

View File

@ -23,6 +23,7 @@
},
"admin": {
"name": "admin",
"server":"admin",
"port": 8088,
"username": "admin",
"password": "admin",
@ -40,183 +41,15 @@
]
},
"servers": [
{
"port": 3000,
"name": "cloudops",
"name": "teststatic",
"server":"www.teststatic.com",
"port": 8088,
"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"
]
"root": "./example",
"default": "index.html"
}
]
}

224
config.jsonbak Normal file
View File

@ -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"
]
}
]
}
]
}

9
example/index.html Normal file
View File

@ -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>

View File

@ -32,7 +32,8 @@ func (g *GoHttp) Start() {
// 设置管理员处理器并使用管理员服务配置
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)

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,8 @@ func makeProxy(upstream string, path *model.HttpPath, index int) *httputil.Rever
directiveHandlers := []func(r *http.Request){}
if len(path.Directives) > 0 {
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)
if dh != nil {
directiveHandlers = append(directiveHandlers, dh)
@ -106,48 +107,45 @@ func NewProxyHandler(p *model.HttpPath) *ProxyHandler {
}
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 {
ph.proxy[index] = makeProxy(upstream, p, index)
}
// 使用配置参数创建健康检查器
ph.checker = healthcheck.NewHealthChecker(interval, timeout, retries)
ph.checker.StartHealthCheck(ph.Upstreams, func(upstream string, healthy bool) {
// 当上游服务器状态变化时的回调函数
logger := gologger.GetLogger("Proxy")
if !healthy {
logger.Warn(fmt.Sprintf("Upstream %s is now unhealthy", upstream))
} else {
logger.Info(fmt.Sprintf("Upstream %s is now healthy", upstream))
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.StartHealthCheck(ph.Upstreams, func(upstream string, healthy bool) {
// 当上游服务器状态变化时的回调函数
logger := gologger.GetLogger("Proxy")
if !healthy {
logger.Warn(fmt.Sprintf("Upstream %s is now unhealthy", upstream))
} else {
logger.Info(fmt.Sprintf("Upstream %s is now healthy", upstream))
}
})
}
return ph
}
}

View File

@ -12,16 +12,17 @@ import (
type HealthCheckConfig struct {
Interval string `json:"interval,omitempty"` // 检查间隔时间
Timeout string `json:"timeout,omitempty"` // 单次检查超时时间
Retries int `json:"retries,omitempty"` // 健康检查失败重试次数
Retries int `json:"retries,omitempty"` // 健康检查失败重试次数
}
// HttpPath 定义HTTP路径配置
type HttpPath struct {
Path string `json:"path"`
Root string `json:"root"`
Default string `json:"default"`
Upstreams []string `json:"upstreams"`
Directives []string `json:"directives"`
Path string `json:"path"`
Root string `json:"root"`
Default string `json:"default"`
Upstreams []string `json:"upstreams"`
Directives []string `json:"directives"`
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
}
type HeaderValueConst string
@ -32,10 +33,10 @@ const (
// HttpServerConfig 定义HTTP服务器配置
type HttpServerConfig struct {
Name string `json:"name"`
ServerName string `json:"server"`
Port int `json:"port"`
Host string `json:"host"`
Name string `json:"name"`
ServerName string `json:"server"`
Port int `json:"port"`
Host string `json:"host"`
Paths []HttpPath `json:"paths"`
Username string `json:"username"`
Password string `json:"password"`
@ -45,10 +46,10 @@ type HttpServerConfig struct {
AuthType string `json:"auth_type"`
Jwt *JwtConfig `json:"jwt"`
// 健康检查配置
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
// 访问控制配置
AllowIPs []string `json:"allow_ips,omitempty"` // 允许访问的IP地址列表
DenyIPs []string `json:"deny_ips,omitempty"` // 禁止访问的IP地址列表
AllowIPs []string `json:"allow_ips,omitempty"` // 允许访问的IP地址列表
DenyIPs []string `json:"deny_ips,omitempty"` // 禁止访问的IP地址列表
}
type JwtConfig struct {

View File

@ -71,7 +71,7 @@ var BasicAuthDirective Directive = func(args ...string) Middleware {
var DirectiveMap = map[string]Directive{
"Set-Header": Set_Header,
"Add-Header": Add_Header,
"Gzip_Response": Gzip_Response,
"Gzip-Response": Gzip_Response,
"Record-Access": DRecordAccess,
"Jwt-Auth": JWTDirective,
"Basic-Auth": BasicAuthDirective,

View File

@ -2,10 +2,12 @@ package server
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"strings"
"time"
"bufio"
"io"
@ -30,10 +32,37 @@ func makeMatcher(name string, s *ServerListener) cmux.Matcher {
}
}
type Server struct {
Conf *model.HttpServerConfig
*http.Server
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 {
Conf *model.HttpServerConfig
Closed bool
*http.Server
l *sl
}
func (s *Server) Renew() {
s.Server = &http.Server{
Handler: s.Handler,
}
}
type ServerListener struct {
port int
listener cmux.CMux
@ -48,28 +77,64 @@ func (s *ServerListener) ServerCount() int {
return len(s.servers)
}
func (s *ServerListener) StartServer(name string) error {
func (s *ServerListener) StartServer(name string) {
server, ok := s.servers[name]
serverName := server.Conf.ServerName
if !ok {
panic("No named server")
}
l := s.listener.Match(makeMatcher(name, s))
if server.Conf.CertFile != "" && server.Conf.KeyFile != "" {
return server.ServeTLS(l, server.Conf.CertFile, server.Conf.KeyFile)
}
return server.Serve(l)
go func() {
var err error
defer func() {
l := logger.GetLogger("ServerListener")
if err != nil {
if err == http.ErrServerClosed {
server.Closed = true
} else {
l.Error("Server error:", err)
}
}
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) StopServer(name string) error {
server, ok := s.servers[name]
if !ok {
return nil
}
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 {
go func(name string) {
err := s.StartServer(name)
if err != nil {
l := logger.GetLogger("ServerListener")
l.Error("Start server error:", name, err)
}
}(name)
// 为每个服务器启动一个新的 goroutine 来执行启动操作
s.StartServer(name)
}
}
@ -109,3 +174,35 @@ func AddServer(name string, server *Server, port int) {
}
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)
}

View File

@ -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 {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m(w, r, next)
@ -84,6 +69,18 @@ func (ml *MiddlewareLink) WrapHandler(next http.Handler) http.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 {
ml := &MiddlewareLink{list.New()}
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) {
l := gologger.GetLogger("JwtAuth")
config := model.GetConfig()
jwtConfig := config.Admin.Jwt
config := getServerConfig(r)
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" {
next.ServeHTTP(w, r)
return
@ -178,16 +179,22 @@ func Parse[T any](w http.ResponseWriter, r *http.Request, next http.Handler) {
next.ServeHTTP(w, r)
}
// IPAccessControl 中间件实现IP访问控制
func IPAccessControl(w http.ResponseWriter, r *http.Request, next http.Handler) {
// get serverName from request context
func getServerConfig(r *http.Request) *model.HttpServerConfig {
ctx := r.Context()
serverName, ok := ctx.Value(RequestCtxKey("serverName")).(string)
if !ok {
serverName = ""
return nil
}
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 {
allowedIPs := config.AllowIPs
deniedIPs := config.DenyIPs
@ -215,6 +222,8 @@ func IPAccessControl(w http.ResponseWriter, r *http.Request, next http.Handler)
return
}
}
} else {
http.Error(w, "Server Config Error", http.StatusInternalServerError)
}
next.ServeHTTP(w, r)

View File

@ -34,7 +34,7 @@ func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (route *Route) Match(r *http.Request) bool {
l := logger.GetLogger("Route")
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")
return false
}
@ -216,11 +216,26 @@ type ServerMux struct {
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 {
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
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)
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))
@ -318,18 +317,19 @@ func NewServeMux(c *model.HttpServerConfig) *ServerMux {
// 将指令添加到 ServerMux 的指令处理中间件链中
s.AddDirective(string(directive))
}
if c.AuthType == "jwt" {
s.AddDirective("Jwt-Auth")
}
if c.AuthType == "basic" {
s.AddDirective("Basic-Auth")
}
// if c.AuthType == "jwt" {
// s.AddDirective("Jwt-Auth")
// }
// if c.AuthType == "basic" {
// s.AddDirective("Basic-Auth")
// }
// 遍历配置中的所有 HTTP 路径
for _, httpPath := range c.Paths {
// 检查路径配置中是否指定了根目录
var fhandler http.Handler = nil
if httpPath.Root != "" {
// 创建一个新的文件处理程序
fileHandler := handler.NewFileHandler(handler.FileHandler{
fhandler = handler.NewFileHandler(handler.FileHandler{
WPath: httpPath.Path,
// 设置文件处理程序的根目录
Root: httpPath.Root,
@ -337,18 +337,23 @@ func NewServeMux(c *model.HttpServerConfig) *ServerMux {
Default: httpPath.Default,
})
// 将文件处理程序注册到 ServerMux 中
s.Handle(httpPath.Path, fileHandler)
// 检查路径配置中是否指定了上游服务器
} else if len(httpPath.Upstreams) != 0 {
// 创建一个新的代理处理程序
proxyHandler := handler.NewProxyHandler(&httpPath)
fhandler = handler.NewProxyHandler(&httpPath)
// 将代理处理程序注册到 ServerMux 中
s.Handle(httpPath.Path, proxyHandler)
// s.Handle(httpPath.Path, proxyHandler)
// 如果既没有指定根目录也没有指定上游服务器
} else {
// 记录不支持的路径类型错误信息
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 实例
return s