Working bidirectional streaming example
This commit is contained in:
		| @@ -63,6 +63,7 @@ func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.Ne | |||||||
| } | } | ||||||
|  |  | ||||||
| func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { | func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { | ||||||
|  | 	c.buf.wbuf.Reset() | ||||||
| 	m := &codec.Message{ | 	m := &codec.Message{ | ||||||
| 		Id:      req.Seq, | 		Id:      req.Seq, | ||||||
| 		Target:  req.Service, | 		Target:  req.Service, | ||||||
|   | |||||||
| @@ -50,7 +50,6 @@ func (r *rpcStream) Send(msg interface{}) error { | |||||||
| 		r.err = err | 		r.err = err | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,8 +54,9 @@ func call(i int) { | |||||||
| 	fmt.Println("Call:", i, "rsp:", rsp.Msg) | 	fmt.Println("Call:", i, "rsp:", rsp.Msg) | ||||||
| } | } | ||||||
|  |  | ||||||
| func stream() { | func stream(i int) { | ||||||
| 	// Create new request to service go.micro.srv.example, method Example.Call | 	// Create new request to service go.micro.srv.example, method Example.Call | ||||||
|  | 	// Request can be empty as its actually ignored and merely used to call the handler | ||||||
| 	req := client.NewRequest("go.micro.srv.example", "Example.Stream", &example.StreamingRequest{}) | 	req := client.NewRequest("go.micro.srv.example", "Example.Stream", &example.StreamingRequest{}) | ||||||
|  |  | ||||||
| 	stream, err := client.Stream(context.Background(), req) | 	stream, err := client.Stream(context.Background(), req) | ||||||
| @@ -63,7 +64,10 @@ func stream() { | |||||||
| 		fmt.Println("err:", err) | 		fmt.Println("err:", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	if err := stream.Send(&example.StreamingRequest{Count: int64(i)}); err != nil { | ||||||
|  | 		fmt.Println("err:", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	for stream.Error() == nil { | 	for stream.Error() == nil { | ||||||
| 		rsp := &example.StreamingResponse{} | 		rsp := &example.StreamingResponse{} | ||||||
| 		err := stream.Recv(rsp) | 		err := stream.Recv(rsp) | ||||||
| @@ -84,6 +88,41 @@ func stream() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func pingPong(i int) { | ||||||
|  | 	// Create new request to service go.micro.srv.example, method Example.Call | ||||||
|  | 	// Request can be empty as its actually ignored and merely used to call the handler | ||||||
|  | 	req := client.NewRequest("go.micro.srv.example", "Example.PingPong", &example.StreamingRequest{}) | ||||||
|  |  | ||||||
|  | 	stream, err := client.Stream(context.Background(), req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println("err:", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for j := 0; j < i; j++ { | ||||||
|  | 		if err := stream.Send(&example.Ping{Stroke: int64(j)}); err != nil { | ||||||
|  | 			fmt.Println("err:", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		rsp := &example.Pong{} | ||||||
|  | 		err := stream.Recv(rsp) | ||||||
|  | 		if err != nil { | ||||||
|  | 			fmt.Println("recv err", err) | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		fmt.Printf("Sent ping %v got pong %v\n", j, rsp.Stroke) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if stream.Error() != nil { | ||||||
|  | 		fmt.Println("stream err:", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := stream.Close(); err != nil { | ||||||
|  | 		fmt.Println("stream close err:", err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
| 	cmd.Init() | 	cmd.Init() | ||||||
| 	//	fmt.Println("\n--- Call example ---\n") | 	//	fmt.Println("\n--- Call example ---\n") | ||||||
| @@ -91,8 +130,11 @@ func main() { | |||||||
| 	//		call(i) | 	//		call(i) | ||||||
| 	//	} | 	//	} | ||||||
|  |  | ||||||
| 	fmt.Println("\n--- Streamer example ---\n") | 	//	fmt.Println("\n--- Streamer example ---\n") | ||||||
| 	stream() | 	//	stream(10) | ||||||
|  |  | ||||||
|  | 	fmt.Println("\n--- Ping Pong example ---\n") | ||||||
|  | 	pingPong(10) | ||||||
|  |  | ||||||
| 	//	fmt.Println("\n--- Publisher example ---\n") | 	//	fmt.Println("\n--- Publisher example ---\n") | ||||||
| 	//	pub() | 	//	pub() | ||||||
|   | |||||||
| @@ -42,3 +42,17 @@ func (e *Example) Stream(ctx context.Context, stream server.Streamer) error { | |||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (e *Example) PingPong(ctx context.Context, stream server.Streamer) error { | ||||||
|  | 	for { | ||||||
|  | 		req := &example.Ping{} | ||||||
|  | 		if err := stream.Recv(req); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		log.Infof("Got ping %v", req.Stroke) | ||||||
|  | 		if err := stream.Send(&example.Pong{Stroke: req.Stroke}); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,6 +14,8 @@ It has these top-level messages: | |||||||
| 	Response | 	Response | ||||||
| 	StreamingRequest | 	StreamingRequest | ||||||
| 	StreamingResponse | 	StreamingResponse | ||||||
|  | 	Ping | ||||||
|  | 	Pong | ||||||
| */ | */ | ||||||
| package go_micro_srv_example | package go_micro_srv_example | ||||||
|  |  | ||||||
| @@ -77,12 +79,32 @@ func (m *StreamingResponse) String() string            { return proto.CompactTex | |||||||
| func (*StreamingResponse) ProtoMessage()               {} | func (*StreamingResponse) ProtoMessage()               {} | ||||||
| func (*StreamingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } | func (*StreamingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } | ||||||
|  |  | ||||||
|  | type Ping struct { | ||||||
|  | 	Stroke int64 `protobuf:"varint,1,opt,name=stroke" json:"stroke,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Ping) Reset()                    { *m = Ping{} } | ||||||
|  | func (m *Ping) String() string            { return proto.CompactTextString(m) } | ||||||
|  | func (*Ping) ProtoMessage()               {} | ||||||
|  | func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } | ||||||
|  |  | ||||||
|  | type Pong struct { | ||||||
|  | 	Stroke int64 `protobuf:"varint,1,opt,name=stroke" json:"stroke,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *Pong) Reset()                    { *m = Pong{} } | ||||||
|  | func (m *Pong) String() string            { return proto.CompactTextString(m) } | ||||||
|  | func (*Pong) ProtoMessage()               {} | ||||||
|  | func (*Pong) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	proto.RegisterType((*Message)(nil), "go.micro.srv.example.Message") | 	proto.RegisterType((*Message)(nil), "go.micro.srv.example.Message") | ||||||
| 	proto.RegisterType((*Request)(nil), "go.micro.srv.example.Request") | 	proto.RegisterType((*Request)(nil), "go.micro.srv.example.Request") | ||||||
| 	proto.RegisterType((*Response)(nil), "go.micro.srv.example.Response") | 	proto.RegisterType((*Response)(nil), "go.micro.srv.example.Response") | ||||||
| 	proto.RegisterType((*StreamingRequest)(nil), "go.micro.srv.example.StreamingRequest") | 	proto.RegisterType((*StreamingRequest)(nil), "go.micro.srv.example.StreamingRequest") | ||||||
| 	proto.RegisterType((*StreamingResponse)(nil), "go.micro.srv.example.StreamingResponse") | 	proto.RegisterType((*StreamingResponse)(nil), "go.micro.srv.example.StreamingResponse") | ||||||
|  | 	proto.RegisterType((*Ping)(nil), "go.micro.srv.example.Ping") | ||||||
|  | 	proto.RegisterType((*Pong)(nil), "go.micro.srv.example.Pong") | ||||||
| } | } | ||||||
|  |  | ||||||
| // Reference imports to suppress errors if they are not otherwise used. | // Reference imports to suppress errors if they are not otherwise used. | ||||||
| @@ -95,6 +117,7 @@ var _ server.Option | |||||||
| type ExampleClient interface { | type ExampleClient interface { | ||||||
| 	Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) | 	Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) | ||||||
| 	Stream(ctx context.Context, in *StreamingRequest, opts ...client.CallOption) (Example_StreamClient, error) | 	Stream(ctx context.Context, in *StreamingRequest, opts ...client.CallOption) (Example_StreamClient, error) | ||||||
|  | 	PingPong(ctx context.Context, in *Ping, opts ...client.CallOption) (Example_PingPongClient, error) | ||||||
| } | } | ||||||
|  |  | ||||||
| type exampleClient struct { | type exampleClient struct { | ||||||
| @@ -152,11 +175,44 @@ func (x *exampleStreamClient) RecvMsg() (*StreamingResponse, error) { | |||||||
| 	return m, nil | 	return m, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *exampleClient) PingPong(ctx context.Context, in *Ping, opts ...client.CallOption) (Example_PingPongClient, error) { | ||||||
|  | 	req := c.c.NewRequest(c.serviceName, "Example.PingPong", in) | ||||||
|  | 	stream, err := c.c.Stream(ctx, req, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &examplePingPongClient{stream}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Example_PingPongClient interface { | ||||||
|  | 	SendMsg(*Ping) error | ||||||
|  | 	RecvMsg() (*Pong, error) | ||||||
|  | 	client.Streamer | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type examplePingPongClient struct { | ||||||
|  | 	client.Streamer | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *examplePingPongClient) SendMsg(m *Ping) error { | ||||||
|  | 	return x.Send(m) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *examplePingPongClient) RecvMsg() (*Pong, error) { | ||||||
|  | 	m := new(Pong) | ||||||
|  | 	err := x.Recv(m) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return m, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Server API for Example service | // Server API for Example service | ||||||
|  |  | ||||||
| type ExampleHandler interface { | type ExampleHandler interface { | ||||||
| 	Call(context.Context, *Request, *Response) error | 	Call(context.Context, *Request, *Response) error | ||||||
| 	Stream(context.Context, func(*StreamingResponse) error) error | 	Stream(context.Context, func(*StreamingResponse) error) error | ||||||
|  | 	PingPong(context.Context, func(*Pong) error) error | ||||||
| } | } | ||||||
|  |  | ||||||
| func RegisterExampleHandler(s server.Server, hdlr ExampleHandler) { | func RegisterExampleHandler(s server.Server, hdlr ExampleHandler) { | ||||||
| @@ -164,20 +220,22 @@ func RegisterExampleHandler(s server.Server, hdlr ExampleHandler) { | |||||||
| } | } | ||||||
|  |  | ||||||
| var fileDescriptor0 = []byte{ | var fileDescriptor0 = []byte{ | ||||||
| 	// 230 bytes of a gzipped FileDescriptorProto | 	// 270 bytes of a gzipped FileDescriptorProto | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x90, 0xcd, 0x4a, 0xc5, 0x30, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x91, 0x5f, 0x4b, 0xc3, 0x30, | ||||||
| 	0x10, 0x85, 0x0d, 0xf7, 0x7a, 0xab, 0xa3, 0x82, 0x06, 0x51, 0x29, 0x28, 0x9a, 0x85, 0xba, 0x31, | 	0x14, 0xc5, 0x17, 0x56, 0xdb, 0x79, 0xfd, 0x83, 0x06, 0x99, 0x52, 0x50, 0x34, 0x0f, 0xba, 0x17, | ||||||
| 	0x15, 0xf5, 0x0d, 0x44, 0x5c, 0xb9, 0xa9, 0x6b, 0x17, 0xb1, 0x0c, 0xa1, 0xd0, 0x24, 0x35, 0x93, | 	0xd3, 0xa1, 0x7e, 0x03, 0x11, 0x7d, 0x11, 0x64, 0x3e, 0xfb, 0x10, 0xc7, 0x25, 0x0c, 0x9b, 0xa6, | ||||||
| 	0x16, 0x7d, 0x2c, 0xdf, 0x50, 0x48, 0xd3, 0xa2, 0x52, 0x71, 0x15, 0x98, 0xf3, 0x9d, 0x1f, 0x02, | 	0xe6, 0x66, 0x43, 0x3f, 0xbb, 0x2f, 0x6e, 0x69, 0x3b, 0xc6, 0xec, 0xf0, 0x29, 0x70, 0x7e, 0xe7, | ||||||
| 	0x77, 0xda, 0x5d, 0x99, 0xba, 0xf2, 0xae, 0xc0, 0x77, 0x65, 0xda, 0x06, 0xa9, 0x20, 0xf4, 0x3d, | 	0x5c, 0xce, 0x21, 0x70, 0xa7, 0xed, 0xb5, 0x99, 0x8c, 0x9d, 0xcd, 0xf0, 0x4b, 0x99, 0x32, 0x47, | ||||||
| 	0xfa, 0xa2, 0xf5, 0x2e, 0x4c, 0xd7, 0xf1, 0x95, 0xf1, 0xca, 0xf7, 0xb5, 0x93, 0xd1, 0x25, 0xc9, | 	0xca, 0x08, 0xdd, 0x0c, 0x5d, 0x56, 0x3a, 0xeb, 0x97, 0x6a, 0xf3, 0xca, 0xa0, 0xf2, 0x23, 0x6d, | ||||||
| 	0xf7, 0x32, 0x69, 0xe2, 0x00, 0xb2, 0x27, 0x24, 0x52, 0x1a, 0xf9, 0x16, 0x2c, 0x48, 0x7d, 0x1c, | 	0x65, 0x48, 0x49, 0x72, 0x33, 0x59, 0x33, 0xd1, 0x87, 0xe4, 0x19, 0x89, 0x94, 0x46, 0xbe, 0x03, | ||||||
| 	0xb1, 0x53, 0x76, 0xb9, 0x29, 0x0e, 0x21, 0x2b, 0xf1, 0xad, 0x43, 0x0a, 0x7c, 0x1b, 0x96, 0x56, | 	0x5d, 0x52, 0xdf, 0x27, 0xec, 0x9c, 0x0d, 0xb6, 0xc5, 0x31, 0x24, 0x23, 0xfc, 0x9c, 0x22, 0x79, | ||||||
| 	0x19, 0x9c, 0x84, 0x8d, 0x12, 0xa9, 0x75, 0x96, 0xa2, 0xc3, 0x90, 0x4e, 0xc2, 0x19, 0xec, 0x3e, | 	0xbe, 0x0b, 0x51, 0xa1, 0x0c, 0x2e, 0x41, 0x6f, 0x84, 0x54, 0xda, 0x82, 0x42, 0xc2, 0x90, 0xae, | ||||||
| 	0x07, 0x8f, 0xca, 0xd4, 0x56, 0x8f, 0xd6, 0x1d, 0x58, 0xaf, 0x5c, 0x67, 0x43, 0x44, 0x16, 0x42, | 	0xc1, 0x05, 0x1c, 0xbc, 0x7a, 0x87, 0xca, 0x4c, 0x0a, 0xdd, 0x44, 0xf7, 0x60, 0x6b, 0x6c, 0xa7, | ||||||
| 	0xc0, 0xde, 0x37, 0x24, 0x85, 0xfc, 0x64, 0x6e, 0x3e, 0x19, 0x64, 0x0f, 0xc3, 0x38, 0xfe, 0x08, | 	0x85, 0x0f, 0x96, 0xae, 0x10, 0x70, 0xb8, 0x62, 0xa9, 0x8f, 0xac, 0x79, 0xfa, 0x10, 0xbd, 0xcc, | ||||||
| 	0xcb, 0x7b, 0xd5, 0x34, 0xfc, 0x58, 0xce, 0x6d, 0x97, 0xa9, 0x25, 0x3f, 0xf9, 0x4b, 0x1e, 0x1a, | 	0x31, 0xdf, 0x87, 0x98, 0xbc, 0xb3, 0x1f, 0xb8, 0xa2, 0xdb, 0xbf, 0xfa, 0xcd, 0x0f, 0x83, 0xe4, | ||||||
| 	0xc4, 0x1a, 0x7f, 0x81, 0xd5, 0x50, 0xcc, 0xcf, 0xe7, 0xd9, 0xdf, 0xcb, 0xf3, 0x8b, 0x7f, 0xb9, | 	0xa1, 0x1a, 0xc3, 0x1f, 0x21, 0xba, 0x57, 0x79, 0xce, 0x4f, 0x65, 0xdb, 0x56, 0x59, 0xb7, 0x4a, | ||||||
| 	0x31, 0xfc, 0x9a, 0xbd, 0xae, 0xe2, 0x0f, 0xdf, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x63, 0x02, | 	0xcf, 0x36, 0xe1, 0xaa, 0x91, 0xe8, 0xf0, 0x37, 0x88, 0xab, 0xa2, 0xfc, 0xb2, 0xdd, 0xbb, 0xbe, | ||||||
| 	0xbf, 0x5f, 0x99, 0x01, 0x00, 0x00, | 	0x34, 0xbd, 0xfa, 0xd7, 0xd7, 0x1c, 0x1f, 0x32, 0xfe, 0x04, 0xbd, 0xc5, 0xc6, 0xb0, 0x27, 0x6d, | ||||||
|  | 	0x0f, 0x2e, 0x78, 0xba, 0x89, 0xcd, 0x73, 0xa2, 0x33, 0x60, 0x43, 0xf6, 0x1e, 0x87, 0xbf, 0xbd, | ||||||
|  | 	0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x53, 0xb5, 0xeb, 0x31, 0x13, 0x02, 0x00, 0x00, | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ package go.micro.srv.example; | |||||||
| service Example { | service Example { | ||||||
| 	rpc Call(Request) returns (Response) {} | 	rpc Call(Request) returns (Response) {} | ||||||
| 	rpc Stream(StreamingRequest) returns (stream StreamingResponse) {} | 	rpc Stream(StreamingRequest) returns (stream StreamingResponse) {} | ||||||
|  | 	rpc PingPong(stream Ping) returns (stream Pong) {} | ||||||
| } | } | ||||||
|  |  | ||||||
| message Message { | message Message { | ||||||
| @@ -26,3 +27,11 @@ message StreamingRequest { | |||||||
| message StreamingResponse { | message StreamingResponse { | ||||||
| 	int64 count = 1; | 	int64 count = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | message Ping { | ||||||
|  | 	int64 stroke = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message Pong { | ||||||
|  | 	int64 stroke = 1; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -60,9 +60,20 @@ func newRpcPlusCodec(req *transport.Message, socket transport.Socket, c codec.Ne | |||||||
| 	return r | 	return r | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *rpcPlusCodec) ReadRequestHeader(r *request) error { | func (c *rpcPlusCodec) ReadRequestHeader(r *request, first bool) error { | ||||||
| 	m := codec.Message{ | 	m := codec.Message{Headers: c.req.Header} | ||||||
| 		Headers: c.req.Header, |  | ||||||
|  | 	if !first { | ||||||
|  | 		var tm transport.Message | ||||||
|  | 		if err := c.socket.Recv(&tm); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		c.buf.rbuf.Reset() | ||||||
|  | 		if _, err := c.buf.rbuf.Write(tm.Body); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		m.Headers = tm.Header | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err := c.codec.ReadHeader(&m, codec.Request) | 	err := c.codec.ReadHeader(&m, codec.Request) | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ func (r *rpcStream) Recv(msg interface{}) error { | |||||||
|  |  | ||||||
| 	req := request{} | 	req := request{} | ||||||
|  |  | ||||||
| 	if err := r.codec.ReadRequestHeader(&req); err != nil { | 	if err := r.codec.ReadRequestHeader(&req, false); err != nil { | ||||||
| 		// discard body | 		// discard body | ||||||
| 		r.codec.ReadRequestBody(nil) | 		r.codec.ReadRequestBody(nil) | ||||||
| 		return err | 		return err | ||||||
|   | |||||||
| @@ -389,7 +389,6 @@ func (server *server) readRequest(codec serverCodec) (service *service, mtype *m | |||||||
| 		codec.ReadRequestBody(nil) | 		codec.ReadRequestBody(nil) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// is it a streaming request? then we don't read the body | 	// is it a streaming request? then we don't read the body | ||||||
| 	if mtype.stream { | 	if mtype.stream { | ||||||
| 		codec.ReadRequestBody(nil) | 		codec.ReadRequestBody(nil) | ||||||
| @@ -421,7 +420,7 @@ func (server *server) readRequest(codec serverCodec) (service *service, mtype *m | |||||||
| func (server *server) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { | func (server *server) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { | ||||||
| 	// Grab the request header. | 	// Grab the request header. | ||||||
| 	req = server.getRequest() | 	req = server.getRequest() | ||||||
| 	err = codec.ReadRequestHeader(req) | 	err = codec.ReadRequestHeader(req, true) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		req = nil | 		req = nil | ||||||
| 		if err == io.EOF || err == io.ErrUnexpectedEOF { | 		if err == io.EOF || err == io.ErrUnexpectedEOF { | ||||||
| @@ -456,7 +455,7 @@ func (server *server) readRequestHeader(codec serverCodec) (service *service, mt | |||||||
| } | } | ||||||
|  |  | ||||||
| type serverCodec interface { | type serverCodec interface { | ||||||
| 	ReadRequestHeader(*request) error | 	ReadRequestHeader(*request, bool) error | ||||||
| 	ReadRequestBody(interface{}) error | 	ReadRequestBody(interface{}) error | ||||||
| 	WriteResponse(*response, interface{}, bool) error | 	WriteResponse(*response, interface{}, bool) error | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,16 +23,21 @@ type httpTransportClient struct { | |||||||
| 	addr     string | 	addr     string | ||||||
| 	conn     net.Conn | 	conn     net.Conn | ||||||
| 	dialOpts dialOptions | 	dialOpts dialOptions | ||||||
| 	r        chan *http.Request |  | ||||||
| 	once     sync.Once | 	once     sync.Once | ||||||
|  |  | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
|  | 	r    chan *http.Request | ||||||
|  | 	bl   []*http.Request | ||||||
| 	buff *bufio.Reader | 	buff *bufio.Reader | ||||||
| } | } | ||||||
|  |  | ||||||
| type httpTransportSocket struct { | type httpTransportSocket struct { | ||||||
| 	r    *http.Request | 	r    chan *http.Request | ||||||
| 	conn net.Conn | 	conn net.Conn | ||||||
|  | 	once sync.Once | ||||||
|  |  | ||||||
|  | 	sync.Mutex | ||||||
|  | 	buff *bufio.Reader | ||||||
| } | } | ||||||
|  |  | ||||||
| type httpTransportListener struct { | type httpTransportListener struct { | ||||||
| @@ -68,7 +73,14 @@ func (h *httpTransportClient) Send(m *Message) error { | |||||||
| 		Host:          h.addr, | 		Host:          h.addr, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	h.r <- req | 	h.Lock() | ||||||
|  | 	h.bl = append(h.bl, req) | ||||||
|  | 	select { | ||||||
|  | 	case h.r <- h.bl[0]: | ||||||
|  | 		h.bl = h.bl[1:] | ||||||
|  | 	default: | ||||||
|  | 	} | ||||||
|  | 	h.Unlock() | ||||||
|  |  | ||||||
| 	return req.Write(h.conn) | 	return req.Write(h.conn) | ||||||
| } | } | ||||||
| @@ -134,17 +146,23 @@ func (h *httpTransportSocket) Recv(m *Message) error { | |||||||
| 		return errors.New("message passed in is nil") | 		return errors.New("message passed in is nil") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	b, err := ioutil.ReadAll(h.r.Body) | 	r, err := http.ReadRequest(h.buff) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	h.r.Body.Close() |  | ||||||
|  | 	b, err := ioutil.ReadAll(r.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	r.Body.Close() | ||||||
|  |  | ||||||
| 	mr := &Message{ | 	mr := &Message{ | ||||||
| 		Header: make(map[string]string), | 		Header: make(map[string]string), | ||||||
| 		Body:   b, | 		Body:   b, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for k, v := range h.r.Header { | 	for k, v := range r.Header { | ||||||
| 		if len(v) > 0 { | 		if len(v) > 0 { | ||||||
| 			mr.Header[k] = v[0] | 			mr.Header[k] = v[0] | ||||||
| 		} else { | 		} else { | ||||||
| @@ -152,6 +170,11 @@ func (h *httpTransportSocket) Recv(m *Message) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case h.r <- r: | ||||||
|  | 	default: | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	*m = *mr | 	*m = *mr | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -159,8 +182,11 @@ func (h *httpTransportSocket) Recv(m *Message) error { | |||||||
| func (h *httpTransportSocket) Send(m *Message) error { | func (h *httpTransportSocket) Send(m *Message) error { | ||||||
| 	b := bytes.NewBuffer(m.Body) | 	b := bytes.NewBuffer(m.Body) | ||||||
| 	defer b.Reset() | 	defer b.Reset() | ||||||
|  |  | ||||||
|  | 	r := <-h.r | ||||||
|  |  | ||||||
| 	rsp := &http.Response{ | 	rsp := &http.Response{ | ||||||
| 		Header:        h.r.Header, | 		Header:        r.Header, | ||||||
| 		Body:          &buffer{b}, | 		Body:          &buffer{b}, | ||||||
| 		Status:        "200 OK", | 		Status:        "200 OK", | ||||||
| 		StatusCode:    200, | 		StatusCode:    200, | ||||||
| @@ -174,6 +200,11 @@ func (h *httpTransportSocket) Send(m *Message) error { | |||||||
| 		rsp.Header.Set(k, v) | 		rsp.Header.Set(k, v) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case h.r <- r: | ||||||
|  | 	default: | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return rsp.Write(h.conn) | 	return rsp.Write(h.conn) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -199,7 +230,14 @@ func (h *httpTransportSocket) error(m *Message) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (h *httpTransportSocket) Close() error { | func (h *httpTransportSocket) Close() error { | ||||||
| 	return h.conn.Close() | 	err := h.conn.Close() | ||||||
|  | 	h.once.Do(func() { | ||||||
|  | 		h.Lock() | ||||||
|  | 		h.buff.Reset(nil) | ||||||
|  | 		h.buff = nil | ||||||
|  | 		h.Unlock() | ||||||
|  | 	}) | ||||||
|  | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (h *httpTransportListener) Addr() string { | func (h *httpTransportListener) Addr() string { | ||||||
| @@ -211,18 +249,19 @@ func (h *httpTransportListener) Close() error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (h *httpTransportListener) Accept(fn func(Socket)) error { | func (h *httpTransportListener) Accept(fn func(Socket)) error { | ||||||
| 	srv := &http.Server{ | 	for { | ||||||
| 		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 		c, err := h.listener.Accept() | ||||||
| 			conn, _, err := w.(http.Hijacker).Hijack() |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 				return | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		sock := &httpTransportSocket{ | 		sock := &httpTransportSocket{ | ||||||
| 				conn: conn, | 			conn: c, | ||||||
| 				r:    r, | 			buff: bufio.NewReader(c), | ||||||
|  | 			r:    make(chan *http.Request, 1), | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		go func() { | ||||||
| 			// TODO: think of a better error response strategy | 			// TODO: think of a better error response strategy | ||||||
| 			defer func() { | 			defer func() { | ||||||
| 				if r := recover(); r != nil { | 				if r := recover(); r != nil { | ||||||
| @@ -231,10 +270,9 @@ func (h *httpTransportListener) Accept(fn func(Socket)) error { | |||||||
| 			}() | 			}() | ||||||
|  |  | ||||||
| 			fn(sock) | 			fn(sock) | ||||||
| 		}), | 		}() | ||||||
| 	} | 	} | ||||||
|  | 	return nil | ||||||
| 	return srv.Serve(h.listener) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { | func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user