refactor(config): 重构配置处理逻辑
- 移除 config.json 中的 admin 配置,改为单独的配置文件 - 新增 Strings 类型处理服务器名称,支持字符串和字符串数组 - 优化服务器匹配逻辑,支持多域名配置 - 重构代码结构,提高可维护性和可扩展性
This commit is contained in:
parent
949de14d47
commit
1b0db0e14b
33
config.json
33
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
21
gohttp.go
21
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)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "teststatic",
|
||||
"server": "www.teststatic.com",
|
||||
"port": 8088,
|
||||
"paths": [
|
||||
{
|
||||
"path": "/",
|
||||
"root": "./example",
|
||||
"default": "index.html"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue