spanner: remove redundant x-goog-api-client header
The Spanner client now uses the gapic client, which automatically
sets the x-goog-api-client header, so this header should no longer
be set by the client itself.
Fixes #1524
Change-Id: Ib7523878a7d94f7e5a05b5caec6fc3312316c72c
Reviewed-on: https://code-review.googlesource.com/c/gocloud/+/43671
Reviewed-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
diff --git a/spanner/client.go b/spanner/client.go
index c3e7acb..a6b4a11 100644
--- a/spanner/client.go
+++ b/spanner/client.go
@@ -25,7 +25,6 @@
"time"
"cloud.google.com/go/internal/trace"
- "cloud.google.com/go/internal/version"
vkit "cloud.google.com/go/spanner/apiv1"
"cloud.google.com/go/spanner/internal/backoff"
"google.golang.org/api/option"
@@ -41,10 +40,6 @@
// resourcePrefixHeader is the name of the metadata header used to indicate
// the resource being operated on.
resourcePrefixHeader = "google-cloud-resource-prefix"
-
- // xGoogHeaderKey is the name of the metadata header used to indicate client
- // information.
- xGoogHeaderKey = "x-goog-api-client"
)
const (
@@ -57,7 +52,6 @@
var (
validDBPattern = regexp.MustCompile("^projects/[^/]+/instances/[^/]+/databases/[^/]+$")
- xGoogHeaderVal = fmt.Sprintf("gl-go/%s gccl/%s grpc/%s", version.Go(), version.Repo, grpc.Version)
)
func validDatabaseName(db string) error {
@@ -125,9 +119,7 @@
func NewClientWithConfig(ctx context.Context, database string, config ClientConfig, opts ...option.ClientOption) (c *Client, err error) {
c = &Client{
database: database,
- md: metadata.Pairs(
- resourcePrefixHeader, database,
- xGoogHeaderKey, xGoogHeaderVal),
+ md: metadata.Pairs(resourcePrefixHeader, database),
}
// Make a copy of labels.
diff --git a/spanner/client_test.go b/spanner/client_test.go
index 57a77b7..912e159 100644
--- a/spanner/client_test.go
+++ b/spanner/client_test.go
@@ -26,7 +26,9 @@
"cloud.google.com/go/spanner/internal/benchserver"
"cloud.google.com/go/spanner/internal/testutil"
"google.golang.org/api/iterator"
+ "google.golang.org/grpc"
"google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
gstatus "google.golang.org/grpc/status"
)
@@ -435,3 +437,50 @@
t.Fatal(err)
}
}
+
+func TestClient_ApiClientHeader(t *testing.T) {
+ t.Parallel()
+ server, client := newSpannerInMemTestServerWithInterceptor(t, func(
+ ctx context.Context,
+ method string,
+ req interface{},
+ reply interface{},
+ cc *grpc.ClientConn,
+ invoker grpc.UnaryInvoker,
+ opts ...grpc.CallOption,
+ ) error {
+ // Check that the x-goog-api-client is set.
+ headers, ok := metadata.FromOutgoingContext(ctx)
+ if !ok {
+ return spannerErrorf(codes.Internal, "could not get outgoing metadata")
+ }
+ token, ok := headers["x-goog-api-client"]
+ if !ok {
+ return spannerErrorf(codes.Internal, "could not get api client token")
+ }
+ if token == nil {
+ return spannerErrorf(codes.Internal, "nil-value for outgoing api client token")
+ }
+ if len(token) != 1 {
+ return spannerErrorf(codes.Internal, "unexpected number of api client token headers: %v", len(token))
+ }
+ if !strings.HasPrefix(token[0], "gl-go/") {
+ return spannerErrorf(codes.Internal, "unexpected api client token: %v", token[0])
+ }
+ return invoker(ctx, method, req, reply, cc, opts...)
+ },
+ )
+ defer server.teardown(client)
+ ctx := context.Background()
+ iter := client.Single().Query(ctx, NewStatement(selectSingerIDAlbumIDAlbumTitleFromAlbums))
+ defer iter.Stop()
+ for {
+ _, err := iter.Next()
+ if err == iterator.Done {
+ break
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/spanner/mocked_inmem_server.go b/spanner/mocked_inmem_server.go
index b98b177..ab96f71 100644
--- a/spanner/mocked_inmem_server.go
+++ b/spanner/mocked_inmem_server.go
@@ -56,18 +56,25 @@
return s, client
}
+// Create a spannerInMemTestServer with default configuration and a client interceptor.
+func newSpannerInMemTestServerWithInterceptor(t *testing.T, interceptor grpc.UnaryClientInterceptor) (*spannerInMemTestServer, *Client) {
+ s := &spannerInMemTestServer{}
+ client := s.setupWithConfig(t, ClientConfig{}, interceptor)
+ return s, client
+}
+
// Create a spannerInMemTestServer with the specified configuration.
func newSpannerInMemTestServerWithConfig(t *testing.T, config ClientConfig) (*spannerInMemTestServer, *Client) {
s := &spannerInMemTestServer{}
- client := s.setupWithConfig(t, config)
+ client := s.setupWithConfig(t, config, nil)
return s, client
}
func (s *spannerInMemTestServer) setup(t *testing.T) *Client {
- return s.setupWithConfig(t, ClientConfig{})
+ return s.setupWithConfig(t, ClientConfig{}, nil)
}
-func (s *spannerInMemTestServer) setupWithConfig(t *testing.T, config ClientConfig) *Client {
+func (s *spannerInMemTestServer) setupWithConfig(t *testing.T, config ClientConfig, interceptor grpc.UnaryClientInterceptor) *Client {
s.testSpanner = testutil.NewInMemSpannerServer()
s.setupFooResults()
s.setupSingersResults()
@@ -83,11 +90,15 @@
serverAddress := lis.Addr().String()
ctx := context.Background()
var formattedDatabase = fmt.Sprintf("projects/%s/instances/%s/databases/%s", "[PROJECT]", "[INSTANCE]", "[DATABASE]")
- client, err := NewClientWithConfig(ctx, formattedDatabase, config,
+ opts := []option.ClientOption{
option.WithEndpoint(serverAddress),
option.WithGRPCDialOption(grpc.WithInsecure()),
option.WithoutAuthentication(),
- )
+ }
+ if interceptor != nil {
+ opts = append(opts, option.WithGRPCDialOption(grpc.WithUnaryInterceptor(interceptor)))
+ }
+ client, err := NewClientWithConfig(ctx, formattedDatabase, config, opts...)
if err != nil {
t.Fatal(err)
}