fix mux matcher

This commit is contained in:
kingecg 2023-12-08 22:02:36 +08:00
parent 57225ac59a
commit 61258c5535
8 changed files with 171 additions and 50 deletions

View File

@ -26,7 +26,7 @@ var AdminRoutes = []Route{
var AdminServerMux *server.RestMux var AdminServerMux *server.RestMux
func init() { func init() {
AdminServerMux = server.NewRestMux("/admin") AdminServerMux = server.NewRestMux("/")
// AdminServerMux.routes = make(map[string]map[string]http.HandlerFunc) // AdminServerMux.routes = make(map[string]map[string]http.HandlerFunc)
for _, route := range AdminRoutes { for _, route := range AdminRoutes {
AdminServerMux.HandleFunc(route.Method, route.Path, route.Handle) AdminServerMux.HandleFunc(route.Method, route.Path, route.Handle)

18
config.json Normal file
View File

@ -0,0 +1,18 @@
{
"logging" :{
"appenders": {
"out" :{
"type": "console"
}
},
"categories": {
"default": {
"appenders": [ "out" ],
"level": "debug"
}
}
},
"admin" : {
"port" : 8088
}
}

61
gohttp.go Normal file
View File

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

78
main.go
View File

@ -1,55 +1,53 @@
package main package main
import ( import (
"net/http"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
admin "git.pyer.club/kingecg/gohttpd/admin"
"git.pyer.club/kingecg/gohttpd/server"
logger "git.pyer.club/kingecg/gologger"
) )
func main() { func main() {
logger.Configure(logger.LoggersConfig{ // logger.Configure(logger.LoggersConfig{
Categories: map[string]logger.LogConfig{ // Categories: map[string]logger.LogConfig{
"default": { // "default": {
Level: "debug", // Level: "debug",
Appenders: []string{ // Appenders: []string{
"console", // "console",
}, // },
}, // },
"fat": { // "fat": {
Level: "debug", // Level: "debug",
Appenders: []string{ // Appenders: []string{
"console", // "console",
"file", // "file",
}, // },
}, // },
}, // },
Appenders: map[string]logger.LogAppenderConfig{ // Appenders: map[string]logger.LogAppenderConfig{
"console": { // "console": {
Type: "console", // Type: "console",
}, // },
"file": { // "file": {
Type: "file", // Type: "file",
Options: map[string]interface{}{ // Options: map[string]interface{}{
"file": "./log/fat.log", // "file": "./log/fat.log",
}, // },
}, // },
}, // },
}) // })
defaultLogger := logger.GetLogger("default") // defaultLogger := logger.GetLogger("default")
defaultLogger.Info("Listening...") // defaultLogger.Info("Listening...")
serverMux := server.NewRestMux("/") // serverMux := server.NewRestMux("/")
serverMux.HandleMux(admin.AdminServerMux) // serverMux.HandleMux(admin.AdminServerMux)
go http.ListenAndServe(":8080", serverMux) // go http.ListenAndServe(":8080", serverMux)
defaultLogger.Debug("Next") // defaultLogger.Debug("Next")
httpd := &GoHttp{}
httpd.LoadConfig("")
httpd.Start()
var waiter = make(chan os.Signal, 1) // buffered channel var waiter = make(chan os.Signal, 1) // buffered channel
signal.Notify(waiter, syscall.SIGTERM, syscall.SIGINT) signal.Notify(waiter, syscall.SIGTERM, syscall.SIGINT)
// blocks here until there's a signal // blocks here until there's a signal
<-waiter <-waiter
defaultLogger.Info("Listened")
} }

View File

@ -1,5 +1,7 @@
package model package model
import "git.pyer.club/kingecg/gologger"
type HttpPath struct { type HttpPath struct {
Path string `json:"path"` Path string `json:"path"`
Root string `json:"root"` Root string `json:"root"`
@ -15,8 +17,9 @@ type HttpServerConfig struct {
} }
type GoHttpdConfig struct { type GoHttpdConfig struct {
Admin HttpServerConfig `json:"admin"` Logging gologger.LoggersConfig `json:"logging"`
Servers []HttpServerConfig `json:"servers"` Admin *HttpServerConfig `json:"admin"`
Servers []*HttpServerConfig `json:"servers"`
} }
var DefaultAdminConfig HttpServerConfig = HttpServerConfig{ var DefaultAdminConfig HttpServerConfig = HttpServerConfig{

View File

@ -5,6 +5,10 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"strings"
"bufio"
"io"
logger "git.pyer.club/kingecg/gologger" logger "git.pyer.club/kingecg/gologger"
"github.com/soheilhy/cmux" "github.com/soheilhy/cmux"
@ -12,6 +16,16 @@ import (
var ServerManager map[string]*ServerListener = make(map[string]*ServerListener) 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 { type ServerListener struct {
listener cmux.CMux listener cmux.CMux
servers map[string]*http.Server servers map[string]*http.Server
@ -27,17 +41,19 @@ func (s *ServerListener) StartServer(name string) error {
panic("No named server") panic("No named server")
} }
l := s.listener.Match(cmux.HTTP1HeaderField("Host", name)) l := s.listener.Match(makeMatcher(name))
return server.Serve(l) return server.Serve(l)
} }
func (s *ServerListener) Start() { func (s *ServerListener) Start() {
for name, _ := range s.servers { for name, _ := range s.servers {
err := s.StartServer(name) go func(name string) {
if err != nil { err := s.StartServer(name)
l := logger.GetLogger("ServerListener") if err != nil {
l.Error("Start server error:", name, err) 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)} s := &ServerListener{listener: muxer, servers: make(map[string]*http.Server)}
return s 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)
}

View File

@ -15,7 +15,7 @@ type RestMux struct {
} }
func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { 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) return strings.HasPrefix(r.URL.Path, s)
}) })
if has { if has {

15
util.go Normal file
View File

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