Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 34 additions & 20 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
module github.com/improbable-eng/grpc-web

go 1.16
go 1.23.5

require (
github.com/cenkalti/backoff/v4 v4.1.1
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f
github.com/golang/protobuf v1.5.2
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/klauspost/compress v1.11.7 // indirect
github.com/cenkalti/backoff/v5 v5.0.2
github.com/coder/websocket v1.8.12
github.com/desertbit/timer v1.0.1
github.com/golang/protobuf v1.5.4
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76
github.com/prometheus/client_golang v1.12.1
github.com/rs/cors v1.7.0
github.com/sirupsen/logrus v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 // indirect
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
nhooyr.io/websocket v1.8.7
github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9
github.com/prometheus/client_golang v1.21.1
github.com/rs/cors v1.11.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
golang.org/x/net v0.37.0
google.golang.org/grpc v1.71.0
google.golang.org/protobuf v1.36.5
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
558 changes: 106 additions & 452 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion go/grpcweb/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"time"

backoff "github.com/cenkalti/backoff/v4"
backoff "github.com/cenkalti/backoff/v5"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
Expand Down
2 changes: 1 addition & 1 deletion go/grpcweb/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"net/http"
"time"

"nhooyr.io/websocket"
"github.com/coder/websocket"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion go/grpcweb/websocket_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"strings"
"time"

"github.com/coder/websocket"
"github.com/desertbit/timer"
"golang.org/x/net/http2"
"nhooyr.io/websocket"
)

type webSocketResponseWriter struct {
Expand Down
2 changes: 1 addition & 1 deletion go/grpcweb/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import (
"strings"
"time"

"github.com/coder/websocket"
"github.com/rs/cors"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"nhooyr.io/websocket"
)

var (
Expand Down
9 changes: 5 additions & 4 deletions go/grpcweb/wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func TestNonRootResource(t *testing.T) {
resp := httptest.NewRecorder()
wrappedServer.ServeHTTP(resp, req)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, http.StatusNoContent, resp.Code)
}

func (s *GrpcWebWrapperTestSuite) SetupTest() {
Expand Down Expand Up @@ -437,16 +437,17 @@ func (s *GrpcWebWrapperTestSuite) TestCORSPreflight_AllowedByOriginFunc() {

corsResp, err := s.makeRequest("OPTIONS", "/improbable.grpcweb.test.TestService/PingList", headers, nil, false)
assert.NoError(s.T(), err, "cors preflight should not return errors")
assert.Equal(s.T(), 204, corsResp.StatusCode, "cors should return 204 as the list is empty")

preflight := corsResp.Header
assert.Equal(s.T(), "https://foo.client.com", preflight.Get("Access-Control-Allow-Origin"), "origin must be in the response headers")
assert.Equal(s.T(), "POST", preflight.Get("Access-Control-Allow-Methods"), "allowed methods must be in the response headers")
assert.Equal(s.T(), "600", preflight.Get("Access-Control-Max-Age"), "allowed max age must be in the response headers")
assert.Equal(s.T(), "Origin, X-Something-Custom, X-Grpc-Web, Accept", preflight.Get("Access-Control-Allow-Headers"), "allowed headers must be in the response headers")
assert.Equal(s.T(), strings.ToLower("Origin, X-Something-Custom, X-Grpc-Web, Accept"), strings.ToLower(preflight.Get("Access-Control-Allow-Headers")), "allowed headers must be in the response headers")

corsResp, err = s.makeRequest("OPTIONS", "/improbable.grpcweb.test.TestService/Unknown", headers, nil, false)
assert.NoError(s.T(), err, "cors preflight should not return errors")
assert.Equal(s.T(), 500, corsResp.StatusCode, "cors should return 500 as grpc server does not understand that endpoint")
assert.Equal(s.T(), 405, corsResp.StatusCode, "cors should return 405 as grpc server does not understand that endpoint")
}

func (s *GrpcWebWrapperTestSuite) TestCORSPreflight_CorsMaxAge() {
Expand Down Expand Up @@ -514,7 +515,7 @@ func (s *GrpcWebWrapperTestSuite) TestCORSPreflight_EndpointsOnlyTrueWithHandler
assert.Equal(s.T(), "https://foo.client.com", preflight.Get("Access-Control-Allow-Origin"), "origin must be in the response headers")
assert.Equal(s.T(), "POST", preflight.Get("Access-Control-Allow-Methods"), "allowed methods must be in the response headers")
assert.Equal(s.T(), "600", preflight.Get("Access-Control-Max-Age"), "allowed max age must be in the response headers")
assert.Equal(s.T(), "Origin, X-Something-Custom, X-Grpc-Web, Accept", preflight.Get("Access-Control-Allow-Headers"), "allowed headers must be in the response headers")
assert.Equal(s.T(), strings.ToLower("Origin, X-Something-Custom, X-Grpc-Web, Accept"), strings.ToLower(preflight.Get("Access-Control-Allow-Headers")), "allowed headers must be in the response headers")

corsResp, err = s.makeRequest("OPTIONS", badMethod, headers, nil, false)
assert.NoError(s.T(), err, "cors preflight should not return errors")
Expand Down
28 changes: 11 additions & 17 deletions go/grpcwebproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ import (
"sync"
"time"

"nhooyr.io/websocket"

"crypto/tls"

grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/coder/websocket"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/mwitkow/go-conntrack"
"github.com/mwitkow/grpc-proxy/proxy"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -67,15 +65,14 @@ func main() {
}

logrus.SetOutput(os.Stdout)
logEntry := logrus.NewEntry(logrus.StandardLogger())

if *flagAllowAllOrigins && len(*flagAllowedOrigins) != 0 {
logrus.Fatal("Ambiguous --allow_all_origins and --allow_origins configuration. Either set --allow_all_origins=true OR specify one or more origins to whitelist with --allow_origins, not both.")
}

backendConn := dialBackendOrFail()

grpcServer := buildGrpcProxyServer(backendConn, logEntry)
grpcServer := buildGrpcProxyServer(backendConn)
errChan := make(chan error)

allowedOrigins := makeAllowedOrigins(*flagAllowedOrigins)
Expand Down Expand Up @@ -203,10 +200,9 @@ func serveServer(server *http.Server, listener net.Listener, name string, errCha
}()
}

func buildGrpcProxyServer(backendConn *grpc.ClientConn, logger *logrus.Entry) *grpc.Server {
func buildGrpcProxyServer(backendConn *grpc.ClientConn) *grpc.Server {
// gRPC-wide changes.
grpc.EnableTracing = true
grpc_logrus.ReplaceGrpcLogger(logger)

// gRPC proxy logic.
director := func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) {
Expand All @@ -222,19 +218,17 @@ func buildGrpcProxyServer(backendConn *grpc.ClientConn, logger *logrus.Entry) *g
return outCtx, backendConn, nil
}

serverMetrics := grpc_prometheus.NewServerMetrics()
reg := prometheus.NewRegistry()
reg.MustRegister(serverMetrics)

// Server with logging and monitoring enabled.
return grpc.NewServer(
grpc.CustomCodec(proxy.Codec()), // needed for proxy to function.
grpc.UnknownServiceHandler(proxy.TransparentHandler(director)),
grpc.MaxRecvMsgSize(*flagMaxCallRecvMsgSize),
grpc_middleware.WithUnaryServerChain(
grpc_logrus.UnaryServerInterceptor(logger),
grpc_prometheus.UnaryServerInterceptor,
),
grpc_middleware.WithStreamServerChain(
grpc_logrus.StreamServerInterceptor(logger),
grpc_prometheus.StreamServerInterceptor,
),
grpc.UnaryInterceptor(serverMetrics.UnaryServerInterceptor()),
grpc.StreamInterceptor(serverMetrics.StreamServerInterceptor()),
)
}

Expand Down