diff --git a/admin/admin.go b/admin/admin.go index 9617950..5c9b713 100644 --- a/admin/admin.go +++ b/admin/admin.go @@ -26,7 +26,7 @@ var AdminRoutes = []Route{ var AdminServerMux *server.RestMux func init() { - AdminServerMux = server.NewRestMux("/admin") + AdminServerMux = server.NewRestMux("/") // AdminServerMux.routes = make(map[string]map[string]http.HandlerFunc) for _, route := range AdminRoutes { AdminServerMux.HandleFunc(route.Method, route.Path, route.Handle) diff --git a/config.json b/config.json new file mode 100644 index 0000000..b1fd2f6 --- /dev/null +++ b/config.json @@ -0,0 +1,18 @@ +{ + "logging" :{ + "appenders": { + "out" :{ + "type": "console" + } + }, + "categories": { + "default": { + "appenders": [ "out" ], + "level": "debug" + } + } + }, + "admin" : { + "port" : 8088 + } +} \ No newline at end of file diff --git a/gohttp.go b/gohttp.go new file mode 100644 index 0000000..98c9525 --- /dev/null +++ b/gohttp.go @@ -0,0 +1,61 @@ +package main + +import ( + "encoding/json" + "net/http" + "os" + + "git.pyer.club/kingecg/gohttpd/admin" + "git.pyer.club/kingecg/gohttpd/model" + "git.pyer.club/kingecg/gohttpd/server" + "git.pyer.club/kingecg/gologger" +) + +type GoHttp struct { + conf model.GoHttpdConfig + logger gologger.Logger +} + +func (g *GoHttp) Start() { + g.logger.Info("start gohttpd") + // if g.conf != nil { + port := model.DefaultAdminConfig.Port + if g.conf.Admin != nil { + port = g.conf.Admin.Port + } + + g.makeServer("admin", port, admin.AdminServerMux) + + //TODO: create other server + // } + + for _, listener := range server.ServerManager { + listener.Start() + listener.Serve() + + } + g.logger.Info("gohttpd start success") +} + +func (g *GoHttp) makeServer(name string, port int, mux *server.RestMux) { + s := &http.Server{ + Handler: mux, + } + server.AddServer(name, s, port) +} + +func (g *GoHttp) Stop() {} + +func (g *GoHttp) LoadConfig(configPath string) { + cpath := configPath + if cpath == "" { + cpath = GetExecDir() + "/config.json" + } + + // read content from cpath + content, _ := os.ReadFile(cpath) + json.Unmarshal(content, &g.conf) + gologger.Configure(g.conf.Logging) + g.logger = gologger.GetLogger("Server") + g.logger.Info("Load config success") +} diff --git a/main.go b/main.go index de6af28..59d8c58 100644 --- a/main.go +++ b/main.go @@ -1,55 +1,53 @@ package main import ( - "net/http" "os" "os/signal" "syscall" - - admin "git.pyer.club/kingecg/gohttpd/admin" - "git.pyer.club/kingecg/gohttpd/server" - logger "git.pyer.club/kingecg/gologger" ) func main() { - logger.Configure(logger.LoggersConfig{ - Categories: map[string]logger.LogConfig{ - "default": { - Level: "debug", - Appenders: []string{ - "console", - }, - }, - "fat": { - Level: "debug", - Appenders: []string{ - "console", - "file", - }, - }, - }, - Appenders: map[string]logger.LogAppenderConfig{ - "console": { - Type: "console", - }, - "file": { - Type: "file", - Options: map[string]interface{}{ - "file": "./log/fat.log", - }, - }, - }, - }) - defaultLogger := logger.GetLogger("default") - defaultLogger.Info("Listening...") - serverMux := server.NewRestMux("/") - serverMux.HandleMux(admin.AdminServerMux) - go http.ListenAndServe(":8080", serverMux) - defaultLogger.Debug("Next") + // logger.Configure(logger.LoggersConfig{ + // Categories: map[string]logger.LogConfig{ + // "default": { + // Level: "debug", + // Appenders: []string{ + // "console", + // }, + // }, + // "fat": { + // Level: "debug", + // Appenders: []string{ + // "console", + // "file", + // }, + // }, + // }, + // Appenders: map[string]logger.LogAppenderConfig{ + // "console": { + // Type: "console", + // }, + // "file": { + // Type: "file", + // Options: map[string]interface{}{ + // "file": "./log/fat.log", + // }, + // }, + // }, + // }) + // defaultLogger := logger.GetLogger("default") + // defaultLogger.Info("Listening...") + // serverMux := server.NewRestMux("/") + // serverMux.HandleMux(admin.AdminServerMux) + // go http.ListenAndServe(":8080", serverMux) + // defaultLogger.Debug("Next") + httpd := &GoHttp{} + httpd.LoadConfig("") + httpd.Start() var waiter = make(chan os.Signal, 1) // buffered channel signal.Notify(waiter, syscall.SIGTERM, syscall.SIGINT) // blocks here until there's a signal <-waiter - defaultLogger.Info("Listened") + } diff --git a/model/model.go b/model/model.go index e6e0864..1ad7b07 100644 --- a/model/model.go +++ b/model/model.go @@ -1,5 +1,7 @@ package model +import "git.pyer.club/kingecg/gologger" + type HttpPath struct { Path string `json:"path"` Root string `json:"root"` @@ -15,8 +17,9 @@ type HttpServerConfig struct { } type GoHttpdConfig struct { - Admin HttpServerConfig `json:"admin"` - Servers []HttpServerConfig `json:"servers"` + Logging gologger.LoggersConfig `json:"logging"` + Admin *HttpServerConfig `json:"admin"` + Servers []*HttpServerConfig `json:"servers"` } var DefaultAdminConfig HttpServerConfig = HttpServerConfig{ diff --git a/server/manager.go b/server/manager.go index 2b03881..ec89ae4 100644 --- a/server/manager.go +++ b/server/manager.go @@ -5,6 +5,10 @@ import ( "fmt" "net" "net/http" + "strings" + + "bufio" + "io" logger "git.pyer.club/kingecg/gologger" "github.com/soheilhy/cmux" @@ -12,6 +16,16 @@ import ( var ServerManager map[string]*ServerListener = make(map[string]*ServerListener) +func makeMatcher(name string) cmux.Matcher { + return func(r io.Reader) bool { + req, err := http.ReadRequest(bufio.NewReader(r)) + if err != nil { + return false + } + return strings.HasPrefix(req.Host, name) + } +} + type ServerListener struct { listener cmux.CMux servers map[string]*http.Server @@ -27,17 +41,19 @@ func (s *ServerListener) StartServer(name string) error { panic("No named server") } - l := s.listener.Match(cmux.HTTP1HeaderField("Host", name)) + l := s.listener.Match(makeMatcher(name)) return server.Serve(l) } func (s *ServerListener) Start() { for name, _ := range s.servers { - err := s.StartServer(name) - if err != nil { - l := logger.GetLogger("ServerListener") - l.Error("Start server error:", name, err) - } + go func(name string) { + err := s.StartServer(name) + if err != nil { + l := logger.GetLogger("ServerListener") + l.Error("Start server error:", name, err) + } + }(name) } } @@ -64,3 +80,13 @@ func NewServerListener(port int) *ServerListener { s := &ServerListener{listener: muxer, servers: make(map[string]*http.Server)} return s } + +func AddServer(name string, server *http.Server, port int) { + listenStr := fmt.Sprintf(":%d", port) + listener, ok := ServerManager[listenStr] + if !ok { + listener = NewServerListener(port) + ServerManager[listenStr] = listener + } + listener.AddServer(name, server) +} diff --git a/server/server.go b/server/server.go index c87850f..e7622af 100644 --- a/server/server.go +++ b/server/server.go @@ -15,7 +15,7 @@ type RestMux struct { } func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { - _, has := lo.Find[string](mux.rmuxPaths, func(s string) bool { + _, has := lo.Find(mux.rmuxPaths, func(s string) bool { return strings.HasPrefix(r.URL.Path, s) }) if has { diff --git a/util.go b/util.go new file mode 100644 index 0000000..4ae961c --- /dev/null +++ b/util.go @@ -0,0 +1,15 @@ +package main + +import ( + "os" + "path/filepath" +) + +func GetExecDir() string { + + execPath, err := os.Executable() + if err != nil { + panic(err) + } + return filepath.Dir(execPath) +}