Skip to content
Draft
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
25 changes: 23 additions & 2 deletions service/pkg/server/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (

"connectrpc.com/connect"
"github.com/casbin/casbin/v2/persist"
"github.com/opentdf/platform/sdk"
"github.com/opentdf/platform/service/logger"
"github.com/opentdf/platform/service/pkg/authz"
"github.com/opentdf/platform/service/pkg/config"
"github.com/opentdf/platform/service/pkg/serviceregistry"
Expand All @@ -13,6 +15,13 @@ import (

type StartOptions func(StartConfig) StartConfig

type InterceptorParams struct {
SDK *sdk.SDK
Logger *logger.Logger
}

type InterceptorFactory func(InterceptorParams) (connect.Interceptor, error)

type StartConfig struct {
ConfigKey string
ConfigFile string
Expand All @@ -26,8 +35,9 @@ type StartConfig struct {
configLoaders []config.Loader
configLoaderOrder []string

extraConnectInterceptors []connect.Interceptor
extraIPCInterceptors []connect.Interceptor
extraConnectInterceptors []connect.Interceptor
extraIPCInterceptors []connect.Interceptor
externalInterceptorFactories []InterceptorFactory

trustKeyManagerCtxs []trust.NamedKeyManagerCtxFactory

Expand Down Expand Up @@ -178,6 +188,17 @@ func WithConnectInterceptors(interceptors ...connect.Interceptor) StartOptions {
}
}

// WithExternalInterceptorFactories appends factories for external
// Connect interceptors that need access to startup-created clients, such as the
// IPC SDK connection. Factories are evaluated after the SDK is created and
// before externally reachable service handlers are registered.
func WithExternalInterceptorFactories(factories ...InterceptorFactory) StartOptions {
return func(c StartConfig) StartConfig {
c.externalInterceptorFactories = append(c.externalInterceptorFactories, factories...)
return c
}
}

// WithIPCInterceptors appends additional Connect interceptors for in-process IPC server.
func WithIPCInterceptors(interceptors ...connect.Interceptor) StartOptions {
return func(c StartConfig) StartConfig {
Expand Down
57 changes: 57 additions & 0 deletions service/pkg/server/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,63 @@ func TestWithConnectInterceptors(t *testing.T) {
}
}

func TestWithExternalInterceptorFactories(t *testing.T) {
factory := func(InterceptorParams) (connect.Interceptor, error) {
return noopInterceptor(), nil
}

tests := []struct {
name string
apply func(*StartConfig)
wantCount int
}{
{
name: "single factory is appended",
apply: func(c *StartConfig) {
*c = WithExternalInterceptorFactories(factory)(*c)
},
wantCount: 1,
},
{
name: "multiple factories are appended in order",
apply: func(c *StartConfig) {
*c = WithExternalInterceptorFactories(factory, factory, factory)(*c)
},
wantCount: 3,
},
{
name: "calling twice accumulates factories",
apply: func(c *StartConfig) {
*c = WithExternalInterceptorFactories(factory)(*c)
*c = WithExternalInterceptorFactories(factory, factory)(*c)
},
wantCount: 3,
},
{
name: "empty call leaves slice nil",
apply: func(c *StartConfig) {
*c = WithExternalInterceptorFactories()(*c)
},
wantCount: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var cfg StartConfig
tt.apply(&cfg)

if tt.wantCount == 0 {
assert.Nil(t, cfg.externalInterceptorFactories)
} else {
require.Len(t, cfg.externalInterceptorFactories, tt.wantCount)
}
assert.Nil(t, cfg.extraConnectInterceptors)
assert.Nil(t, cfg.extraIPCInterceptors)
})
}
}

func TestWithIPCInterceptors(t *testing.T) {
tests := []struct {
name string
Expand Down
15 changes: 15 additions & 0 deletions service/pkg/server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,21 @@ func Start(f ...StartOptions) error {

defer client.Close()
Comment thread
jakedoublev marked this conversation as resolved.

if len(startConfig.externalInterceptorFactories) > 0 {
for _, factory := range startConfig.externalInterceptorFactories {
interceptor, err := factory(InterceptorParams{
SDK: client,
Logger: logger,
})
if err != nil {
return fmt.Errorf("failed to create external connect interceptor: %w", err)
}
if interceptor != nil {
otdf.ConnectRPC.Interceptors = append(otdf.ConnectRPC.Interceptors, connect.WithInterceptors(interceptor))
}
}
}

logger.Info("starting services")
gatewayCleanup, err := startServices(ctx, startServicesParams{
cfg: cfg,
Expand Down
Loading