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": {
|
"includs":"./include",
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"servers": [
|
"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")
|
g.logger.Info("start gohttpd")
|
||||||
|
|
||||||
// if g.conf != nil {
|
// 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)
|
g.makeServer(conf.Admin, adminHandler)
|
||||||
admin.InitAdminApi(conf.Admin)
|
} else {
|
||||||
adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux), []string{})
|
g.logger.Info("no admin server config, skip admin server")
|
||||||
|
}
|
||||||
// 创建并启动管理员服务器
|
|
||||||
g.makeServer(conf.Admin, adminHandler)
|
|
||||||
|
|
||||||
// 遍历配置中的服务器列表,为每个服务器设置处理器并启动
|
// 遍历配置中的服务器列表,为每个服务器设置处理器并启动
|
||||||
for _, s := range conf.Servers {
|
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 != "" {
|
if model.Config.IncludDir != "" {
|
||||||
model.Config.IncludDir = utils.NormalizePath(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服务器配置
|
// HttpServerConfig 定义HTTP服务器配置
|
||||||
type HttpServerConfig struct {
|
type HttpServerConfig struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ServerName string `json:"server"`
|
ServerName Strings `json:"server"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Paths []HttpPath `json:"paths"`
|
Paths []HttpPath `json:"paths"`
|
||||||
|
@ -64,12 +64,12 @@ type JwtConfig struct {
|
||||||
type GoHttpdConfig struct {
|
type GoHttpdConfig struct {
|
||||||
Logging gologger.LoggersConfig `json:"logging"`
|
Logging gologger.LoggersConfig `json:"logging"`
|
||||||
Admin *HttpServerConfig `json:"admin"`
|
Admin *HttpServerConfig `json:"admin"`
|
||||||
IncludDir string `json:"includ_dir"`
|
IncludDir string `json:"includs"`
|
||||||
Servers []*HttpServerConfig `json:"servers"`
|
Servers []*HttpServerConfig `json:"servers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultAdminConfig HttpServerConfig = HttpServerConfig{
|
var DefaultAdminConfig HttpServerConfig = HttpServerConfig{
|
||||||
ServerName: "admin",
|
ServerName: Strings{"admin"},
|
||||||
Port: 8080,
|
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"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
|
@ -17,7 +16,7 @@ import (
|
||||||
|
|
||||||
var ServerManager map[string]*ServerListener = make(map[string]*ServerListener)
|
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 {
|
return func(r io.Reader) bool {
|
||||||
if s.ServerCount() == 1 {
|
if s.ServerCount() == 1 {
|
||||||
return true
|
return true
|
||||||
|
@ -26,7 +25,7 @@ func makeMatcher(name string, s *ServerListener) cmux.Matcher {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return strings.HasPrefix(req.Host, name)
|
return name.HasOrContainPrefix(req.Host) || name.HasOrContainPrefix(req.URL.Host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue