Merge HTTP and HLS middleware into session middleware

This commit is contained in:
Ingo Oppermann 2023-06-28 10:41:29 +02:00
parent 6c6fa33903
commit fff7f986a0
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
4 changed files with 316 additions and 784 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,155 +1,54 @@
package session
import (
"net"
"net/http"
"net/url"
"github.com/datarhei/core/v16/glob"
"github.com/datarhei/core/v16/http/api"
"github.com/datarhei/core/v16/http/handler/util"
"github.com/datarhei/core/v16/session"
"github.com/lithammer/shortuuid/v4"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/lithammer/shortuuid/v4"
)
type HTTPConfig struct {
// Skipper defines a function to skip middleware.
Skipper middleware.Skipper
Collector session.Collector
}
func (h *handler) handleHTTP(c echo.Context, ctxuser string, data map[string]interface{}, next echo.HandlerFunc) error {
req := c.Request()
res := c.Response()
var DefaultHTTPConfig = HTTPConfig{
Skipper: middleware.DefaultSkipper,
Collector: session.NewNullCollector(),
}
// NewHTTP returns a new HTTP session middleware with default config
func NewHTTP() echo.MiddlewareFunc {
return NewHTTPWithConfig(DefaultHTTPConfig)
}
// NewHTTPWithConfig returns a new HTTP session middleware
func NewHTTPWithConfig(config HTTPConfig) echo.MiddlewareFunc {
if config.Skipper == nil {
config.Skipper = DefaultHTTPConfig.Skipper
if !h.httpCollector.IsCollectableIP(c.RealIP()) {
return next(c)
}
if config.Collector == nil {
config.Collector = DefaultHTTPConfig.Collector
path := req.URL.Path
location := path + req.URL.RawQuery
remote := req.RemoteAddr
id := shortuuid.New()
reader := req.Body
r := &fakeReader{
reader: req.Body,
}
req.Body = r
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if config.Skipper(c) {
return next(c)
}
if !config.Collector.IsCollectableIP(c.RealIP()) {
return next(c)
}
ctxuser := util.DefaultContext(c, "user", "")
req := c.Request()
res := c.Response()
host, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
host = ""
}
path := req.URL.Path
location := path + req.URL.RawQuery
remote := req.RemoteAddr
id := shortuuid.New()
data := map[string]interface{}{}
e := util.DefaultContext[interface{}](c, "session", nil)
if e != nil {
var ok bool
data, ok = e.(map[string]interface{})
if !ok {
return api.Err(http.StatusForbidden, "", "invalid session data, cast")
}
if match, ok := data["match"].(string); ok {
if ok, err := glob.Match(match, path, '/'); !ok {
if err != nil {
return api.Err(http.StatusForbidden, "", "no match for '%s' in %s: %s", match, path, err.Error())
}
return api.Err(http.StatusForbidden, "", "no match for '%s' in %s", match, path)
}
}
referrer := req.Header.Get("Referer")
if u, err := url.Parse(referrer); err == nil {
referrer = u.Host
}
if remote, ok := data["remote"].([]string); ok && len(remote) != 0 {
match := false
for _, r := range remote {
if ok, _ := glob.Match(r, referrer, '.'); ok {
match = true
break
}
}
if !match {
return api.Err(http.StatusForbidden, "", "remote not allowed")
}
}
}
data["name"] = ctxuser
data["method"] = req.Method
data["code"] = 0
reader := req.Body
r := &fakeReader{
reader: req.Body,
}
req.Body = r
writer := res.Writer
w := &fakeWriter{
ResponseWriter: res.Writer,
}
res.Writer = w
if config.Collector.IsCollectableIP(host) {
config.Collector.RegisterAndActivate(id, "", location, remote)
config.Collector.Extra(id, data)
}
defer config.Collector.Close(id)
defer func() {
req.Body = reader
if config.Collector.IsCollectableIP(host) {
config.Collector.Ingress(id, r.size+headerSize(req.Header))
}
}()
defer func() {
res.Writer = writer
if config.Collector.IsCollectableIP(host) {
config.Collector.Egress(id, w.size+headerSize(res.Header()))
data["code"] = res.Status
config.Collector.Extra(id, data)
}
}()
return next(c)
}
writer := res.Writer
w := &fakeWriter{
ResponseWriter: res.Writer,
}
res.Writer = w
h.httpCollector.RegisterAndActivate(id, "", location, remote)
h.httpCollector.Extra(id, data)
defer h.httpCollector.Close(id)
defer func() {
req.Body = reader
h.httpCollector.Ingress(id, r.size+headerSize(req.Header))
}()
defer func() {
res.Writer = writer
h.httpCollector.Egress(id, w.size+headerSize(res.Header()))
data["code"] = res.Status
h.httpCollector.Extra(id, data)
}()
return next(c)
}

File diff suppressed because it is too large Load Diff

View File

@ -302,6 +302,18 @@ func NewServer(config Config) (Server, error) {
if config.Sessions == nil {
config.Sessions, _ = session.New(session.Config{})
if config.Sessions.Collector("hlsingress") == nil {
return nil, fmt.Errorf("hlsingress session collector must be available")
}
if config.Sessions.Collector("hls") == nil {
return nil, fmt.Errorf("hls session collector must be available")
}
if config.Sessions.Collector("http") == nil {
return nil, fmt.Errorf("http session collector must be available")
}
}
s.v3handler.session = api.NewSession(
@ -379,7 +391,7 @@ func NewServer(config Config) (Server, error) {
s.router.Use(s.middleware.iam)
s.router.Use(mwsession.NewWithConfig(mwsession.Config{
HLSIngressCollector: config.Sessions.Collector("hlsingest"),
HLSIngressCollector: config.Sessions.Collector("hlsingress"),
HLSEgressCollector: config.Sessions.Collector("hls"),
HTTPCollector: config.Sessions.Collector("http"),
Skipper: func(c echo.Context) bool {