fake-gcs-server icon indicating copy to clipboard operation
fake-gcs-server copied to clipboard

Support the GRPC API?

Open fsouza opened this issue 5 years ago • 3 comments

Certain clients use only the GRPC API and we currently don't support this.

As reported in #84 and #142, the Java clients seem to be use only GRPC.

Open as a question because I don't know yet how much work that would be.

fsouza avatar Dec 09 '19 16:12 fsouza

Hello @fsouza, I am looking to use this within a C# app. I believe the C# app also uses the GRPC API. I was wondering where you were on researching this. I may have some time coming up to help work on this, with research, coding etc, if needed, as others have pointed out this is really the only library available for emulating GCS.

Tyler-Gauch avatar Apr 07 '20 19:04 Tyler-Gauch

Chiming in here to lend a few tips:

You can generate a server that fully implements the API quick using the proto file

git clone https://github.com/fsouza/fake-gcs-server.git
git clone --depth=1 https://github.com/googleapis/googleapis.git
mkdir grpc
protoc -I googleapis/ googleapis/google/storage/v1/*.proto --go_out=plugins=grpc:grpc
mv grpc/google.golang.org/genproto fake-gcs-server
rm -r grpc/
mkdir fake-gcs-server/grpc
touch fake-gcs-server/grpc/server.go

You should now have most of it ready to go, server.go contents (I did one as an example):

package grpc

import (
	"context"

	"github.com/golang/protobuf/ptypes"

	pb "github.com/fsouza/fake-gcs-server/genproto/googleapis/storage/v1"
	"github.com/fsouza/fake-gcs-server/internal/backend"
)

type Server struct {
	pb.UnimplementedStorageServer // To satisfy the interface without having to implement every method

	backend backend.Storage // share the same backend as fakeserver does
}

// Now just override whichever endpoints have been implemented in backend.Storage

func (g *grpcServer) ListBuckets(context.Context, *pb.ListBucketsRequest) (*pb.ListBucketsResponse, error) {
	buckets, err := g.backend.ListBuckets()
	if err != nil {
		return nil, err
	}

	resp := &pb.ListBucketsResponse{
		Items: make([]*pb.Bucket, len(buckets)),
	}
	for idx, bucket := range buckets {
		resp.Items[idx].Name = bucket.Name
		tc, err := ptypes.TimestampProto(bucket.TimeCreated)
		if err != nil {
			return nil, err
		}
		resp.Items[idx].TimeCreated = tc
		resp.Items[idx].Versioning = &pb.Bucket_Versioning{
			Enabled: bucket.VersioningEnabled,
		}
	}

	return resp, nil
}

you can use something like cmux to host both the HTTP and gRPC server on the same port (see this article)

I hope that helps!

someone1 avatar Apr 16 '20 03:04 someone1

Turns out the Java SDK issues were not related to gRPC, but rather gzip. Will leave this open though.

fsouza avatar Feb 15 '21 22:02 fsouza

Fixed via #1138.

fsouza avatar May 09 '23 00:05 fsouza