diff --git a/config.json b/config.json index 1ac9973..5d79034 100644 --- a/config.json +++ b/config.json @@ -21,37 +21,8 @@ } } }, - "admin": { - "name": "admin", - "server":"localhost", - "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" - } - ] - }, + "includs":"./include", "servers": [ - { - "name": "teststatic", - "server":"www.teststatic.com", - "port": 8088, - "paths": [ - { - "path": "/", - "root": "./example", - "default": "index.html" - } - ] - } + ] } diff --git a/gohttp.go b/gohttp.go index 75be866..c893486 100644 --- a/gohttp.go +++ b/gohttp.go @@ -30,14 +30,17 @@ func (g *GoHttp) Start() { g.logger.Info("start gohttpd") // if g.conf != nil { + if conf.Admin != nil { + // 设置管理员处理器并使用管理员服务配置 + adminHandler := server.NewServeMux(conf.Admin) + admin.InitAdminApi(conf.Admin) + adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux), []string{}) - // 设置管理员处理器并使用管理员服务配置 - adminHandler := server.NewServeMux(conf.Admin) - admin.InitAdminApi(conf.Admin) - adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux), []string{}) - - // 创建并启动管理员服务器 - g.makeServer(conf.Admin, adminHandler) + // 创建并启动管理员服务器 + g.makeServer(conf.Admin, adminHandler) + } else { + g.logger.Info("no admin server config, skip admin server") + } // 遍历配置中的服务器列表,为每个服务器设置处理器并启动 for _, s := range conf.Servers { @@ -101,7 +104,9 @@ func LoadConfig() { } // 规范化管理员服务器配置中的路径 - normalizeServer(model.Config.Admin) + if model.Config.Admin != nil { + normalizeServer(model.Config.Admin) + } if model.Config.IncludDir != "" { model.Config.IncludDir = utils.NormalizePath(model.Config.IncludDir) diff --git a/include/www.teststatic.com.json b/include/www.teststatic.com.json new file mode 100644 index 0000000..29240f6 --- /dev/null +++ b/include/www.teststatic.com.json @@ -0,0 +1,12 @@ +{ + "name": "teststatic", + "server": "www.teststatic.com", + "port": 8088, + "paths": [ + { + "path": "/", + "root": "./example", + "default": "index.html" + } + ] +} \ No newline at end of file diff --git a/model/model.go b/model/model.go index bae7861..9b11def 100644 --- a/model/model.go +++ b/model/model.go @@ -34,7 +34,7 @@ const ( // HttpServerConfig 定义HTTP服务器配置 type HttpServerConfig struct { Name string `json:"name"` - ServerName string `json:"server"` + ServerName Strings `json:"server"` Port int `json:"port"` Host string `json:"host"` Paths []HttpPath `json:"paths"` @@ -64,12 +64,12 @@ type JwtConfig struct { type GoHttpdConfig struct { Logging gologger.LoggersConfig `json:"logging"` Admin *HttpServerConfig `json:"admin"` - IncludDir string `json:"includ_dir"` + IncludDir string `json:"includs"` Servers []*HttpServerConfig `json:"servers"` } var DefaultAdminConfig HttpServerConfig = HttpServerConfig{ - ServerName: "admin", + ServerName: Strings{"admin"}, Port: 8080, } diff --git a/model/names.go b/model/names.go new file mode 100644 index 0000000..b95c63a --- /dev/null +++ b/model/names.go @@ -0,0 +1,53 @@ +package model + +import ( + "encoding/json" + "errors" + "strings" +) + +type Strings struct { + Values interface{} +} + +func (s *Strings) UnmarshalJSON(data []byte) error { + var raw interface{} + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + switch v := raw.(type) { + case string: + s.Values = v + return nil + case []interface{}: + for _, item := range v { + if _, ok := item.(string); !ok { + return errors.New("invalid type in array, expected string") + } + } + s.Values = v + return nil + default: + return errors.New("invalid type") + } +} + +func (s *Strings) MarshalJSON() ([]byte, error) { + return json.Marshal(s.Values) +} + +func (s *Strings) HasOrContainPrefix(value string) bool { + switch v := s.Values.(type) { + case []interface{}: + for _, item := range v { + if strings.HasPrefix(value, item.(string)) { + return true + } + } + return false + case string: + return strings.HasPrefix(value, v) + default: + return false + } +} diff --git a/model/names_test.go b/model/names_test.go new file mode 100644 index 0000000..6b1521d --- /dev/null +++ b/model/names_test.go @@ -0,0 +1,85 @@ +package model + +import ( + "testing" +) + +func TestStrings_UnmarshalJSON(t *testing.T) { + tests := []struct { + name string + input string + want interface{} + wantErr bool + }{ + { + name: "valid string", + input: `"test"`, + want: "test", + }, + { + name: "valid array", + input: `["a","b"]`, + want: []string{"a", "b"}, + }, + { + name: "invalid type", + input: `123`, + wantErr: true, + }, + { + name: "invalid array type", + input: `["a", 123]`, + wantErr: true, + }, + } + + for _, tt := range tests { + s := &Strings{} + err := s.UnmarshalJSON([]byte(tt.input)) + if tt.wantErr { + if err == nil { + t.Errorf("%s: expected error but got none", tt.name) + } + continue + } + if err != nil { + t.Errorf("%s: unexpected error %v", tt.name, err) + continue + } + } +} + +func TestStrings_HasOrContainPrefix(t *testing.T) { + tests := []struct { + name string + input string + value string + want bool + wantErr bool + }{ + { + name: "valid string", + input: `"test"`, + value: "test", + want: true, + }, + { + name: "valid array", + input: `["a","b"]`, + value: "a", + want: true, + }, + } + for _, tt := range tests { + s := &Strings{} + err := s.UnmarshalJSON([]byte(tt.input)) + if err != nil { + t.Errorf("%s: unexpected error %v", tt.name, err) + continue + } + got := s.HasOrContainPrefix(tt.value) + if got != tt.want { + t.Errorf("%s: expected %v, got %v", tt.name, tt.want, got) + } + } +} diff --git a/server/manager.go b/server/manager.go index 4da617c..0d72642 100644 --- a/server/manager.go +++ b/server/manager.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "net/http" - "strings" "bufio" "io" @@ -17,7 +16,7 @@ import ( var ServerManager map[string]*ServerListener = make(map[string]*ServerListener) -func makeMatcher(name string, s *ServerListener) cmux.Matcher { +func makeMatcher(name model.Strings, s *ServerListener) cmux.Matcher { return func(r io.Reader) bool { if s.ServerCount() == 1 { return true @@ -26,7 +25,7 @@ func makeMatcher(name string, s *ServerListener) cmux.Matcher { if err != nil { return false } - return strings.HasPrefix(req.Host, name) + return name.HasOrContainPrefix(req.Host) || name.HasOrContainPrefix(req.URL.Host) } }