0.2.63 update
This commit is contained in:
@@ -2,6 +2,8 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -19,11 +21,12 @@ import (
|
||||
// still read what an inner layer filled in. A request is served on one goroutine and the
|
||||
// handler has returned by the time the middleware reads this, so no lock is needed.
|
||||
type requestIdentity struct {
|
||||
component string
|
||||
user string
|
||||
device string
|
||||
client string
|
||||
protocol string
|
||||
component string
|
||||
user string
|
||||
device string
|
||||
client string
|
||||
protocol string
|
||||
correlation string
|
||||
}
|
||||
|
||||
type identityKey struct{}
|
||||
@@ -31,9 +34,10 @@ type identityKey struct{}
|
||||
// withRequestIdentity installs an empty identity for this request and returns it.
|
||||
func withRequestIdentity(r *http.Request) (*http.Request, *requestIdentity) {
|
||||
identity := &requestIdentity{
|
||||
component: componentFor(r.URL.Path),
|
||||
client: clientVersion(r),
|
||||
protocol: clientProtocol(r),
|
||||
component: componentFor(r.URL.Path),
|
||||
client: clientVersion(r),
|
||||
protocol: clientProtocol(r),
|
||||
correlation: requestCorrelation(r),
|
||||
}
|
||||
return r.WithContext(context.WithValue(r.Context(), identityKey{}, identity)), identity
|
||||
}
|
||||
@@ -79,9 +83,35 @@ func (i *requestIdentity) attrs() []any {
|
||||
if i.client != "" {
|
||||
attrs = append(attrs, "client", i.client)
|
||||
}
|
||||
if i.correlation != "" {
|
||||
attrs = append(attrs, "correlation", i.correlation)
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
// requestCorrelation accepts a client-supplied safe identifier or creates one at the
|
||||
// gateway boundary. The same value is attached to every log line within the exchange and
|
||||
// returned to the client, making a playback launch traceable through gateway and Emby work.
|
||||
func requestCorrelation(r *http.Request) string {
|
||||
if value := strings.TrimSpace(r.Header.Get("X-Memby-Correlation")); len(value) >= 6 && len(value) <= 64 {
|
||||
for _, rune := range value {
|
||||
if !(rune >= 'a' && rune <= 'z' || rune >= 'A' && rune <= 'Z' || rune >= '0' && rune <= '9' || rune == '-' || rune == '_') {
|
||||
return newCorrelation()
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
return newCorrelation()
|
||||
}
|
||||
|
||||
func newCorrelation() string {
|
||||
var raw [4]byte
|
||||
if _, err := rand.Read(raw[:]); err != nil {
|
||||
return "request-unknown"
|
||||
}
|
||||
return "req-" + strings.ToUpper(hex.EncodeToString(raw[:]))
|
||||
}
|
||||
|
||||
// viewerAttrs names the person and the television, and only when they are known: an
|
||||
// unauthenticated probe has neither, and "user=unknown" on every health check is noise.
|
||||
func (i *requestIdentity) viewerAttrs() []any {
|
||||
|
||||
Reference in New Issue
Block a user