Skip to content

Commit

Permalink
Add example for conditional option
Browse files Browse the repository at this point in the history
  • Loading branch information
emcfarlane committed Jul 12, 2023
1 parent b9ed035 commit 11df7c4
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 24 deletions.
2 changes: 1 addition & 1 deletion error_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type ErrorWriter struct {
// NewErrorWriter constructs an ErrorWriter. To properly recognize supported
// RPC Content-Types in net/http middleware, you must pass the same
// HandlerOptions to NewErrorWriter and any wrapped Connect handlers.
// Conditional options are ignored.
// Options supplied via [WithConditionalHandlerOptions] are ignored.
func NewErrorWriter(opts ...HandlerOption) *ErrorWriter {
config := newHandlerConfig("", StreamTypeUnary, opts)
writer := &ErrorWriter{
Expand Down
11 changes: 11 additions & 0 deletions interceptor_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,14 @@ func ExampleWithInterceptors() {
// inner interceptor: after call
// outer interceptor: after call
}

func ExampleWithConditionalHandlerOptions() {
connect.WithConditionalHandlerOptions(func(spec connect.Spec) []connect.HandlerOption {
var options []connect.HandlerOption
if spec.Procedure == pingv1connect.PingServicePingProcedure {
options = append(options, connect.WithReadMaxBytes(1024))
}
return options
})
// Output:
}
38 changes: 15 additions & 23 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,34 +166,12 @@ func WithRequireConnectProtocolHeader() HandlerOption {
return &requireConnectProtocolHeaderOption{}
}

// WithConditionalHandlerOptions is a function that returns a HandlerOption.
// WithConditionalHandlerOptions accepts a function that returns a HandlerOption.
// It's used to conditionally apply HandlerOption to a Handler based on the Spec.
// For example, to apply a HandlerOption only to a specific procedure:
//
// connect.WithConditionalHandlerOptions(func(spec connect.Spec) (options []connect.HandlerOption) {
// if spec.Procedure == pingv1connect.PingServicePingProcedure {
// options = append(options, connect.WithReadMaxBytes(1024))
// }
// return options
// })
func WithConditionalHandlerOptions(conditional func(spec Spec) []HandlerOption) HandlerOption {
return &conditionalHandlerOptions{conditional: conditional}
}

type conditionalHandlerOptions struct {
conditional func(spec Spec) []HandlerOption
}

func (o *conditionalHandlerOptions) applyToHandler(config *handlerConfig) {
spec := config.newSpec()
if spec.Procedure == "" {
return // ignore empty specs
}
for _, option := range o.conditional(spec) {
option.applyToHandler(config)
}
}

// Option implements both [ClientOption] and [HandlerOption], so it can be
// applied both client-side and server-side.
type Option interface {
Expand Down Expand Up @@ -585,3 +563,17 @@ func withProtoJSONCodecs() HandlerOption {
WithCodec(&protoJSONCodec{codecNameJSONCharsetUTF8}),
)
}

type conditionalHandlerOptions struct {
conditional func(spec Spec) []HandlerOption
}

func (o *conditionalHandlerOptions) applyToHandler(config *handlerConfig) {
spec := config.newSpec()
if spec.Procedure == "" {
return // ignore empty specs
}
for _, option := range o.conditional(spec) {
option.applyToHandler(config)
}
}

0 comments on commit 11df7c4

Please sign in to comment.