mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-05 16:46:58 +08:00
加入summary 优化http监听逻辑,实现基本身份认证
This commit is contained in:
@@ -169,6 +169,9 @@ func Struct2Config(s any) (config Config) {
|
||||
}
|
||||
for i, j := 0, t.NumField(); i < j; i++ {
|
||||
ft := t.Field(i)
|
||||
if !ft.IsExported() {
|
||||
continue
|
||||
}
|
||||
name := strings.ToLower(ft.Name)
|
||||
switch ft.Type.Kind() {
|
||||
case reflect.Struct:
|
||||
|
@@ -4,27 +4,69 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
. "github.com/logrusorgru/aurora"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"m7s.live/engine/v4/log"
|
||||
"m7s.live/engine/v4/util"
|
||||
)
|
||||
|
||||
var _ HTTPConfig = (*HTTP)(nil)
|
||||
|
||||
type HTTP struct {
|
||||
ListenAddr string
|
||||
ListenAddrTLS string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
CORS bool //是否自动添加CORS头
|
||||
UserName string
|
||||
Password string
|
||||
mux *http.ServeMux
|
||||
}
|
||||
type HTTPConfig interface {
|
||||
InitMux()
|
||||
GetHTTPConfig() *HTTP
|
||||
Listen(ctx context.Context) error
|
||||
HandleFunc(string, func(http.ResponseWriter, *http.Request))
|
||||
}
|
||||
|
||||
func (config *HTTP) InitMux() {
|
||||
hasOwnTLS := config.ListenAddrTLS != "" && config.ListenAddrTLS != Global.ListenAddrTLS
|
||||
hasOwnHTTP := config.ListenAddr != "" && config.ListenAddr != Global.ListenAddr
|
||||
if hasOwnTLS || hasOwnHTTP {
|
||||
config.mux = http.NewServeMux()
|
||||
}
|
||||
}
|
||||
|
||||
func (config *HTTP) HandleFunc(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
if config.mux != nil {
|
||||
if config.CORS {
|
||||
f = util.CORS(f)
|
||||
}
|
||||
if config.UserName != "" && config.Password != "" {
|
||||
f = util.BasicAuth(config.UserName, config.Password, f)
|
||||
}
|
||||
config.mux.HandleFunc(path, f)
|
||||
}
|
||||
}
|
||||
|
||||
func (config *HTTP) GetHTTPConfig() *HTTP {
|
||||
return config
|
||||
}
|
||||
|
||||
// ListenAddrs Listen http and https
|
||||
func (config *HTTP) Listen(ctx context.Context, plugin HTTPPlugin) error {
|
||||
func (config *HTTP) Listen(ctx context.Context) error {
|
||||
var g errgroup.Group
|
||||
if config.ListenAddrTLS != "" {
|
||||
if config.ListenAddrTLS != "" && (config == &Global.HTTP || config.ListenAddrTLS != Global.ListenAddrTLS) {
|
||||
g.Go(func() error {
|
||||
return http.ListenAndServeTLS(config.ListenAddrTLS, config.CertFile, config.KeyFile, plugin)
|
||||
log.Info("🌐 https listen at ", Blink(config.ListenAddrTLS))
|
||||
return http.ListenAndServeTLS(config.ListenAddrTLS, config.CertFile, config.KeyFile, config.mux)
|
||||
})
|
||||
}
|
||||
if config.ListenAddr != "" {
|
||||
g.Go(func() error { return http.ListenAndServe(config.ListenAddr, plugin) })
|
||||
if config.ListenAddr != "" && (config == &Global.HTTP || config.ListenAddr != Global.ListenAddr) {
|
||||
g.Go(func() error {
|
||||
log.Info("🌐 http listen at ", Blink(config.ListenAddr))
|
||||
return http.ListenAndServe(config.ListenAddr, config.mux)
|
||||
})
|
||||
}
|
||||
g.Go(func() error {
|
||||
<-ctx.Done()
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package config
|
||||
|
||||
import "net/http"
|
||||
|
||||
type PublishConfig interface {
|
||||
GetPublishConfig() *Publish
|
||||
}
|
||||
@@ -77,10 +79,12 @@ type Engine struct {
|
||||
EnableRTP bool //启用RTP格式,rtsp、gb18181等协议使用
|
||||
EnableFLV bool //开启FLV格式,hdl协议使用
|
||||
}
|
||||
func (cfg *Engine) OnEvent(event any) {
|
||||
|
||||
}
|
||||
var Global = &Engine{
|
||||
Publish{true, true, false, 10, 0},
|
||||
Subscribe{true, true, false, 10},
|
||||
HTTP{ListenAddr: ":8080", CORS: true},
|
||||
HTTP{ListenAddr: ":8080", CORS: true, mux: http.DefaultServeMux},
|
||||
false, true, true, true,
|
||||
}
|
||||
|
12
go.mod
12
go.mod
@@ -8,6 +8,7 @@ require (
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/pion/rtp v1.7.4
|
||||
github.com/q191201771/naza v0.19.1
|
||||
github.com/shirou/gopsutil/v3 v3.22.1
|
||||
go.uber.org/zap v1.21.0
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
@@ -21,4 +22,13 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
require github.com/pion/randutil v0.1.0 // indirect
|
||||
require (
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
|
||||
)
|
||||
|
31
go.sum
31
go.sum
@@ -9,12 +9,18 @@ github.com/cnotch/queue v0.0.0-20200326024423-6e88bdbf2ad4/go.mod h1:zOssjAlNusO
|
||||
github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6/go.mod h1:zOssjAlNusOxvtaqT+EMA+Iyi8rrtKr4/XfzN1Fgoeg=
|
||||
github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5/go.mod h1:F4GE3SZkJZ8an1Y0ZCqvSM3jeozNuKzoC67erG1PhIo=
|
||||
github.com/cnotch/xlog v0.0.0-20201208005456-cfda439cd3a0/go.mod h1:RW9oHsR79ffl3sR3yMGgxYupMn2btzdtJUwoxFPUE5E=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emitter-io/address v1.0.0/go.mod h1:GfZb5+S/o8694B1GMGK2imUYQyn2skszMvGNA5D84Ug=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
@@ -24,11 +30,15 @@ github.com/kelindar/rate v1.0.0/go.mod h1:AjT4G+hTItNwt30lucEGZIz8y7Uk5zPho6vurI
|
||||
github.com/kelindar/tcp v1.0.0/go.mod h1:JB5hj1cshLU60XrLij2BBxW3JQ4hOye8vqbyvuKb52k=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@@ -42,9 +52,14 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/q191201771/naza v0.19.1 h1:4KLcxT2CHztO+7miPRtBG3FFgadSQYQw1gPPPKN7rnY=
|
||||
github.com/q191201771/naza v0.19.1/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM6rExjqt0=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/shirou/gopsutil/v3 v3.22.1 h1:33y31Q8J32+KstqPfscvFwBlNJ6xLaBy4xqBXzlYV5w=
|
||||
github.com/shirou/gopsutil/v3 v3.22.1/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
@@ -52,7 +67,13 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
@@ -78,10 +99,15 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -92,10 +118,14 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
@@ -103,6 +133,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
22
http.go
22
http.go
@@ -3,28 +3,22 @@ package engine
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
. "github.com/logrusorgru/aurora"
|
||||
"go.uber.org/zap"
|
||||
"m7s.live/engine/v4/config"
|
||||
"m7s.live/engine/v4/log"
|
||||
"m7s.live/engine/v4/util"
|
||||
)
|
||||
|
||||
type GlobalConfig struct {
|
||||
*http.ServeMux
|
||||
*config.Engine
|
||||
}
|
||||
|
||||
func (cfg *GlobalConfig) OnEvent(event any) {
|
||||
switch event.(type) {
|
||||
case FirstConfig:
|
||||
log.Info(Green("api server start at"), BrightBlue(cfg.ListenAddr), BrightBlue(cfg.ListenAddrTLS))
|
||||
cfg.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("visit", zap.String("path", "/"), zap.String("remote", r.RemoteAddr))
|
||||
w.Write([]byte("Monibuca API Server"))
|
||||
})
|
||||
go cfg.Listen(Engine, cfg)
|
||||
}
|
||||
func (config *GlobalConfig) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Write([]byte("Monibuca API Server"))
|
||||
}
|
||||
|
||||
func (config *GlobalConfig) API_summary(rw http.ResponseWriter, r *http.Request) {
|
||||
util.ReturnJson(summary.collect, time.Second, rw, r)
|
||||
}
|
||||
|
||||
func (config *GlobalConfig) API_sysInfo(rw http.ResponseWriter, r *http.Request) {
|
||||
|
8
main.go
8
main.go
@@ -8,7 +8,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
@@ -30,13 +29,10 @@ var (
|
||||
Plugins = make(map[string]*Plugin) // Plugins 所有的插件配置
|
||||
EngineConfig = &GlobalConfig{
|
||||
Engine: config.Global,
|
||||
ServeMux: http.DefaultServeMux,
|
||||
}
|
||||
settingDir string //配置缓存目录,该目录按照插件名称作为文件名存储修改过的配置
|
||||
Engine = InstallPlugin(EngineConfig) //复用安装插件逻辑,将全局配置信息注入,并启动server
|
||||
toolManForGetHandlerFuncType http.HandlerFunc //专门用来获取HandlerFunc类型的工具人
|
||||
handlerFuncType = reflect.TypeOf(toolManForGetHandlerFuncType) //供反射使用的Handler类型的类型
|
||||
MergeConfigs = []string{"Publish", "Subscribe"} //需要合并配置的属性项,插件若没有配置则使用全局配置
|
||||
MergeConfigs = []string{"Publish", "Subscribe", "HTTP"} //需要合并配置的属性项,插件若没有配置则使用全局配置
|
||||
EventBus = make(chan any, 10)
|
||||
)
|
||||
|
||||
@@ -73,7 +69,7 @@ func Run(ctx context.Context, configFile string) (err error) {
|
||||
Engine.registerHandler()
|
||||
// 使得RawConfig具备全量配置信息,用于合并到插件配置中
|
||||
Engine.RawConfig = config.Struct2Config(EngineConfig.Engine)
|
||||
go EngineConfig.OnEvent(FirstConfig(Engine.RawConfig))
|
||||
go EngineConfig.Listen(Engine)
|
||||
for name, plugin := range Plugins {
|
||||
plugin.RawConfig = cg.GetChild(name)
|
||||
plugin.assign()
|
||||
|
51
plugin.go
51
plugin.go
@@ -55,30 +55,28 @@ type Plugin struct {
|
||||
*zap.Logger
|
||||
}
|
||||
|
||||
func (opt *Plugin) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
func (opt *Plugin) logHandler(pattern string, handler func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
return func(rw http.ResponseWriter, r *http.Request) {
|
||||
opt.Debug("visit", zap.String("path", pattern), zap.String("remote", r.RemoteAddr))
|
||||
handler(rw, r)
|
||||
}
|
||||
}
|
||||
func (opt *Plugin) handleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
if opt == nil {
|
||||
return
|
||||
}
|
||||
var cors bool
|
||||
if v, ok := opt.RawConfig["cors"]; ok {
|
||||
cors = v.(bool)
|
||||
} else if EngineConfig.CORS {
|
||||
cors = true
|
||||
}
|
||||
conf, ok := opt.Config.(config.HTTPConfig)
|
||||
if !strings.HasPrefix(pattern, "/") {
|
||||
pattern = "/" + pattern
|
||||
}
|
||||
opt.Info("http handle added:" + pattern)
|
||||
if ok {
|
||||
conf.HandleFunc(pattern, opt.logHandler(pattern, handler))
|
||||
}
|
||||
if opt != Engine {
|
||||
pattern = "/" + strings.ToLower(opt.Name) + pattern
|
||||
EngineConfig.HandleFunc(pattern, opt.logHandler(pattern, handler))
|
||||
}
|
||||
opt.Info("http handle added:" + pattern)
|
||||
EngineConfig.HandleFunc(pattern, func(rw http.ResponseWriter, r *http.Request) {
|
||||
if cors {
|
||||
util.CORS(rw, r)
|
||||
}
|
||||
opt.Debug("visit", zap.String("path", pattern), zap.String("remote", r.RemoteAddr))
|
||||
handler(rw, r)
|
||||
})
|
||||
}
|
||||
|
||||
// 读取独立配置合并入总配置中
|
||||
@@ -111,6 +109,10 @@ func (opt *Plugin) assign() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if conf, ok := opt.Config.(config.HTTPConfig); ok {
|
||||
httpConf := conf.GetHTTPConfig()
|
||||
httpConf.InitMux()
|
||||
}
|
||||
opt.registerHandler()
|
||||
opt.run()
|
||||
}
|
||||
@@ -120,6 +122,12 @@ func (opt *Plugin) run() {
|
||||
opt.RawConfig.Unmarshal(opt.Config)
|
||||
opt.Debug("config", zap.Any("config", opt.Config))
|
||||
opt.Config.OnEvent(FirstConfig(opt.RawConfig))
|
||||
if conf, ok := opt.Config.(config.HTTPConfig); ok {
|
||||
httpconf := conf.GetHTTPConfig()
|
||||
if httpconf.ListenAddr != "" && httpconf.ListenAddr != EngineConfig.ListenAddr {
|
||||
go conf.Listen(opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update 热更新配置
|
||||
@@ -133,16 +141,13 @@ func (opt *Plugin) registerHandler() {
|
||||
v := reflect.ValueOf(opt.Config)
|
||||
// 注册http响应
|
||||
for i, j := 0, t.NumMethod(); i < j; i++ {
|
||||
mt := t.Method(i)
|
||||
mv := v.Method(i)
|
||||
if mv.CanConvert(handlerFuncType) {
|
||||
name := t.Method(i).Name
|
||||
if handler, ok := v.Method(i).Interface().(func(http.ResponseWriter, *http.Request)); ok {
|
||||
patten := "/"
|
||||
if mt.Name != "ServeHTTP" {
|
||||
patten = strings.ToLower(strings.ReplaceAll(mt.Name, "_", "/"))
|
||||
} else if opt == Engine {
|
||||
continue
|
||||
if name != "ServeHTTP" {
|
||||
patten = strings.ToLower(strings.ReplaceAll(name, "_", "/"))
|
||||
}
|
||||
opt.HandleFunc(patten, mv.Interface().(func(http.ResponseWriter, *http.Request)))
|
||||
opt.handleFunc(patten, handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,8 @@ type Puller struct {
|
||||
}
|
||||
|
||||
// 是否需要重连
|
||||
func (pub *Puller) Reconnect() bool {
|
||||
return pub.Config.RePull == -1 || pub.ReConnectCount <= pub.Config.RePull
|
||||
func (pub *Puller) Reconnect() (ok bool) {
|
||||
ok = pub.Config.RePull == -1 || pub.ReConnectCount <= pub.Config.RePull
|
||||
pub.ReConnectCount++
|
||||
return
|
||||
}
|
||||
|
123
summary.go
Normal file
123
summary.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"m7s.live/engine/v4/log"
|
||||
"m7s.live/engine/v4/util"
|
||||
)
|
||||
|
||||
var summary Summary
|
||||
var children util.Map[string, *Summary]
|
||||
|
||||
func init() {
|
||||
children.Init()
|
||||
go summary.Start()
|
||||
}
|
||||
|
||||
// ServerSummary 系统摘要定义
|
||||
type Summary struct {
|
||||
Address string
|
||||
Memory struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
Used uint64
|
||||
Usage float64
|
||||
}
|
||||
CPUUsage float64
|
||||
HardDisk struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
Used uint64
|
||||
Usage float64
|
||||
}
|
||||
NetWork []NetWorkInfo
|
||||
Streams []*Stream
|
||||
lastNetWork []net.IOCountersStat
|
||||
ref int32
|
||||
}
|
||||
|
||||
// NetWorkInfo 网速信息
|
||||
type NetWorkInfo struct {
|
||||
Name string
|
||||
Receive uint64
|
||||
Sent uint64
|
||||
ReceiveSpeed uint64
|
||||
SentSpeed uint64
|
||||
}
|
||||
|
||||
//StartSummary 开始定时采集数据,每秒一次
|
||||
func (s *Summary) Start() {
|
||||
for range time.Tick(time.Second) {
|
||||
if s.ref > 0 {
|
||||
summary.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *Summary) Point() *Summary {
|
||||
return s
|
||||
}
|
||||
// Running 是否正在采集数据
|
||||
func (s *Summary) Running() bool {
|
||||
return s.ref > 0
|
||||
}
|
||||
|
||||
// Add 增加订阅者
|
||||
func (s *Summary) Add() {
|
||||
if atomic.AddInt32(&s.ref, 1) == 1 {
|
||||
log.Info("start report summary")
|
||||
}
|
||||
}
|
||||
|
||||
// Done 删除订阅者
|
||||
func (s *Summary) Done() {
|
||||
if atomic.AddInt32(&s.ref, -1) == 0 {
|
||||
log.Info("stop report summary")
|
||||
s.lastNetWork = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Report 上报数据
|
||||
func (s *Summary) Report(slave *Summary) {
|
||||
children.Set(slave.Address, slave)
|
||||
}
|
||||
|
||||
func (s *Summary) collect() *Summary{
|
||||
v, _ := mem.VirtualMemory()
|
||||
d, _ := disk.Usage("/")
|
||||
nv, _ := net.IOCounters(true)
|
||||
|
||||
s.Memory.Total = v.Total >> 20
|
||||
s.Memory.Free = v.Available >> 20
|
||||
s.Memory.Used = v.Used >> 20
|
||||
s.Memory.Usage = v.UsedPercent
|
||||
|
||||
if cc, _ := cpu.Percent(time.Second, false); len(cc) > 0 {
|
||||
s.CPUUsage = cc[0]
|
||||
}
|
||||
s.HardDisk.Free = d.Free >> 30
|
||||
s.HardDisk.Total = d.Total >> 30
|
||||
s.HardDisk.Used = d.Used >> 30
|
||||
s.HardDisk.Usage = d.UsedPercent
|
||||
s.NetWork = []NetWorkInfo{}
|
||||
for i, n := range nv {
|
||||
info := NetWorkInfo{
|
||||
Name: n.Name,
|
||||
Receive: n.BytesRecv,
|
||||
Sent: n.BytesSent,
|
||||
}
|
||||
if s.lastNetWork != nil && len(s.lastNetWork) > i {
|
||||
info.ReceiveSpeed = n.BytesRecv - s.lastNetWork[i].BytesRecv
|
||||
info.SentSpeed = n.BytesSent - s.lastNetWork[i].BytesSent
|
||||
}
|
||||
s.NetWork = append(s.NetWork, info)
|
||||
}
|
||||
s.lastNetWork = nv
|
||||
s.Streams = Streams.ToList()
|
||||
return s
|
||||
}
|
@@ -2,6 +2,8 @@ package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -69,7 +71,8 @@ func ListenUDP(address string, networkBuffer int) (*net.UDPConn, error) {
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func CORS(w http.ResponseWriter, r *http.Request) {
|
||||
func CORS(next http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
origin := r.Header["Origin"]
|
||||
if len(origin) == 0 {
|
||||
@@ -77,4 +80,53 @@ func CORS(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin[0])
|
||||
}
|
||||
if next != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BasicAuth(u, p string, next http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Extract the username and password from the request
|
||||
// Authorization header. If no Authentication header is present
|
||||
// or the header value is invalid, then the 'ok' return value
|
||||
// will be false.
|
||||
username, password, ok := r.BasicAuth()
|
||||
if ok {
|
||||
// Calculate SHA-256 hashes for the provided and expected
|
||||
// usernames and passwords.
|
||||
usernameHash := sha256.Sum256([]byte(username))
|
||||
passwordHash := sha256.Sum256([]byte(password))
|
||||
expectedUsernameHash := sha256.Sum256([]byte(u))
|
||||
expectedPasswordHash := sha256.Sum256([]byte(p))
|
||||
|
||||
// 使用 subtle.ConstantTimeCompare() 进行校验
|
||||
// the provided username and password hashes equal the
|
||||
// expected username and password hashes. ConstantTimeCompare
|
||||
// 如果值相等,则返回1,否则返回0。
|
||||
// Importantly, we should to do the work to evaluate both the
|
||||
// username and password before checking the return values to
|
||||
// 避免泄露信息。
|
||||
usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1)
|
||||
passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1)
|
||||
|
||||
// If the username and password are correct, then call
|
||||
// the next handler in the chain. Make sure to return
|
||||
// afterwards, so that none of the code below is run.
|
||||
if usernameMatch && passwordMatch {
|
||||
if next != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If the Authentication header is not present, is invalid, or the
|
||||
// username or password is wrong, then set a WWW-Authenticate
|
||||
// header to inform the client that we expect them to use basic
|
||||
// authentication and send a 401 Unauthorized response.
|
||||
w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user