1
0
mirror of https://github.com/taigrr/wasm-experiments synced 2025-01-18 04:03:21 -08:00

gRPC: Use grpc-wasm as client package

This commit is contained in:
Johan Brandhorst
2018-06-04 22:51:10 +01:00
parent e48ef08afd
commit 2392bc267d
19 changed files with 672 additions and 270 deletions

View File

@@ -38,3 +38,7 @@ func (b Backend) GetUser(ctx context.Context, req *server.GetUserRequest) (*serv
Id: req.GetUserId(),
}, nil
}
func (b Backend) GetUsers(req *server.GetUsersRequest, srv server.Backend_GetUsersServer) error {
return nil
}

View File

@@ -1 +0,0 @@
html/test.wasm

File diff suppressed because one or more lines are too long

View File

@@ -1,28 +1,14 @@
package main
import (
"bufio"
"bytes"
"context"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
_ "google.golang.org/genproto/googleapis/rpc/errdetails"
spb "google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"github.com/johanbrandhorst/fetch"
"github.com/johanbrandhorst/wasm-experiments/grpc/proto/server"
grpc "github.com/johanbrandhorst/grpc-wasm"
server "github.com/johanbrandhorst/wasm-experiments/grpc/proto/client"
)
// Build with Go WASM fork
@@ -33,220 +19,24 @@ import (
//go:generate bash -c "go run assets_generate.go"
func main() {
s := newClientConn("", "web.Backend")
req := &server.GetUserRequest{
cc, _ := grpc.Dial("")
client := server.NewBackendClient(cc)
resp, err := client.GetUser(context.Background(), &server.GetUserRequest{
UserId: "1234",
}
resp := new(server.User)
err := s.Invoke(context.Background(), "GetUser", req, resp)
})
if err != nil {
st := status.Convert(err)
fmt.Println(st.Code(), st.Message(), st.Details())
return
}
fmt.Println(resp.GetId())
req.UserId = "123"
err = s.Invoke(context.Background(), "GetUser", req, resp)
if err != nil {
st := status.Convert(err)
fmt.Println(st.Code(), st.Message(), st.Details())
return
}
fmt.Println(resp.GetId())
}
type ClientConn struct {
client *http.Client
service string
host string
}
func newClientConn(host, service string) *ClientConn {
return &ClientConn{
client: &http.Client{
Transport: &fetch.Transport{},
},
service: service,
host: host,
}
}
func (cc *ClientConn) Invoke(ctx context.Context, method string, in, out proto.Message) error {
b, err := proto.Marshal(in)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
bufHeader := make([]byte, 5)
// Write length of b into buf
binary.BigEndian.PutUint32(bufHeader[1:], uint32(len(b)))
req, err := http.NewRequest(
"POST",
strings.Join([]string{cc.host, cc.service, method}, "/"),
bytes.NewBuffer(append(bufHeader, b...)),
)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
req = req.WithContext(ctx)
addHeaders(req)
resp, err := cc.client.Do(req)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
defer resp.Body.Close()
st := statusFromHeaders(resp.Header)
if st.Code() != codes.OK {
return st.Err()
}
msgHeader := make([]byte, 5)
for {
_, err := resp.Body.Read(msgHeader)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
// 1 in MSB signifies that this is the trailer. Break loop.
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2
if msgHeader[0]>>7 == 1 {
break
}
msgLen := binary.BigEndian.Uint32(msgHeader[1:])
msg := make([]byte, msgLen)
_, err = resp.Body.Read(msg)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
err = proto.Unmarshal(msg, out)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
}
if msgHeader[0]&1 == 0 {
trailers, err := readTrailers(resp.Body)
if err != nil {
return status.Error(codes.Internal, err.Error())
}
st = statusFromHeaders(trailers)
if st.Code() != codes.OK {
return st.Err()
}
} else {
// TODO(johanbrandhorst): Support compressed trailers
fmt.Println(resp.GetId())
}
return nil
}
func addHeaders(req *http.Request) {
// TODO: Add more headers
// https://github.com/grpc/grpc-go/blob/590da37e2dfb4705d8ebd9574ce4cb75295d9674/transport/http2_client.go#L356
req.Header.Add("content-type", "application/grpc-web+proto")
if dl, ok := req.Context().Deadline(); ok {
timeout := dl.Sub(time.Now())
req.Header.Add("grpc-timeout", encodeTimeout(timeout))
}
md, ok := metadata.FromOutgoingContext(req.Context())
if ok {
for h, vs := range md {
for _, v := range vs {
req.Header.Add(h, v)
}
}
resp, err = client.GetUser(context.Background(), &server.GetUserRequest{
UserId: "123",
})
if err != nil {
st := status.Convert(err)
fmt.Println(st.Code(), st.Message(), st.Details())
} else {
fmt.Println(resp.GetId())
}
}
const maxTimeoutValue int64 = 100000000 - 1
// Copied from grpc-go
// https://github.com/grpc/grpc-go/blob/590da37e2dfb4705d8ebd9574ce4cb75295d9674/transport/http_util.go#L388
// div does integer division and round-up the result. Note that this is
// equivalent to (d+r-1)/r but has less chance to overflow.
func div(d, r time.Duration) int64 {
if m := d % r; m > 0 {
return int64(d/r + 1)
}
return int64(d / r)
}
// Copied from grpc-go
// https://github.com/grpc/grpc-go/blob/590da37e2dfb4705d8ebd9574ce4cb75295d9674/transport/http_util.go#L398
func encodeTimeout(t time.Duration) string {
if t <= 0 {
return "0n"
}
if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
return strconv.FormatInt(d, 10) + "n"
}
if d := div(t, time.Microsecond); d <= maxTimeoutValue {
return strconv.FormatInt(d, 10) + "u"
}
if d := div(t, time.Millisecond); d <= maxTimeoutValue {
return strconv.FormatInt(d, 10) + "m"
}
if d := div(t, time.Second); d <= maxTimeoutValue {
return strconv.FormatInt(d, 10) + "S"
}
if d := div(t, time.Minute); d <= maxTimeoutValue {
return strconv.FormatInt(d, 10) + "M"
}
// Note that maxTimeoutValue * time.Hour > MaxInt64.
return strconv.FormatInt(div(t, time.Hour), 10) + "H"
}
// Copied from grpc-go
// https://github.com/grpc/grpc-go/blob/b94ea975f3beb73799fac17cc24ee923fcd3cb5c/transport/http_util.go#L213
func decodeBinHeader(v string) ([]byte, error) {
if len(v)%4 == 0 {
// Input was padded, or padding was not necessary.
return base64.StdEncoding.DecodeString(v)
}
return base64.RawStdEncoding.DecodeString(v)
}
func readTrailers(in io.Reader) (http.Header, error) {
s := bufio.NewScanner(in)
trailers := http.Header{}
for s.Scan() {
v := s.Text()
kv := strings.SplitN(v, ": ", 2)
if len(kv) != 2 {
return nil, errors.New("malformed header: " + v)
}
trailers.Add(kv[0], kv[1])
}
return trailers, s.Err()
}
func statusFromHeaders(h http.Header) *status.Status {
details := h.Get("grpc-status-details-bin")
if details != "" {
b, err := decodeBinHeader(details)
if err != nil {
return status.New(codes.Internal, "malformed grps-status-details-bin header: "+err.Error())
}
s := &spb.Status{}
err = proto.Unmarshal(b, s)
if err != nil {
return status.New(codes.Internal, "malformed grps-status-details-bin header: "+err.Error())
}
return status.FromProto(s)
}
sh := h.Get("grpc-status")
if sh != "" {
val, err := strconv.Atoi(sh)
if err != nil {
return status.New(codes.Internal, "malformed grpc-status header: "+err.Error())
}
return status.New(codes.Code(val), h.Get("grpc-message"))
}
return status.New(codes.OK, "")
}

View File

@@ -12,8 +12,8 @@ import fmt "fmt"
import math "math"
import (
grpc "github.com/johanbrandhorst/grpc-wasm"
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
@@ -38,7 +38,7 @@ func (m *GetUserRequest) Reset() { *m = GetUserRequest{} }
func (m *GetUserRequest) String() string { return proto.CompactTextString(m) }
func (*GetUserRequest) ProtoMessage() {}
func (*GetUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_web_19a831568a3bf959, []int{0}
return fileDescriptor_web_87670d45010119fa, []int{0}
}
func (m *GetUserRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetUserRequest.Unmarshal(m, b)
@@ -76,7 +76,7 @@ func (m *User) Reset() { *m = User{} }
func (m *User) String() string { return proto.CompactTextString(m) }
func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) {
return fileDescriptor_web_19a831568a3bf959, []int{1}
return fileDescriptor_web_87670d45010119fa, []int{1}
}
func (m *User) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_User.Unmarshal(m, b)
@@ -103,9 +103,48 @@ func (m *User) GetId() string {
return ""
}
type GetUsersRequest struct {
NumUsers int64 `protobuf:"varint,1,opt,name=num_users,json=numUsers" json:"num_users,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetUsersRequest) Reset() { *m = GetUsersRequest{} }
func (m *GetUsersRequest) String() string { return proto.CompactTextString(m) }
func (*GetUsersRequest) ProtoMessage() {}
func (*GetUsersRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_web_87670d45010119fa, []int{2}
}
func (m *GetUsersRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetUsersRequest.Unmarshal(m, b)
}
func (m *GetUsersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetUsersRequest.Marshal(b, m, deterministic)
}
func (dst *GetUsersRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetUsersRequest.Merge(dst, src)
}
func (m *GetUsersRequest) XXX_Size() int {
return xxx_messageInfo_GetUsersRequest.Size(m)
}
func (m *GetUsersRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetUsersRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetUsersRequest proto.InternalMessageInfo
func (m *GetUsersRequest) GetNumUsers() int64 {
if m != nil {
return m.NumUsers
}
return 0
}
func init() {
proto.RegisterType((*GetUserRequest)(nil), "web.GetUserRequest")
proto.RegisterType((*User)(nil), "web.User")
proto.RegisterType((*GetUsersRequest)(nil), "web.GetUsersRequest")
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -121,6 +160,7 @@ const _ = grpc.SupportPackageIsVersion4
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BackendClient interface {
GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*User, error)
GetUsers(ctx context.Context, in *GetUsersRequest, opts ...grpc.CallOption) (Backend_GetUsersClient, error)
}
type backendClient struct {
@@ -140,9 +180,42 @@ func (c *backendClient) GetUser(ctx context.Context, in *GetUserRequest, opts ..
return out, nil
}
func (c *backendClient) GetUsers(ctx context.Context, in *GetUsersRequest, opts ...grpc.CallOption) (Backend_GetUsersClient, error) {
stream, err := c.cc.NewStream(ctx, &_Backend_serviceDesc.Streams[0], "/web.Backend/GetUsers", opts...)
if err != nil {
return nil, err
}
x := &backendGetUsersClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Backend_GetUsersClient interface {
Recv() (*User, error)
grpc.ClientStream
}
type backendGetUsersClient struct {
grpc.ClientStream
}
func (x *backendGetUsersClient) Recv() (*User, error) {
m := new(User)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// BackendServer is the server API for Backend service.
type BackendServer interface {
GetUser(context.Context, *GetUserRequest) (*User, error)
GetUsers(*GetUsersRequest, Backend_GetUsersServer) error
}
func RegisterBackendServer(s *grpc.Server, srv BackendServer) {
@@ -167,6 +240,27 @@ func _Backend_GetUser_Handler(srv interface{}, ctx context.Context, dec func(int
return interceptor(ctx, in, info, handler)
}
func _Backend_GetUsers_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetUsersRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(BackendServer).GetUsers(m, &backendGetUsersServer{stream})
}
type Backend_GetUsersServer interface {
Send(*User) error
grpc.ServerStream
}
type backendGetUsersServer struct {
grpc.ServerStream
}
func (x *backendGetUsersServer) Send(m *User) error {
return x.ServerStream.SendMsg(m)
}
var _Backend_serviceDesc = grpc.ServiceDesc{
ServiceName: "web.Backend",
HandlerType: (*BackendServer)(nil),
@@ -176,25 +270,33 @@ var _Backend_serviceDesc = grpc.ServiceDesc{
Handler: _Backend_GetUser_Handler,
},
},
Streams: []grpc.StreamDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "GetUsers",
Handler: _Backend_GetUsers_Handler,
ServerStreams: true,
},
},
Metadata: "proto/web.proto",
}
func init() { proto.RegisterFile("proto/web.proto", fileDescriptor_web_19a831568a3bf959) }
func init() { proto.RegisterFile("proto/web.proto", fileDescriptor_web_87670d45010119fa) }
var fileDescriptor_web_19a831568a3bf959 = []byte{
// 197 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x28, 0xca, 0x2f,
0xc9, 0xd7, 0x2f, 0x4f, 0x4d, 0xd2, 0x03, 0xb3, 0x84, 0x98, 0xcb, 0x53, 0x93, 0x94, 0x34, 0xb9,
0xf8, 0xdc, 0x53, 0x4b, 0x42, 0x8b, 0x53, 0x8b, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84,
0xc4, 0xb9, 0xd8, 0x4b, 0x8b, 0x53, 0x8b, 0xe2, 0x33, 0x53, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38,
0x83, 0xd8, 0x40, 0x5c, 0xcf, 0x14, 0x25, 0x31, 0x2e, 0x16, 0x90, 0x3a, 0x21, 0x3e, 0x2e, 0x26,
0xb8, 0x1c, 0x53, 0x66, 0x8a, 0x91, 0x19, 0x17, 0xbb, 0x53, 0x62, 0x72, 0x76, 0x6a, 0x5e, 0x8a,
0x90, 0x36, 0x17, 0x3b, 0xd4, 0x34, 0x21, 0x61, 0x3d, 0x90, 0x4d, 0xa8, 0x66, 0x4b, 0x71, 0x82,
0x05, 0x41, 0x22, 0x4a, 0x0c, 0x4e, 0xf6, 0x51, 0xb6, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a,
0xc9, 0xf9, 0xb9, 0xfa, 0x59, 0xf9, 0x19, 0x89, 0x79, 0x49, 0x45, 0x89, 0x79, 0x29, 0x19, 0xf9,
0x45, 0xc5, 0x25, 0xfa, 0xe5, 0x89, 0xc5, 0xb9, 0xba, 0xa9, 0x15, 0x05, 0xa9, 0x45, 0x99, 0xb9,
0xa9, 0x79, 0x25, 0xc5, 0xfa, 0xe9, 0x45, 0x05, 0xc9, 0xfa, 0x10, 0x3f, 0x14, 0xa7, 0x16, 0x95,
0xa5, 0x16, 0x25, 0xb1, 0x81, 0x79, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x64, 0xf1,
0x41, 0xda, 0x00, 0x00, 0x00,
var fileDescriptor_web_87670d45010119fa = []byte{
// 236 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xc1, 0x4b, 0xc3, 0x30,
0x18, 0xc5, 0xdd, 0x26, 0xeb, 0xfa, 0x1d, 0x36, 0x88, 0xa2, 0xa2, 0x17, 0xe9, 0x49, 0x11, 0x1b,
0xd1, 0xb3, 0x08, 0xbb, 0x88, 0xd7, 0x82, 0x17, 0x2f, 0xa3, 0x69, 0x3e, 0xda, 0x2a, 0x49, 0xea,
0xf7, 0x25, 0xd6, 0x3f, 0x5f, 0x12, 0x37, 0x51, 0xf0, 0x96, 0xf7, 0xf2, 0x7b, 0x2f, 0x8f, 0xc0,
0x6a, 0x20, 0xe7, 0x9d, 0x1c, 0x51, 0x95, 0xe9, 0x24, 0x66, 0x23, 0xaa, 0xe2, 0x12, 0x96, 0x8f,
0xe8, 0x9f, 0x19, 0xa9, 0xc2, 0xf7, 0x80, 0xec, 0xc5, 0x31, 0x64, 0x81, 0x91, 0x36, 0xbd, 0x3e,
0x99, 0x9c, 0x4f, 0x2e, 0xf2, 0x6a, 0x1e, 0xe5, 0x93, 0x2e, 0x8e, 0x60, 0x3f, 0x72, 0x62, 0x09,
0xd3, 0x9f, 0xbb, 0x69, 0xaf, 0x8b, 0x12, 0x56, 0xdb, 0x0a, 0xde, 0x75, 0x9c, 0x41, 0x6e, 0x83,
0xd9, 0xc4, 0x20, 0x27, 0x72, 0x56, 0x2d, 0x6c, 0x30, 0x89, 0xb9, 0x6d, 0x21, 0x5b, 0xd7, 0xcd,
0x1b, 0x5a, 0x2d, 0xae, 0x20, 0xdb, 0x46, 0xc5, 0x41, 0x19, 0x97, 0xfd, 0xdd, 0x72, 0x9a, 0x27,
0x33, 0x3a, 0xc5, 0x9e, 0x90, 0xb0, 0xd8, 0xbd, 0x23, 0x0e, 0x7f, 0xd3, 0xfc, 0x1f, 0x7e, 0x33,
0x59, 0x3f, 0xbc, 0xdc, 0xb7, 0xbd, 0xef, 0x82, 0x2a, 0x1b, 0x67, 0xe4, 0xab, 0xeb, 0x6a, 0xab,
0xa8, 0xb6, 0xba, 0x73, 0xc4, 0x5e, 0x8e, 0x35, 0x9b, 0x6b, 0xfc, 0x1c, 0x90, 0x7a, 0x83, 0xd6,
0xb3, 0x6c, 0x69, 0x68, 0xe4, 0xf7, 0x27, 0x31, 0xd2, 0x07, 0x92, 0x9a, 0x27, 0x75, 0xf7, 0x15,
0x00, 0x00, 0xff, 0xff, 0x75, 0x28, 0x26, 0x8f, 0x3b, 0x01, 0x00, 0x00,
}

View File

@@ -38,7 +38,7 @@ func (m *GetUserRequest) Reset() { *m = GetUserRequest{} }
func (m *GetUserRequest) String() string { return proto.CompactTextString(m) }
func (*GetUserRequest) ProtoMessage() {}
func (*GetUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_web_19a831568a3bf959, []int{0}
return fileDescriptor_web_87670d45010119fa, []int{0}
}
func (m *GetUserRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetUserRequest.Unmarshal(m, b)
@@ -76,7 +76,7 @@ func (m *User) Reset() { *m = User{} }
func (m *User) String() string { return proto.CompactTextString(m) }
func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) {
return fileDescriptor_web_19a831568a3bf959, []int{1}
return fileDescriptor_web_87670d45010119fa, []int{1}
}
func (m *User) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_User.Unmarshal(m, b)
@@ -103,9 +103,48 @@ func (m *User) GetId() string {
return ""
}
type GetUsersRequest struct {
NumUsers int64 `protobuf:"varint,1,opt,name=num_users,json=numUsers" json:"num_users,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetUsersRequest) Reset() { *m = GetUsersRequest{} }
func (m *GetUsersRequest) String() string { return proto.CompactTextString(m) }
func (*GetUsersRequest) ProtoMessage() {}
func (*GetUsersRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_web_87670d45010119fa, []int{2}
}
func (m *GetUsersRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetUsersRequest.Unmarshal(m, b)
}
func (m *GetUsersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetUsersRequest.Marshal(b, m, deterministic)
}
func (dst *GetUsersRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetUsersRequest.Merge(dst, src)
}
func (m *GetUsersRequest) XXX_Size() int {
return xxx_messageInfo_GetUsersRequest.Size(m)
}
func (m *GetUsersRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetUsersRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetUsersRequest proto.InternalMessageInfo
func (m *GetUsersRequest) GetNumUsers() int64 {
if m != nil {
return m.NumUsers
}
return 0
}
func init() {
proto.RegisterType((*GetUserRequest)(nil), "web.GetUserRequest")
proto.RegisterType((*User)(nil), "web.User")
proto.RegisterType((*GetUsersRequest)(nil), "web.GetUsersRequest")
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -121,6 +160,7 @@ const _ = grpc.SupportPackageIsVersion4
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BackendClient interface {
GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*User, error)
GetUsers(ctx context.Context, in *GetUsersRequest, opts ...grpc.CallOption) (Backend_GetUsersClient, error)
}
type backendClient struct {
@@ -140,9 +180,42 @@ func (c *backendClient) GetUser(ctx context.Context, in *GetUserRequest, opts ..
return out, nil
}
func (c *backendClient) GetUsers(ctx context.Context, in *GetUsersRequest, opts ...grpc.CallOption) (Backend_GetUsersClient, error) {
stream, err := c.cc.NewStream(ctx, &_Backend_serviceDesc.Streams[0], "/web.Backend/GetUsers", opts...)
if err != nil {
return nil, err
}
x := &backendGetUsersClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Backend_GetUsersClient interface {
Recv() (*User, error)
grpc.ClientStream
}
type backendGetUsersClient struct {
grpc.ClientStream
}
func (x *backendGetUsersClient) Recv() (*User, error) {
m := new(User)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// BackendServer is the server API for Backend service.
type BackendServer interface {
GetUser(context.Context, *GetUserRequest) (*User, error)
GetUsers(*GetUsersRequest, Backend_GetUsersServer) error
}
func RegisterBackendServer(s *grpc.Server, srv BackendServer) {
@@ -167,6 +240,27 @@ func _Backend_GetUser_Handler(srv interface{}, ctx context.Context, dec func(int
return interceptor(ctx, in, info, handler)
}
func _Backend_GetUsers_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetUsersRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(BackendServer).GetUsers(m, &backendGetUsersServer{stream})
}
type Backend_GetUsersServer interface {
Send(*User) error
grpc.ServerStream
}
type backendGetUsersServer struct {
grpc.ServerStream
}
func (x *backendGetUsersServer) Send(m *User) error {
return x.ServerStream.SendMsg(m)
}
var _Backend_serviceDesc = grpc.ServiceDesc{
ServiceName: "web.Backend",
HandlerType: (*BackendServer)(nil),
@@ -176,25 +270,33 @@ var _Backend_serviceDesc = grpc.ServiceDesc{
Handler: _Backend_GetUser_Handler,
},
},
Streams: []grpc.StreamDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "GetUsers",
Handler: _Backend_GetUsers_Handler,
ServerStreams: true,
},
},
Metadata: "proto/web.proto",
}
func init() { proto.RegisterFile("proto/web.proto", fileDescriptor_web_19a831568a3bf959) }
func init() { proto.RegisterFile("proto/web.proto", fileDescriptor_web_87670d45010119fa) }
var fileDescriptor_web_19a831568a3bf959 = []byte{
// 197 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x28, 0xca, 0x2f,
0xc9, 0xd7, 0x2f, 0x4f, 0x4d, 0xd2, 0x03, 0xb3, 0x84, 0x98, 0xcb, 0x53, 0x93, 0x94, 0x34, 0xb9,
0xf8, 0xdc, 0x53, 0x4b, 0x42, 0x8b, 0x53, 0x8b, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84,
0xc4, 0xb9, 0xd8, 0x4b, 0x8b, 0x53, 0x8b, 0xe2, 0x33, 0x53, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38,
0x83, 0xd8, 0x40, 0x5c, 0xcf, 0x14, 0x25, 0x31, 0x2e, 0x16, 0x90, 0x3a, 0x21, 0x3e, 0x2e, 0x26,
0xb8, 0x1c, 0x53, 0x66, 0x8a, 0x91, 0x19, 0x17, 0xbb, 0x53, 0x62, 0x72, 0x76, 0x6a, 0x5e, 0x8a,
0x90, 0x36, 0x17, 0x3b, 0xd4, 0x34, 0x21, 0x61, 0x3d, 0x90, 0x4d, 0xa8, 0x66, 0x4b, 0x71, 0x82,
0x05, 0x41, 0x22, 0x4a, 0x0c, 0x4e, 0xf6, 0x51, 0xb6, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a,
0xc9, 0xf9, 0xb9, 0xfa, 0x59, 0xf9, 0x19, 0x89, 0x79, 0x49, 0x45, 0x89, 0x79, 0x29, 0x19, 0xf9,
0x45, 0xc5, 0x25, 0xfa, 0xe5, 0x89, 0xc5, 0xb9, 0xba, 0xa9, 0x15, 0x05, 0xa9, 0x45, 0x99, 0xb9,
0xa9, 0x79, 0x25, 0xc5, 0xfa, 0xe9, 0x45, 0x05, 0xc9, 0xfa, 0x10, 0x3f, 0x14, 0xa7, 0x16, 0x95,
0xa5, 0x16, 0x25, 0xb1, 0x81, 0x79, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x64, 0xf1,
0x41, 0xda, 0x00, 0x00, 0x00,
var fileDescriptor_web_87670d45010119fa = []byte{
// 236 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xc1, 0x4b, 0xc3, 0x30,
0x18, 0xc5, 0xdd, 0x26, 0xeb, 0xfa, 0x1d, 0x36, 0x88, 0xa2, 0xa2, 0x17, 0xe9, 0x49, 0x11, 0x1b,
0xd1, 0xb3, 0x08, 0xbb, 0x88, 0xd7, 0x82, 0x17, 0x2f, 0xa3, 0x69, 0x3e, 0xda, 0x2a, 0x49, 0xea,
0xf7, 0x25, 0xd6, 0x3f, 0x5f, 0x12, 0x37, 0x51, 0xf0, 0x96, 0xf7, 0xf2, 0x7b, 0x2f, 0x8f, 0xc0,
0x6a, 0x20, 0xe7, 0x9d, 0x1c, 0x51, 0x95, 0xe9, 0x24, 0x66, 0x23, 0xaa, 0xe2, 0x12, 0x96, 0x8f,
0xe8, 0x9f, 0x19, 0xa9, 0xc2, 0xf7, 0x80, 0xec, 0xc5, 0x31, 0x64, 0x81, 0x91, 0x36, 0xbd, 0x3e,
0x99, 0x9c, 0x4f, 0x2e, 0xf2, 0x6a, 0x1e, 0xe5, 0x93, 0x2e, 0x8e, 0x60, 0x3f, 0x72, 0x62, 0x09,
0xd3, 0x9f, 0xbb, 0x69, 0xaf, 0x8b, 0x12, 0x56, 0xdb, 0x0a, 0xde, 0x75, 0x9c, 0x41, 0x6e, 0x83,
0xd9, 0xc4, 0x20, 0x27, 0x72, 0x56, 0x2d, 0x6c, 0x30, 0x89, 0xb9, 0x6d, 0x21, 0x5b, 0xd7, 0xcd,
0x1b, 0x5a, 0x2d, 0xae, 0x20, 0xdb, 0x46, 0xc5, 0x41, 0x19, 0x97, 0xfd, 0xdd, 0x72, 0x9a, 0x27,
0x33, 0x3a, 0xc5, 0x9e, 0x90, 0xb0, 0xd8, 0xbd, 0x23, 0x0e, 0x7f, 0xd3, 0xfc, 0x1f, 0x7e, 0x33,
0x59, 0x3f, 0xbc, 0xdc, 0xb7, 0xbd, 0xef, 0x82, 0x2a, 0x1b, 0x67, 0xe4, 0xab, 0xeb, 0x6a, 0xab,
0xa8, 0xb6, 0xba, 0x73, 0xc4, 0x5e, 0x8e, 0x35, 0x9b, 0x6b, 0xfc, 0x1c, 0x90, 0x7a, 0x83, 0xd6,
0xb3, 0x6c, 0x69, 0x68, 0xe4, 0xf7, 0x27, 0x31, 0xd2, 0x07, 0x92, 0x9a, 0x27, 0x75, 0xf7, 0x15,
0x00, 0x00, 0xff, 0xff, 0x75, 0x28, 0x26, 0x8f, 0x3b, 0x01, 0x00, 0x00,
}

View File

@@ -8,6 +8,7 @@ option go_package = "github.com/johanbrandhorst/wasm-experiments/grpc/proto/serv
// Backend defines the interface exposed by the backend.
service Backend {
rpc GetUser(GetUserRequest) returns (User) {}
rpc GetUsers(GetUsersRequest) returns (stream User) {}
}
message GetUserRequest {
@@ -17,3 +18,7 @@ message GetUserRequest {
message User {
string id = 1;
}
message GetUsersRequest {
int64 num_users = 1;
}