diff --git a/Makefile b/Makefile index cc880094592..abac26e6609 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,7 @@ $(ABE_EXAMPLE_SRCS): $(ABE_EXAMPLE_SPEC) examples: $(EXAMPLE_SVCSRCS) $(EXAMPLE_GWSRCS) $(EXAMPLE_DEPSRCS) $(EXAMPLE_SWAGGERSRCS) $(EXAMPLE_CLIENT_SRCS) test: examples go test -race $(PKG)/... + go test -race $(PKG)/examples -args -network=unix -endpoint=test.sock lint: golint --set_exit_status $(PKG)/runtime diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 41a853217c7..5ca5fa4ae2e 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -7,10 +7,9 @@ go_library( srcs = ["main.go"], importpath = "github.com/grpc-ecosystem/grpc-gateway/examples", deps = [ - "//examples/examplepb:go_default_library", + "//examples/gateway:go_default_library", "//runtime:go_default_library", "@com_github_golang_glog//:go_default_library", - "@org_golang_google_grpc//:go_default_library", ], ) diff --git a/examples/gateway/BUILD.bazel b/examples/gateway/BUILD.bazel new file mode 100644 index 00000000000..6aefb52a02b --- /dev/null +++ b/examples/gateway/BUILD.bazel @@ -0,0 +1,13 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["gateway.go"], + importpath = "github.com/grpc-ecosystem/grpc-gateway/examples/gateway", + visibility = ["//visibility:public"], + deps = [ + "//examples/examplepb:go_default_library", + "//runtime:go_default_library", + "@org_golang_google_grpc//:go_default_library", + ], +) diff --git a/examples/gateway/gateway.go b/examples/gateway/gateway.go new file mode 100644 index 00000000000..cc503dd2814 --- /dev/null +++ b/examples/gateway/gateway.go @@ -0,0 +1,71 @@ +package gateway + +import ( + "context" + "net" + "net/http" + "time" + + "github.com/grpc-ecosystem/grpc-gateway/examples/examplepb" + gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" +) + +type optSet struct { + mux []gwruntime.ServeMuxOption + dial []grpc.DialOption + + echoEndpoint, abeEndpoint, flowEndpoint string +} + +// newGateway returns a new gateway server which translates HTTP into gRPC. +func newGateway(ctx context.Context, opts optSet) (http.Handler, error) { + mux := gwruntime.NewServeMux(opts.mux...) + + err := examplepb.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, opts.echoEndpoint, opts.dial) + if err != nil { + return nil, err + } + err = examplepb.RegisterStreamServiceHandlerFromEndpoint(ctx, mux, opts.abeEndpoint, opts.dial) + if err != nil { + return nil, err + } + err = examplepb.RegisterABitOfEverythingServiceHandlerFromEndpoint(ctx, mux, opts.abeEndpoint, opts.dial) + if err != nil { + return nil, err + } + err = examplepb.RegisterFlowCombinationHandlerFromEndpoint(ctx, mux, opts.flowEndpoint, opts.dial) + if err != nil { + return nil, err + } + return mux, nil +} + +// NewTCPGateway returns a new gateway server which connect to the gRPC service with TCP. +// "addr" must be a valid TCP address with a port number. +func NewTCPGateway(ctx context.Context, addr string, opts ...gwruntime.ServeMuxOption) (http.Handler, error) { + return newGateway(ctx, optSet{ + mux: opts, + dial: []grpc.DialOption{grpc.WithInsecure()}, + echoEndpoint: addr, + abeEndpoint: addr, + flowEndpoint: addr, + }) +} + +// NewUnixGatway returns a new gateway server which connect to the gRPC service with a unix domain socket. +// "addr" must be a valid path to the socket. +func NewUnixGateway(ctx context.Context, addr string, opts ...gwruntime.ServeMuxOption) (http.Handler, error) { + return newGateway(ctx, optSet{ + mux: opts, + dial: []grpc.DialOption{ + grpc.WithInsecure(), + grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("unix", addr, timeout) + }), + }, + echoEndpoint: addr, + abeEndpoint: addr, + flowEndpoint: addr, + }) +} diff --git a/examples/main.go b/examples/main.go index 19945df3d3c..bb2b55614da 100644 --- a/examples/main.go +++ b/examples/main.go @@ -1,49 +1,24 @@ package main import ( + "context" "flag" + "fmt" "net/http" "path" "strings" - "context" "github.com/golang/glog" - "github.com/grpc-ecosystem/grpc-gateway/examples/examplepb" + "github.com/grpc-ecosystem/grpc-gateway/examples/gateway" "github.com/grpc-ecosystem/grpc-gateway/runtime" - "google.golang.org/grpc" ) var ( - echoEndpoint = flag.String("echo_endpoint", "localhost:9090", "endpoint of EchoService") - abeEndpoint = flag.String("more_endpoint", "localhost:9090", "endpoint of ABitOfEverythingService") - flowEndpoint = flag.String("flow_endpoint", "localhost:9090", "endpoint of FlowCombination") - + endpoint = flag.String("endpoint", "localhost:9090", "endpoint of the gRPC service") + network = flag.String("network", "tcp", `one of "tcp" or "unix". Must be consistent to -endpoint`) swaggerDir = flag.String("swagger_dir", "examples/examplepb", "path to the directory which contains swagger definitions") ) -// newGateway returns a new gateway server which translates HTTP into gRPC. -func newGateway(ctx context.Context, opts ...runtime.ServeMuxOption) (http.Handler, error) { - mux := runtime.NewServeMux(opts...) - dialOpts := []grpc.DialOption{grpc.WithInsecure()} - err := examplepb.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, dialOpts) - if err != nil { - return nil, err - } - err = examplepb.RegisterStreamServiceHandlerFromEndpoint(ctx, mux, *abeEndpoint, dialOpts) - if err != nil { - return nil, err - } - err = examplepb.RegisterABitOfEverythingServiceHandlerFromEndpoint(ctx, mux, *abeEndpoint, dialOpts) - if err != nil { - return nil, err - } - err = examplepb.RegisterFlowCombinationHandlerFromEndpoint(ctx, mux, *flowEndpoint, dialOpts) - if err != nil { - return nil, err - } - return mux, nil -} - func serveSwagger(w http.ResponseWriter, r *http.Request) { if !strings.HasSuffix(r.URL.Path, ".swagger.json") { glog.Errorf("Not Found: %s", r.URL.Path) @@ -81,6 +56,17 @@ func preflightHandler(w http.ResponseWriter, r *http.Request) { return } +func newGateway(ctx context.Context, opts ...runtime.ServeMuxOption) (http.Handler, error) { + switch *network { + case "tcp": + return gateway.NewTCPGateway(ctx, *endpoint, opts...) + case "unix": + return gateway.NewUnixGateway(ctx, *endpoint, opts...) + default: + return nil, fmt.Errorf("unsupported network type %q:", *network) + } +} + // Run starts a HTTP server and blocks forever if successful. func Run(ctx context.Context, address string, opts ...runtime.ServeMuxOption) error { ctx, cancel := context.WithCancel(ctx) diff --git a/examples/main_test.go b/examples/main_test.go index 9dfdd2dbe63..9c98c6f7a4e 100644 --- a/examples/main_test.go +++ b/examples/main_test.go @@ -15,7 +15,7 @@ import ( func runServers(ctx context.Context) <-chan error { ch := make(chan error, 2) go func() { - if err := server.Run(ctx); err != nil { + if err := server.Run(ctx, *network, *endpoint); err != nil { ch <- fmt.Errorf("cannot run grpc service: %v", err) } }() diff --git a/examples/server/cmd/example-server/main.go b/examples/server/cmd/example-server/main.go index fc1763c04ea..31e182c4b12 100644 --- a/examples/server/cmd/example-server/main.go +++ b/examples/server/cmd/example-server/main.go @@ -8,12 +8,17 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/examples/server" ) +var ( + addr = flag.String("addr", ":9090", "endpoint of the gRPC service") + network = flag.String("network", "tcp", "a valid network type which is consistent to -addr") +) + func main() { flag.Parse() defer glog.Flush() ctx := context.Background() - if err := server.Run(ctx); err != nil { + if err := server.Run(ctx, *network, *addr); err != nil { glog.Fatal(err) } } diff --git a/examples/server/main.go b/examples/server/main.go index 88f4df0f611..a24f16b7cab 100644 --- a/examples/server/main.go +++ b/examples/server/main.go @@ -10,14 +10,15 @@ import ( ) // Run starts the example gRPC service. -func Run(ctx context.Context) error { - l, err := net.Listen("tcp", ":9090") +// "network" and "address" are passed to net.Listen. +func Run(ctx context.Context, network, address string) error { + l, err := net.Listen(network, address) if err != nil { return err } defer func() { if err := l.Close(); err != nil { - glog.Errorf("Failed to close tcp :9090: %v", err) + glog.Errorf("Failed to close %s %s: %v", network, address, err) } }()