Skip to content

Commit

Permalink
support gRPC reflection with gRPC Web (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktr0731 authored Aug 18, 2018
1 parent 31ada70 commit c089af0
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 44 deletions.
206 changes: 179 additions & 27 deletions Gopkg.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ deadcode-test:

.PHONY: vet
vet:
@gometalinter --vendor --disable-all --enable=vet ./...
@gometalinter --vendor --disable-all $(shell go list ./... | grep -v tests)

.PHONY: deadcode
deadcode:
Expand Down
10 changes: 6 additions & 4 deletions adapter/controller/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,11 @@ func (c *CLI) runAsCLI() int {
errCh <- err
return
}
interactor := usecase.NewInteractor(p)
closeCtx, closeCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer closeCancel()
defer interactor.Close(closeCtx)
defer p.Cleanup(closeCtx)

interactor := usecase.NewInteractor(p)

res, err := interactor.Call(&port.CallParams{RPCName: c.wcfg.call})
if err != nil {
Expand Down Expand Up @@ -398,10 +399,11 @@ func (c *CLI) runAsREPL() int {
errCh <- err
return
}
interactor := usecase.NewInteractor(p)
closeCtx, closeCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer closeCancel()
defer interactor.Close(closeCtx)
defer p.Cleanup(closeCtx)

interactor := usecase.NewInteractor(p)

var ui UI
if c.wcfg.cfg.REPL.ColoredOutput {
Expand Down
8 changes: 8 additions & 0 deletions adapter/gateway/grpc_reflection.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/jhump/protoreflect/grpcreflect"
"github.com/ktr0731/evans/adapter/protobuf"
"github.com/ktr0731/evans/entity"
"github.com/ktr0731/grpc-web-go-client/grpcweb"
"github.com/ktr0731/grpc-web-go-client/grpcweb/grpcweb_reflection_v1alpha"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
Expand All @@ -24,6 +26,12 @@ func newGRPCReflectionClient(conn *grpc.ClientConn) *gRPCReflectoinClient {
}
}

func newGRPCWebReflectionClient(conn *grpcweb.Client) *gRPCReflectoinClient {
return &gRPCReflectoinClient{
client: grpcreflect.NewClient(context.Background(), grpcweb_reflection_v1alpha.NewServerReflectionClient(conn)),
}
}

func (c *gRPCReflectoinClient) ReflectionEnabled() bool {
return c != nil
}
Expand Down
7 changes: 5 additions & 2 deletions adapter/gateway/grpcweb.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewGRPCWebClient(config *config.Config, builder port.DynamicBuilder) *GRPCW
}

if config.Server.Reflection {
// TODO: gRPC Web + gRPC reflection
client.gRPCReflectoinClient = newGRPCWebReflectionClient(conn)
}

return client
Expand Down Expand Up @@ -179,7 +179,10 @@ func (c *GRPCWebClient) NewBidiStream(ctx context.Context, rpc entity.RPC) (enti
}

req := newRequest(c.builder.NewMessage(rpc.RequestMessage()))
sc := c.conn.BidiStreaming(ctx, req)
sc, err := c.conn.BidiStreaming(ctx, req)
if err != nil {
return nil, errors.Wrap(err, "failed to start bidirectional streaming")
}

return &webBidiStream{
conn: sc,
Expand Down
7 changes: 6 additions & 1 deletion di/dependency.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package di

import (
"context"
"io"
"sync"

Expand Down Expand Up @@ -254,5 +255,9 @@ func initDependencies(cfg *config.Config, in io.Reader) error {
initDynamicBuilder,
)
})
return initer.init()
if err := initer.init(); err != nil {
gRPCClient.Close(context.Background())
return err
}
return nil
}
1 change: 1 addition & 0 deletions di/interactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func NewCLIInteractorParams(cfg *config.Config, in io.Reader) (*usecase.Interact
if err := initDependencies(cfg, in); err != nil {
return nil, err
}

return &usecase.InteractorParams{
Env: env,
OutputPort: jsonCLIPresenter,
Expand Down
2 changes: 1 addition & 1 deletion meta/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import (
const AppName = "evans"

var (
Version = semver.MustParse("0.5.2")
Version = semver.MustParse("0.6.0")
)
7 changes: 6 additions & 1 deletion tests/e2e/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ func TestCLI(t *testing.T) {
{args: "--reflection", code: 1, useReflection: true},
{args: "--reflection --service Greeter", code: 1, useReflection: true},
{args: "--reflection --call SayHello", code: 1, useReflection: true},
{args: "--reflection --service Greeter --call SayHello", code: 0, useReflection: true},
{args: "--reflection --service Greeter --call SayHello", useReflection: true},

{args: "--web --package helloworld --service Greeter --call SayHello testdata/helloworld.proto", useWeb: true},

{args: "--web --reflection --package foo", useReflection: true, useWeb: true, code: 1},
{args: "--web --reflection --service bar", useReflection: true, useWeb: true, code: 1},
{args: "--web --reflection --service Greeter", useReflection: true, useWeb: true, code: 1},
{args: "--web --reflection --service Greeter --call SayHello", useReflection: true, useWeb: true},
}

for _, c := range cases {
Expand Down
3 changes: 2 additions & 1 deletion tests/e2e/repl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func TestREPL(t *testing.T) {
{args: "--web --package helloworld --service foo testdata/helloworld.proto", useWeb: true, code: 1},
{args: "--web --package helloworld --service Greeter testdata/helloworld.proto", useWeb: true},

{args: "--web --reflection --service Greeter", useReflection: true, useWeb: true, code: 1},
{args: "--web --reflection --service Greeter", useReflection: true, useWeb: true},
{args: "--web --reflection --service bar", useReflection: true, useWeb: true, code: 1},
}

rh := newREPLHelper([]string{"--silent", "--repl"})
Expand Down
6 changes: 5 additions & 1 deletion tests/helper/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func NewServer(t *testing.T, enableReflection bool) *Server {

func (s *Server) Start(web bool) *Server {
if web {
ws := grpcweb.WrapServer(s.s, grpcweb.WithWebsockets(false))
ws := grpcweb.WrapServer(
s.s,
grpcweb.WithWebsockets(true),
grpcweb.WithWebsocketOriginFunc(func(req *http.Request) bool { return true }),
)
mux := http.NewServeMux()
mux.Handle("/", ws)
s.ws = &http.Server{
Expand Down
12 changes: 7 additions & 5 deletions usecase/interactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ type InteractorParams struct {
GRPCClient entity.GRPCClient
}

func (p *InteractorParams) Cleanup(ctx context.Context) error {
if p.GRPCClient != nil {
return p.GRPCClient.Close(ctx)
}
return nil
}

func NewInteractor(params *InteractorParams) *Interactor {
return &Interactor{
env: params.Env,
Expand Down Expand Up @@ -59,8 +66,3 @@ func (i *Interactor) Header(params *port.HeaderParams) (io.Reader, error) {
func (i *Interactor) Call(params *port.CallParams) (io.Reader, error) {
return Call(params, i.outputPort, i.inputterPort, i.grpcPort, i.dynamicBuilder, i.env)
}

// Close closes all dependencies by each Close method.
func (i *Interactor) Close(ctx context.Context) error {
return i.grpcPort.Close(ctx)
}

0 comments on commit c089af0

Please sign in to comment.