Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions livekit/livekit_analytics.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions protobufs/livekit_analytics.proto
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,5 @@ message WebhookInfo {
int32 service_error_code = 20;
string service_error = 21;
string send_error = 22;
int32 http_status_code = 23; // HTTP response status code for the delivery attempt (0 if no response).
}
2 changes: 1 addition & 1 deletion rpc/agent.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/agent_dispatch.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/egress.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/ingress.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/io.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/keepalive.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/participant.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/room.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/roommanager.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/signal.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/sip.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/whip_signal.psrpc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion webhook/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@ var (
ErrInvalidChecksum = errors.New("could not verify authenticity of message")
)

const authHeader = "Authorization"
const (
authHeader = "Authorization"
contentTypeHeader = "content-type"
userAgentHeader = "User-Agent"
)

const (
// use a custom mime type to ensure signature is checked prior to parsing
ContentType = "application/webhook+json"
DefaultUserAgent = "LiveKit"
)

const (
EventRoomStarted = "room_started"
Expand Down
6 changes: 6 additions & 0 deletions webhook/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ func (f *filter) SetFilter(params FilterParams) {
f.params = params
}

// IsAllowed reports whether event passes the include/exclude filter. IncludeEvents
// takes precedence over ExcludeEvents; if neither is set, the event is allowed.
func (p FilterParams) IsAllowed(event string) bool {
return newFilter(p).IsAllowed(event)
}

// IncludeEvents and ExcludeEvents are mutually exclusive; only one will be checked
// if neither are set, the event will be allowed
func (f *filter) IsAllowed(event string) bool {
Expand Down
3 changes: 3 additions & 0 deletions webhook/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ type HTTPClientParams struct {
MaxRetries int
ClientTimeout time.Duration
ForceIPv4 bool
// receivers pin WAF rules to this, so it must stay stable across releases
// defaults to DefaultUserAgent
UserAgent string
}

type FilterParams struct {
Expand Down
7 changes: 5 additions & 2 deletions webhook/resource_url_notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ func NewResourceURLNotifier(params ResourceURLNotifierParams) *ResourceURLNotifi
if params.Config.MaxDepth == 0 {
params.Config.MaxDepth = DefaultResourceURLNotifierConfig.MaxDepth
}
if params.UserAgent == "" {
params.UserAgent = DefaultUserAgent
}

rhc := retryablehttp.NewClient()
if params.RetryWaitMin > 0 {
Expand Down Expand Up @@ -374,8 +377,8 @@ func (r *ResourceURLNotifier) send(event *livekit.WebhookEvent, params *Resource
return err
}
req.Header.Set(authHeader, token)
// use a custom mime type to ensure signature is checked prior to parsing
req.Header.Set("content-type", "application/webhook+json")
req.Header.Set(contentTypeHeader, ContentType)
req.Header.Set(userAgentHeader, params.UserAgent)
res, err := r.client.Do(req)
if err != nil {
return err
Expand Down
7 changes: 5 additions & 2 deletions webhook/url_notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ func NewURLNotifier(params URLNotifierParams) *URLNotifier {
if params.Logger == nil {
params.Logger = logger.GetLogger()
}
if params.UserAgent == "" {
params.UserAgent = DefaultUserAgent
}

rhc := retryablehttp.NewClient()
if params.RetryWaitMin > 0 {
Expand Down Expand Up @@ -282,8 +285,8 @@ func (n *URLNotifier) send(event *livekit.WebhookEvent, params *URLNotifierParam
return err
}
r.Header.Set(authHeader, token)
// use a custom mime type to ensure signature is checked prior to parsing
r.Header.Set("content-type", "application/webhook+json")
r.Header.Set(contentTypeHeader, ContentType)
r.Header.Set(userAgentHeader, params.UserAgent)
res, err := n.client.Do(r)
if err != nil {
return err
Expand Down
60 changes: 60 additions & 0 deletions webhook/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func TestWebHook(t *testing.T) {

require.EqualValues(t, event, decodedEvent)
require.Equal(t, expectedUrl, r.URL.String())
require.Equal(t, DefaultUserAgent, r.UserAgent())
}
require.NoError(t, notifier.QueueNotify(context.Background(), event))
wg.Wait()
Expand All @@ -84,6 +85,35 @@ func TestWebHook(t *testing.T) {
wg.Wait()

})

t.Run("overridden user agent", func(t *testing.T) {
notifier := NewURLNotifier(URLNotifierParams{
URL: testUrl,
APIKey: testAPIKey,
APISecret: testAPISecret,
Config: URLNotifierConfig{
QueueSize: 20,
},
HTTPClientParams: HTTPClientParams{
UserAgent: "LiveKitCloud",
},
})
defer notifier.Stop(false)

ua := atomic.String{}
s.handler = func(w http.ResponseWriter, r *http.Request) {
ua.Store(r.UserAgent())
}
require.NoError(t, notifier.QueueNotify(context.Background(), &livekit.WebhookEvent{Event: EventRoomStarted}))
require.Eventually(
t,
func() bool {
return ua.Load() == "LiveKitCloud"
},
5*time.Second,
webhookCheckInterval,
)
})
}

func TestURLNotifierDropped(t *testing.T) {
Expand Down Expand Up @@ -395,11 +425,41 @@ func TestResourceWebHook(t *testing.T) {
require.NoError(t, err)

require.EqualValues(t, event, decodedEvent)
require.Equal(t, DefaultUserAgent, r.UserAgent())
}
require.NoError(t, resourceURLNotifier.QueueNotify(context.Background(), event))
wg.Wait()
})

t.Run("overridden user agent", func(t *testing.T) {
resourceURLNotifier := NewResourceURLNotifier(ResourceURLNotifierParams{
URL: testUrl,
APIKey: testAPIKey,
APISecret: testAPISecret,
Config: ResourceURLNotifierConfig{
MaxAge: 200 * time.Millisecond,
MaxDepth: 50,
},
HTTPClientParams: HTTPClientParams{
UserAgent: "LiveKitCloud",
},
})
defer resourceURLNotifier.Stop(false)

ua := atomic.String{}
s.handler = func(w http.ResponseWriter, r *http.Request) {
ua.Store(r.UserAgent())
}
require.NoError(t, resourceURLNotifier.QueueNotify(context.Background(), &livekit.WebhookEvent{Event: EventRoomStarted}))
require.Eventually(
t,
func() bool {
return ua.Load() == "LiveKitCloud"
},
5*time.Second,
webhookCheckInterval,
)
})
}

func TestResourceURLNotifierDropped(t *testing.T) {
Expand Down
Loading