mirror of
				https://github.com/datarhei/core.git
				synced 2025-11-01 03:42:51 +08:00 
			
		
		
		
	Add logging HTTP requests as single session
This commit is contained in:
		| @@ -94,6 +94,8 @@ func NewHLSWithConfig(config HLSConfig) echo.MiddlewareFunc { | |||||||
| func (h *hls) handleIngress(c echo.Context, next echo.HandlerFunc) error { | func (h *hls) handleIngress(c echo.Context, next echo.HandlerFunc) error { | ||||||
| 	req := c.Request() | 	req := c.Request() | ||||||
|  |  | ||||||
|  | 	ctxuser := util.DefaultContext(c, "user", "") | ||||||
|  |  | ||||||
| 	path := req.URL.Path | 	path := req.URL.Path | ||||||
|  |  | ||||||
| 	if strings.HasSuffix(path, ".m3u8") { | 	if strings.HasSuffix(path, ".m3u8") { | ||||||
| @@ -113,10 +115,15 @@ func (h *hls) handleIngress(c echo.Context, next echo.HandlerFunc) error { | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !h.ingressCollector.IsKnownSession(path) { | 			if !h.ingressCollector.IsKnownSession(path) { | ||||||
|  | 				ip, _ := net.AnonymizeIPString(c.RealIP()) | ||||||
|  |  | ||||||
| 				// Register a new session | 				// Register a new session | ||||||
| 				reference := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) | 				reference := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) | ||||||
| 				h.ingressCollector.RegisterAndActivate(path, reference, path, "") | 				h.ingressCollector.RegisterAndActivate(path, reference, path, ip) | ||||||
|  |  | ||||||
| 				h.ingressCollector.Extra(path, map[string]interface{}{ | 				h.ingressCollector.Extra(path, map[string]interface{}{ | ||||||
|  | 					"name":       ctxuser, | ||||||
|  | 					"ip":         ip, | ||||||
| 					"user_agent": req.Header.Get("User-Agent"), | 					"user_agent": req.Header.Get("User-Agent"), | ||||||
| 				}) | 				}) | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -4,8 +4,13 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/http" | 	"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/datarhei/core/v16/session" | ||||||
|  | 	"github.com/lithammer/shortuuid/v4" | ||||||
|  |  | ||||||
| 	"github.com/labstack/echo/v4" | 	"github.com/labstack/echo/v4" | ||||||
| 	"github.com/labstack/echo/v4/middleware" | 	"github.com/labstack/echo/v4/middleware" | ||||||
| @@ -43,6 +48,8 @@ func NewHTTPWithConfig(config HTTPConfig) echo.MiddlewareFunc { | |||||||
| 				return next(c) | 				return next(c) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			ctxuser := util.DefaultContext(c, "user", "") | ||||||
|  |  | ||||||
| 			req := c.Request() | 			req := c.Request() | ||||||
| 			res := c.Response() | 			res := c.Response() | ||||||
|  |  | ||||||
| @@ -51,32 +58,91 @@ func NewHTTPWithConfig(config HTTPConfig) echo.MiddlewareFunc { | |||||||
| 				host = "" | 				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 referrer == r { | ||||||
|  | 							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 | 			reader := req.Body | ||||||
| 			r := &fakeReader{ | 			r := &fakeReader{ | ||||||
| 				reader: req.Body, | 				reader: req.Body, | ||||||
| 			} | 			} | ||||||
| 			req.Body = r | 			req.Body = r | ||||||
|  |  | ||||||
| 			defer func() { |  | ||||||
| 				req.Body = reader |  | ||||||
|  |  | ||||||
| 				if config.Collector.IsCollectableIP(host) { |  | ||||||
| 					config.Collector.RegisterAndActivate("HTTP", "", "any", "any") |  | ||||||
| 					config.Collector.Ingress("HTTP", r.size+headerSize(req.Header)) |  | ||||||
| 				} |  | ||||||
| 			}() |  | ||||||
|  |  | ||||||
| 			writer := res.Writer | 			writer := res.Writer | ||||||
| 			w := &fakeWriter{ | 			w := &fakeWriter{ | ||||||
| 				ResponseWriter: res.Writer, | 				ResponseWriter: res.Writer, | ||||||
| 			} | 			} | ||||||
| 			res.Writer = w | 			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() { | 			defer func() { | ||||||
| 				res.Writer = writer | 				res.Writer = writer | ||||||
|  |  | ||||||
| 				if config.Collector.IsCollectableIP(host) { | 				if config.Collector.IsCollectableIP(host) { | ||||||
| 					config.Collector.Egress("HTTP", w.size+headerSize(res.Header())) | 					config.Collector.Egress(id, w.size+headerSize(res.Header())) | ||||||
|  | 					data["code"] = res.Status | ||||||
|  | 					config.Collector.Extra(id, data) | ||||||
| 				} | 				} | ||||||
| 			}() | 			}() | ||||||
|  |  | ||||||
| @@ -104,6 +170,13 @@ func (r *fakeReader) Close() error { | |||||||
| type fakeWriter struct { | type fakeWriter struct { | ||||||
| 	http.ResponseWriter | 	http.ResponseWriter | ||||||
| 	size int64 | 	size int64 | ||||||
|  | 	code int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *fakeWriter) WriteHeader(statusCode int) { | ||||||
|  | 	w.ResponseWriter.WriteHeader(statusCode) | ||||||
|  |  | ||||||
|  | 	w.code = statusCode | ||||||
| } | } | ||||||
|  |  | ||||||
| func (w *fakeWriter) Write(body []byte) (int, error) { | func (w *fakeWriter) Write(body []byte) (int, error) { | ||||||
|   | |||||||
| @@ -371,9 +371,6 @@ func NewServer(config Config) (Server, error) { | |||||||
| 			return nil | 			return nil | ||||||
| 		}, | 		}, | ||||||
| 	})) | 	})) | ||||||
| 	s.router.Use(mwsession.NewHTTPWithConfig(mwsession.HTTPConfig{ |  | ||||||
| 		Collector: config.Sessions.Collector("http"), |  | ||||||
| 	})) |  | ||||||
|  |  | ||||||
| 	s.router.HideBanner = true | 	s.router.HideBanner = true | ||||||
| 	s.router.HidePort = true | 	s.router.HidePort = true | ||||||
| @@ -386,6 +383,10 @@ func NewServer(config Config) (Server, error) { | |||||||
|  |  | ||||||
| 	s.router.Use(s.middleware.iam) | 	s.router.Use(s.middleware.iam) | ||||||
|  |  | ||||||
|  | 	s.router.Use(mwsession.NewHTTPWithConfig(mwsession.HTTPConfig{ | ||||||
|  | 		Collector: config.Sessions.Collector("http"), | ||||||
|  | 	})) | ||||||
|  |  | ||||||
| 	// Add static routes | 	// Add static routes | ||||||
| 	if path, target := config.Router.StaticRoute(); len(target) != 0 { | 	if path, target := config.Router.StaticRoute(); len(target) != 0 { | ||||||
| 		group := s.router.Group(path) | 		group := s.router.Group(path) | ||||||
|   | |||||||
| @@ -314,7 +314,7 @@ func (r *registry) Register(id string, conf CollectorConfig) (Collector, error) | |||||||
| 		return nil, fmt.Errorf("a collector with the ID '%s' already exists", id) | 		return nil, fmt.Errorf("a collector with the ID '%s' already exists", id) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	m, err := newCollector(id, r.persist.sessionsCh, r.logger.WithComponent(id), conf) | 	m, err := newCollector(id, r.persist.sessionsCh, r.logger, conf) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ingo Oppermann
					Ingo Oppermann