Skip to content

Commit

Permalink
Simplify the endpoint client
Browse files Browse the repository at this point in the history
  • Loading branch information
chriso committed Jun 4, 2024
1 parent 678901d commit 97c0725
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 43 deletions.
7 changes: 5 additions & 2 deletions dispatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ func TestDispatchEndpoint(t *testing.T) {

d.EndpointUrl = server.URL

client := dispatchtest.NewEndpointClient(server.URL, dispatchtest.WithSigningKey(signingKey))
client := dispatchtest.EndpointClient{
EndpointUrl: server.URL,
SigningKey: signingKey,
}

// Send a request for the identity function, and check that the
// input was echoed back.
Expand Down Expand Up @@ -100,7 +103,7 @@ func TestDispatchEndpoint(t *testing.T) {

// Try with a client that does not sign requests. The Dispatch
// instance should reject the request.
nonSigningClient := dispatchtest.NewEndpointClient(server.URL)
nonSigningClient := dispatchtest.EndpointClient{EndpointUrl: server.URL}
_, err = nonSigningClient.Run(context.Background(), &sdkv1.RunRequest{
Function: "identity",
Directive: &sdkv1.RunRequest_Input{Input: input},
Expand Down
85 changes: 44 additions & 41 deletions dispatchtest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/ed25519"
"net/http"
"sync"

"buf.build/gen/go/stealthrocket/dispatch-proto/connectrpc/go/dispatch/sdk/v1/sdkv1connect"
sdkv1 "buf.build/gen/go/stealthrocket/dispatch-proto/protocolbuffers/go/dispatch/sdk/v1"
Expand All @@ -18,60 +19,62 @@ import (
// is a client for the Dispatch API. The client here is
// useful when testing an endpoint.
type EndpointClient struct {
httpClient connect.HTTPClient
signingKey ed25519.PrivateKey
// EndpointUrl is the URL of the endpoint to connect to.
EndpointUrl string

// Client is the client to use when making HTTP requets.
// By default, http.DefaultClient is used.
Client connect.HTTPClient

// SigningKey is an optional signing key to use when signing
// outbound HTTP requests. If the key is omitted, requests are
// not signed.
SigningKey ed25519.PrivateKey

client sdkv1connect.FunctionServiceClient
err error
mu sync.Mutex
}

// NewEndpointClient creates an EndpointClient.
func NewEndpointClient(baseURL string, opts ...endpointClientOption) *EndpointClient {
c := &EndpointClient{}
for _, opt := range opts {
opt(c)
}

if c.httpClient == nil {
c.httpClient = http.DefaultClient
}
if c.signingKey != nil {
signer := auth.NewSigner(c.signingKey)
c.httpClient = signer.Client(c.httpClient)
// Run sends a RunRequest and returns a RunResponse.
func (c *EndpointClient) Run(ctx context.Context, req *sdkv1.RunRequest) (*sdkv1.RunResponse, error) {
client, err := c.endpointClient()
if err != nil {
return nil, err
}

validatingInterceptor, err := validate.NewInterceptor()
res, err := client.Run(ctx, connect.NewRequest(req))
if err != nil {
panic(err)
return nil, err
}
c.client = sdkv1connect.NewFunctionServiceClient(c.httpClient, baseURL,
connect.WithInterceptors(validatingInterceptor))
return c
return res.Msg, nil
}

type endpointClientOption func(*EndpointClient)
func (c *EndpointClient) endpointClient() (sdkv1connect.FunctionServiceClient, error) {
c.mu.Lock()
defer c.mu.Unlock()

// WithClient configures an EndpointClient to make HTTP
// requests using the specified HTTP client.
//
// By default, http.DefaultClient is used.
func WithClient(client *http.Client) endpointClientOption {
return endpointClientOption(func(c *EndpointClient) { c.httpClient = client })
}
if c.err != nil {
return nil, c.err
}
if c.client != nil {
return c.client, nil
}

// WithSigningKey configures an EndpointClient to sign
// requests in the same way that Dispatch would, using
// the specified ed25519 private key.
//
// By default, requests are not signed.
func WithSigningKey(signingKey ed25519.PrivateKey) endpointClientOption {
return endpointClientOption(func(c *EndpointClient) { c.signingKey = signingKey })
}
httpClient := c.Client
if httpClient == nil {
httpClient = http.DefaultClient
}
if c.SigningKey != nil {
signer := auth.NewSigner(c.SigningKey)
httpClient = signer.Client(httpClient)
}

// Run sends a RunRequest and returns a RunResponse.
func (c *EndpointClient) Run(ctx context.Context, req *sdkv1.RunRequest) (*sdkv1.RunResponse, error) {
res, err := c.client.Run(ctx, connect.NewRequest(req))
validatingInterceptor, err := validate.NewInterceptor()
if err != nil {
c.err = err
return nil, err
}
return res.Msg, nil
c.client = sdkv1connect.NewFunctionServiceClient(httpClient, c.EndpointUrl,
connect.WithInterceptors(validatingInterceptor))
return c.client, nil
}

0 comments on commit 97c0725

Please sign in to comment.