diff --git a/.changeset/great-birds-work.md b/.changeset/great-birds-work.md new file mode 100644 index 000000000..b72d78585 --- /dev/null +++ b/.changeset/great-birds-work.md @@ -0,0 +1,5 @@ +--- +"@livekit/protocol": patch +--- + +add local protojson with permissive defaults diff --git a/.golangci.yml b/.golangci.yml index 8fc7a14e7..118a9463b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,8 +2,18 @@ version: "2" linters: default: none enable: + - depguard - staticcheck settings: + depguard: + rules: + protojson: + files: + - "$all" + - "!**/utils/protojson/**" + deny: + - pkg: google.golang.org/protobuf/encoding/protojson + desc: use github.com/livekit/protocol/utils/protojson instead — it sets DiscardUnknown by default to avoid schema-drift footguns staticcheck: checks: - "all" @@ -14,3 +24,5 @@ linters: - "-ST1022" - "-SA1019" - "-QF1008" + exclusions: + generated: strict diff --git a/auth/grants.go b/auth/grants.go index 8fc0bf00a..69719f7b9 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -22,25 +22,15 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "golang.org/x/exp/slices" - "google.golang.org/protobuf/encoding/protojson" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" "github.com/livekit/protocol/utils" + "github.com/livekit/protocol/utils/protojson" ) type RoomConfiguration livekit.RoomConfiguration -var tokenMarshaler = protojson.MarshalOptions{ - EmitDefaultValues: false, -} - -// tokenUnmarshaler discards unknown fields so that older servers can accept -// tokens issued by newer clients that include fields the server does not yet know about. -var tokenUnmarshaler = protojson.UnmarshalOptions{ - DiscardUnknown: true, -} - var ErrSensitiveCredentials = errors.New("room configuration should not contain sensitive credentials") func (c *RoomConfiguration) Clone() *RoomConfiguration { @@ -51,11 +41,11 @@ func (c *RoomConfiguration) Clone() *RoomConfiguration { } func (c *RoomConfiguration) MarshalJSON() ([]byte, error) { - return tokenMarshaler.Marshal((*livekit.RoomConfiguration)(c)) + return protojson.Marshal((*livekit.RoomConfiguration)(c)) } func (c *RoomConfiguration) UnmarshalJSON(data []byte) error { - return tokenUnmarshaler.Unmarshal(data, (*livekit.RoomConfiguration)(c)) + return protojson.Unmarshal(data, (*livekit.RoomConfiguration)(c)) } // CheckCredentials checks if the room configuration contains sensitive credentials diff --git a/observability/egressobs/egress.go b/observability/egressobs/egress.go index a95abef49..3a1b5872f 100644 --- a/observability/egressobs/egress.go +++ b/observability/egressobs/egress.go @@ -3,7 +3,7 @@ package egressobs import ( "encoding/json" - "google.golang.org/protobuf/encoding/protojson" + "github.com/livekit/protocol/utils/protojson" "github.com/pkg/errors" diff --git a/utils/interceptors/curl.go b/utils/interceptors/curl.go index d64adf2cb..4169dcf27 100644 --- a/utils/interceptors/curl.go +++ b/utils/interceptors/curl.go @@ -8,8 +8,9 @@ import ( "sort" "github.com/twitchtv/twirp" - "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + + "github.com/livekit/protocol/utils/protojson" ) // NewCurlPrinter creates a Twirp interceptor that prints a curl commands for each request made. diff --git a/utils/protojson/protojson.go b/utils/protojson/protojson.go new file mode 100644 index 000000000..a4496bb2c --- /dev/null +++ b/utils/protojson/protojson.go @@ -0,0 +1,45 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package protojson + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +type MarshalOptions = protojson.MarshalOptions +type UnmarshalOptions = protojson.UnmarshalOptions + +// Format formats the message as a multiline string. +// This function is only intended for human consumption and ignores errors. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. +func Format(m proto.Message) string { + return MarshalOptions{ + Multiline: true, + AllowPartial: true, + }.Format(m) +} + +// Marshal writes the given [proto.Message] in JSON format using permissive +// options that avoid errors due to schema drift. Do not depend on the output +// being stable. Its output will change across different builds of your program, +// even when using the same version of the protobuf module. +func Marshal(m proto.Message) ([]byte, error) { + return MarshalOptions{ + AllowPartial: true, + }.Marshal(m) +} + +// Unmarshal reads the given []byte into the given [proto.Message] using +// permissive options that avoid errors due to schema drift. The provided +// message must be mutable (e.g., a non-nil pointer to a message). +func Unmarshal(b []byte, m proto.Message) error { + return UnmarshalOptions{ + AllowPartial: true, + DiscardUnknown: true, + }.Unmarshal(b, m) +} diff --git a/webhook/resource_url_notifier.go b/webhook/resource_url_notifier.go index 8b88b38fc..895f9ed76 100644 --- a/webhook/resource_url_notifier.go +++ b/webhook/resource_url_notifier.go @@ -28,12 +28,12 @@ import ( "github.com/frostbyte73/core" "github.com/hashicorp/go-retryablehttp" - "google.golang.org/protobuf/encoding/protojson" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" "github.com/livekit/protocol/utils" + "github.com/livekit/protocol/utils/protojson" ) const ( diff --git a/webhook/url_notifier.go b/webhook/url_notifier.go index 9317878e1..ee96c376f 100644 --- a/webhook/url_notifier.go +++ b/webhook/url_notifier.go @@ -28,11 +28,11 @@ import ( "github.com/frostbyte73/core" "github.com/hashicorp/go-retryablehttp" "go.uber.org/atomic" - "google.golang.org/protobuf/encoding/protojson" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" + "github.com/livekit/protocol/utils/protojson" ) type URLNotifierConfig struct { diff --git a/webhook/verifier.go b/webhook/verifier.go index 69eda2111..45c24297f 100644 --- a/webhook/verifier.go +++ b/webhook/verifier.go @@ -21,10 +21,9 @@ import ( "io" "net/http" - "google.golang.org/protobuf/encoding/protojson" - "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" + "github.com/livekit/protocol/utils/protojson" ) // Receive reads and verifies incoming webhook is signed with key/secret pair