Skip to content

Commit

Permalink
⭐️ support the use of client plugins that allow an easy addition of h…
Browse files Browse the repository at this point in the history
…ttp headers (#12)

Signed-off-by: Christoph Hartmann <[email protected]>
  • Loading branch information
chris-rock authored Jul 27, 2022
1 parent ffa1f6f commit 5f288d0
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
23 changes: 22 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ import (
"moul.io/http2curl"
)

// ClientPlugin is a plugin that can be used to modify the http headers of a request.
type ClientPlugin interface {
GetName() string
GetHeader(content []byte) http.Header
}

// Client is the client for the Ranger service. It is used as the base client for all service calls.
type Client struct{}
type Client struct {
plugins []ClientPlugin
}

func (c *Client) AddPlugin(plugin ClientPlugin) {
c.plugins = append(c.plugins, plugin)
}

type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
Expand All @@ -39,6 +51,15 @@ func (c *Client) DoClientRequest(ctx context.Context, client HTTPClient, url str
header.Set("Accept", "application/protobuf")
header.Set("Content-Type", "application/protobuf")

for i := range c.plugins {
p := c.plugins[i]
pluginHeader := p.GetHeader(reqBodyBytes)
for k, v := range pluginHeader {
// check if we overwrite an existing header
header[k] = v
}
}

reader := bytes.NewReader(reqBodyBytes)
req, err := http.NewRequest("POST", url, reader)
if err != nil {
Expand Down
52 changes: 52 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ranger_test
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -240,3 +241,54 @@ func TestRangerStatusCodes(t *testing.T) {
assert.Equal(t, codes.InvalidArgument, codes.Code(status.GetCode()), "correct error message")
assert.Equal(t, "Value of `Input` is not allowed", status.GetMessage(), "correct error message")
}

type pingPongHeaderServiceTest struct{}

func (s *pingPongHeaderServiceTest) Ping(ctx context.Context, in *pingpong.PingRequest) (*pingpong.PongReply, error) {
msg := "Hello " + in.GetSender()
md, _ := metadata.FromIncomingContext(ctx)
header := md.Get("Authorization")
if len(header) == 1 {
msg += " with " + header[0]
}

return &pingpong.PongReply{Message: msg}, nil
}

func (s *pingPongHeaderServiceTest) NoPing(ctx context.Context, in *pingpong.Empty) (*pingpong.PongReply, error) {
return &pingpong.PongReply{Message: "HelloPong"}, nil
}

func newStaticTokenClientPlugin(token string) ranger.ClientPlugin {
return &staticTokenClientPlugin{token: token}
}

type staticTokenClientPlugin struct {
token string
}

func (scp *staticTokenClientPlugin) GetName() string {
return "Static Token Plugin"
}

func (scp *staticTokenClientPlugin) GetHeader(serialzed []byte) http.Header {
header := make(http.Header)
header.Set("Authorization", fmt.Sprintf("Bearer %s", scp.token))
return header
}

func TestClientPlugin(t *testing.T) {
service := pingPongHeaderServiceTest{}
pingPongSrv := pingpong.NewPingPongServer(&service)
ts := httptest.NewServer(pingPongSrv)
defer ts.Close()

client, err := pingpong.NewPingPongClient(ts.URL, ts.Client())
require.NoError(t, err)
client.AddPlugin(newStaticTokenClientPlugin("secret"))
resp, err := client.Ping(context.Background(), &pingpong.PingRequest{
Sender: "hi",
})
require.NoError(t, err)
assert.Equal(t, "Hello hi with Bearer secret", resp.Message, "correct response")
}

0 comments on commit 5f288d0

Please sign in to comment.