mirror of
https://github.com/foomo/gotsrpc.git
synced 2025-10-16 12:35:35 +00:00
feat: update handling of servers & clients
This commit is contained in:
parent
d93b987eaf
commit
8cee3c7df9
35
client.go
35
client.go
@ -18,13 +18,12 @@ var _ Client = &bufferedClient{}
|
|||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Call(url string, endpoint string, method string, args []interface{}, reply []interface{}) (err error)
|
Call(url string, endpoint string, method string, args []interface{}, reply []interface{}) (err error)
|
||||||
|
SetEncoding(encoding ClientEncoding)
|
||||||
|
SetHttpClient(client *http.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(httpClient *http.Client) Client {
|
func NewClient() Client {
|
||||||
if httpClient == nil {
|
return &bufferedClient{client: http.DefaultClient, handle: getHandleForEncoding(EncodingMsgpack)}
|
||||||
httpClient = http.DefaultClient
|
|
||||||
}
|
|
||||||
return &bufferedClient{client: httpClient}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRequest(url string, contentType string, reader io.Reader) (r *http.Request, err error) {
|
func newRequest(url string, contentType string, reader io.Reader) (r *http.Request, err error) {
|
||||||
@ -32,21 +31,31 @@ func newRequest(url string, contentType string, reader io.Reader) (r *http.Reque
|
|||||||
if errRequest != nil {
|
if errRequest != nil {
|
||||||
return nil, errors.Wrap(errRequest, "could not create a request")
|
return nil, errors.Wrap(errRequest, "could not create a request")
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Header.Set("Content-Type", contentType)
|
request.Header.Set("Content-Type", contentType)
|
||||||
request.Header.Set("Accept", contentType)
|
request.Header.Set("Accept", contentType)
|
||||||
|
|
||||||
return request, nil
|
return request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type bufferedClient struct {
|
type bufferedClient struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
handle *clientHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *bufferedClient) SetEncoding(encoding ClientEncoding) {
|
||||||
|
c.handle = getHandleForEncoding(encoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *bufferedClient) SetHttpClient(client *http.Client) {
|
||||||
|
c.client = client
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallClient calls a method on the remove service
|
// CallClient calls a method on the remove service
|
||||||
func (c *bufferedClient) Call(url string, endpoint string, method string, args []interface{}, reply []interface{}) (err error) {
|
func (c *bufferedClient) Call(url string, endpoint string, method string, args []interface{}, reply []interface{}) (err error) {
|
||||||
// Marshall args
|
// Marshall args
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
errEncode := codec.NewEncoder(b, msgpackHandle).Encode(args)
|
errEncode := codec.NewEncoder(b, c.handle.handle).Encode(args)
|
||||||
if errEncode != nil {
|
if errEncode != nil {
|
||||||
return errors.Wrap(errEncode, "could not encode argument")
|
return errors.Wrap(errEncode, "could not encode argument")
|
||||||
}
|
}
|
||||||
@ -56,7 +65,7 @@ func (c *bufferedClient) Call(url string, endpoint string, method string, args [
|
|||||||
postURL := fmt.Sprintf("%s%s/%s", url, endpoint, method)
|
postURL := fmt.Sprintf("%s%s/%s", url, endpoint, method)
|
||||||
// Post
|
// Post
|
||||||
|
|
||||||
request, errRequest := newRequest(postURL, msgpackContentType, b)
|
request, errRequest := newRequest(postURL, c.handle.contentType, b)
|
||||||
if errRequest != nil {
|
if errRequest != nil {
|
||||||
return errRequest
|
return errRequest
|
||||||
}
|
}
|
||||||
@ -77,14 +86,8 @@ func (c *bufferedClient) Call(url string, endpoint string, method string, args [
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errDecode error
|
var errDecode error
|
||||||
switch resp.Header.Get("Content-Type") {
|
responseHandle := getHandlerForContentType(resp.Header.Get("Content-Type")).handle
|
||||||
case msgpackContentType:
|
errDecode = codec.NewDecoder(resp.Body, responseHandle).Decode(reply)
|
||||||
errDecode = codec.NewDecoder(resp.Body, msgpackHandle).Decode(reply)
|
|
||||||
case jsonContentType:
|
|
||||||
errDecode = codec.NewDecoder(resp.Body, jsonHandle).Decode(reply)
|
|
||||||
default:
|
|
||||||
errDecode = codec.NewDecoder(resp.Body, jsonHandle).Decode(reply)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal reply
|
// Unmarshal reply
|
||||||
if errDecode != nil {
|
if errDecode != nil {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
gotsrpc "github.com/foomo/gotsrpc"
|
gotsrpc "github.com/foomo/gotsrpc"
|
||||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
github_com_foomo_gotsrpc_demo_nested "github.com/foomo/gotsrpc/demo/nested"
|
||||||
gorpc "github.com/valyala/gorpc"
|
gorpc "github.com/valyala/gorpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -111,8 +111,8 @@ type (
|
|||||||
DemoGiveMeAScalarRequest struct {
|
DemoGiveMeAScalarRequest struct {
|
||||||
}
|
}
|
||||||
DemoGiveMeAScalarResponse struct {
|
DemoGiveMeAScalarResponse struct {
|
||||||
Amount nested.Amount
|
Amount github_com_foomo_gotsrpc_demo_nested.Amount
|
||||||
Wahr nested.True
|
Wahr github_com_foomo_gotsrpc_demo_nested.True
|
||||||
Hier ScalarInPlace
|
Hier ScalarInPlace
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ type (
|
|||||||
DemoNestRequest struct {
|
DemoNestRequest struct {
|
||||||
}
|
}
|
||||||
DemoNestResponse struct {
|
DemoNestResponse struct {
|
||||||
RetNest_0 []*nested.Nested
|
RetNest_0 []*github_com_foomo_gotsrpc_demo_nested.Nested
|
||||||
}
|
}
|
||||||
|
|
||||||
DemoTestScalarInPlaceRequest struct {
|
DemoTestScalarInPlaceRequest struct {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ package demo
|
|||||||
import (
|
import (
|
||||||
tls "crypto/tls"
|
tls "crypto/tls"
|
||||||
|
|
||||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
github_com_foomo_gotsrpc_demo_nested "github.com/foomo/gotsrpc/demo/nested"
|
||||||
gorpc "github.com/valyala/gorpc"
|
gorpc "github.com/valyala/gorpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ func (tsc *DemoGoRPCClient) ExtractAddress(person *Person) (addr *Address, e *Er
|
|||||||
return response.Addr, response.E, nil
|
return response.Addr, response.E, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tsc *DemoGoRPCClient) GiveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace, clientErr error) {
|
func (tsc *DemoGoRPCClient) GiveMeAScalar() (amount github_com_foomo_gotsrpc_demo_nested.Amount, wahr github_com_foomo_gotsrpc_demo_nested.True, hier ScalarInPlace, clientErr error) {
|
||||||
req := DemoGiveMeAScalarRequest{}
|
req := DemoGiveMeAScalarRequest{}
|
||||||
rpcCallRes, rpcCallErr := tsc.Client.Call(req)
|
rpcCallRes, rpcCallErr := tsc.Client.Call(req)
|
||||||
if rpcCallErr != nil {
|
if rpcCallErr != nil {
|
||||||
@ -129,7 +129,7 @@ func (tsc *DemoGoRPCClient) MapCrap() (crap map[string][]int, clientErr error) {
|
|||||||
return response.Crap, nil
|
return response.Crap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tsc *DemoGoRPCClient) Nest() (retNest_0 []*nested.Nested, clientErr error) {
|
func (tsc *DemoGoRPCClient) Nest() (retNest_0 []*github_com_foomo_gotsrpc_demo_nested.Nested, clientErr error) {
|
||||||
req := DemoNestRequest{}
|
req := DemoNestRequest{}
|
||||||
rpcCallRes, rpcCallErr := tsc.Client.Call(req)
|
rpcCallRes, rpcCallErr := tsc.Client.Call(req)
|
||||||
if rpcCallErr != nil {
|
if rpcCallErr != nil {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ package demo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
gotsrpc "github.com/foomo/gotsrpc"
|
gotsrpc "github.com/foomo/gotsrpc"
|
||||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
github_com_foomo_gotsrpc_demo_nested "github.com/foomo/gotsrpc/demo/nested"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FooGoTSRPCClient interface {
|
type FooGoTSRPCClient interface {
|
||||||
@ -25,7 +25,7 @@ func NewFooGoTSRPCClient(url string, endpoint string) FooGoTSRPCClient {
|
|||||||
return &tsrpcFooGoTSRPCClient{
|
return &tsrpcFooGoTSRPCClient{
|
||||||
URL: url,
|
URL: url,
|
||||||
EndPoint: endpoint,
|
EndPoint: endpoint,
|
||||||
Client: gotsrpc.NewClient(nil),
|
Client: gotsrpc.NewClient(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,17 +41,15 @@ func (tsc *tsrpcFooGoTSRPCClient) Hello(number int64) (retHello_0 int, clientErr
|
|||||||
|
|
||||||
type DemoGoTSRPCClient interface {
|
type DemoGoTSRPCClient interface {
|
||||||
ExtractAddress(person *Person) (addr *Address, e *Err, clientErr error)
|
ExtractAddress(person *Person) (addr *Address, e *Err, clientErr error)
|
||||||
GiveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace, clientErr error)
|
GiveMeAScalar() (amount github_com_foomo_gotsrpc_demo_nested.Amount, wahr github_com_foomo_gotsrpc_demo_nested.True, hier ScalarInPlace, clientErr error)
|
||||||
Hello(name string) (retHello_0 string, retHello_1 *Err, clientErr error)
|
Hello(name string) (retHello_0 string, retHello_1 *Err, clientErr error)
|
||||||
HelloInterface(anything interface{}, anythingMap map[string]interface{}, anythingSlice []interface{}) (clientErr error)
|
HelloInterface(anything interface{}, anythingMap map[string]interface{}, anythingSlice []interface{}) (clientErr error)
|
||||||
HelloScalarError() (err *ScalarError, clientErr error)
|
HelloScalarError() (err *ScalarError, clientErr error)
|
||||||
MapCrap() (crap map[string][]int, clientErr error)
|
MapCrap() (crap map[string][]int, clientErr error)
|
||||||
Nest() (retNest_0 []*nested.Nested, clientErr error)
|
Nest() (retNest_0 []*github_com_foomo_gotsrpc_demo_nested.Nested, clientErr error)
|
||||||
TestScalarInPlace() (retTestScalarInPlace_0 ScalarInPlace, clientErr error)
|
TestScalarInPlace() (retTestScalarInPlace_0 ScalarInPlace, clientErr error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ DemoGoTSRPCClient = &tsrpcDemoGoTSRPCClient{}
|
|
||||||
|
|
||||||
type tsrpcDemoGoTSRPCClient struct {
|
type tsrpcDemoGoTSRPCClient struct {
|
||||||
URL string
|
URL string
|
||||||
EndPoint string
|
EndPoint string
|
||||||
@ -66,7 +64,7 @@ func NewDemoGoTSRPCClient(url string, endpoint string) DemoGoTSRPCClient {
|
|||||||
return &tsrpcDemoGoTSRPCClient{
|
return &tsrpcDemoGoTSRPCClient{
|
||||||
URL: url,
|
URL: url,
|
||||||
EndPoint: endpoint,
|
EndPoint: endpoint,
|
||||||
Client: gotsrpc.NewClient(nil),
|
Client: gotsrpc.NewClient(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +78,7 @@ func (tsc *tsrpcDemoGoTSRPCClient) ExtractAddress(person *Person) (addr *Address
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tsc *tsrpcDemoGoTSRPCClient) GiveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace, clientErr error) {
|
func (tsc *tsrpcDemoGoTSRPCClient) GiveMeAScalar() (amount github_com_foomo_gotsrpc_demo_nested.Amount, wahr github_com_foomo_gotsrpc_demo_nested.True, hier ScalarInPlace, clientErr error) {
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
reply := []interface{}{&amount, &wahr, &hier}
|
reply := []interface{}{&amount, &wahr, &hier}
|
||||||
clientErr = tsc.Client.Call(tsc.URL, tsc.EndPoint, "GiveMeAScalar", args, reply)
|
clientErr = tsc.Client.Call(tsc.URL, tsc.EndPoint, "GiveMeAScalar", args, reply)
|
||||||
@ -115,7 +113,7 @@ func (tsc *tsrpcDemoGoTSRPCClient) MapCrap() (crap map[string][]int, clientErr e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tsc *tsrpcDemoGoTSRPCClient) Nest() (retNest_0 []*nested.Nested, clientErr error) {
|
func (tsc *tsrpcDemoGoTSRPCClient) Nest() (retNest_0 []*github_com_foomo_gotsrpc_demo_nested.Nested, clientErr error) {
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
reply := []interface{}{&retNest_0}
|
reply := []interface{}{&retNest_0}
|
||||||
clientErr = tsc.Client.Call(tsc.URL, tsc.EndPoint, "Nest", args, reply)
|
clientErr = tsc.Client.Call(tsc.URL, tsc.EndPoint, "Nest", args, reply)
|
||||||
|
|||||||
2
go.go
2
go.go
@ -433,7 +433,7 @@ func renderTSRPCServiceClients(services ServiceList, fullPackageName string, pac
|
|||||||
return &` + clientName + `{
|
return &` + clientName + `{
|
||||||
URL: url,
|
URL: url,
|
||||||
EndPoint: endpoint,
|
EndPoint: endpoint,
|
||||||
Client: gotsrpc.NewClient(nil),
|
Client: gotsrpc.NewClient(),
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
|
|||||||
28
gotsrpc.go
28
gotsrpc.go
@ -39,15 +39,9 @@ func ErrorMethodNotAllowed(w http.ResponseWriter) {
|
|||||||
|
|
||||||
func LoadArgs(args interface{}, callStats *CallStats, r *http.Request) error {
|
func LoadArgs(args interface{}, callStats *CallStats, r *http.Request) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
var errDecode error
|
|
||||||
switch r.Header.Get("Content-Type") {
|
|
||||||
case msgpackContentType:
|
|
||||||
errDecode = codec.NewDecoder(r.Body, msgpackHandle).Decode(args)
|
|
||||||
default:
|
|
||||||
errDecode = codec.NewDecoder(r.Body, jsonHandle).Decode(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errDecode != nil {
|
handle := getHandlerForContentType(r.Header.Get("Content-Type")).handle
|
||||||
|
if errDecode := codec.NewDecoder(r.Body, handle).Decode(args); errDecode != nil {
|
||||||
return errors.Wrap(errDecode, "could not decode arguments")
|
return errors.Wrap(errDecode, "could not decode arguments")
|
||||||
}
|
}
|
||||||
if callStats != nil {
|
if callStats != nil {
|
||||||
@ -85,21 +79,12 @@ func ClearStats(r *http.Request) {
|
|||||||
func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.ResponseWriter) {
|
func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.ResponseWriter) {
|
||||||
writer := newResponseWriterWithLength(w)
|
writer := newResponseWriterWithLength(w)
|
||||||
serializationStart := time.Now()
|
serializationStart := time.Now()
|
||||||
var errEncode error
|
|
||||||
|
|
||||||
switch r.Header.Get("Accept") {
|
clientHandle := getHandlerForContentType(r.Header.Get("Content-Type"))
|
||||||
case msgpackContentType:
|
|
||||||
writer.Header().Set("Content-Type", msgpackContentType)
|
|
||||||
errEncode = codec.NewEncoder(writer, msgpackHandle).Encode(response)
|
|
||||||
case jsonContentType:
|
|
||||||
writer.Header().Set("Content-Type", jsonContentType)
|
|
||||||
errEncode = codec.NewEncoder(writer, jsonHandle).Encode(response)
|
|
||||||
default:
|
|
||||||
writer.Header().Set("Content-Type", jsonContentType)
|
|
||||||
errEncode = codec.NewEncoder(writer, jsonHandle).Encode(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errEncode != nil {
|
writer.Header().Set("Content-Type", clientHandle.contentType)
|
||||||
|
|
||||||
|
if errEncode := codec.NewEncoder(writer, clientHandle.handle).Encode(response); errEncode != nil {
|
||||||
fmt.Println(errEncode)
|
fmt.Println(errEncode)
|
||||||
http.Error(w, "could not encode data to accepted format", http.StatusInternalServerError)
|
http.Error(w, "could not encode data to accepted format", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@ -109,7 +94,6 @@ func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.Res
|
|||||||
stats.ResponseSize = writer.length
|
stats.ResponseSize = writer.length
|
||||||
stats.Marshalling = time.Now().Sub(serializationStart)
|
stats.Marshalling = time.Now().Sub(serializationStart)
|
||||||
}
|
}
|
||||||
//writer.WriteHeader(http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDir(goPaths []string, packageName string) (map[string]*ast.Package, error) {
|
func parseDir(goPaths []string, packageName string) (map[string]*ast.Package, error) {
|
||||||
|
|||||||
54
transport.go
54
transport.go
@ -6,19 +6,53 @@ import (
|
|||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
type ClientEncoding int
|
||||||
msgpackHandle = &codec.MsgpackHandle{
|
|
||||||
RawToString: true,
|
const (
|
||||||
}
|
EncodingMsgpack = ClientEncoding(0)
|
||||||
msgpackContentType = "application/msgpack; charset=utf-8"
|
EncodingJson = ClientEncoding(1)
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
type clientHandle struct {
|
||||||
jsonHandle = &codec.JsonHandle{
|
handle codec.Handle
|
||||||
MapKeyAsString: true,
|
contentType string
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgpackClientHandle = &clientHandle{
|
||||||
|
handle: &codec.MsgpackHandle{
|
||||||
|
RawToString: true,
|
||||||
|
},
|
||||||
|
contentType: "application/msgpack; charset=utf-8",
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonClientHandle = &clientHandle{
|
||||||
|
handle: &codec.JsonHandle{
|
||||||
|
MapKeyAsString: true,
|
||||||
|
},
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHandleForEncoding(encoding ClientEncoding) *clientHandle {
|
||||||
|
switch encoding {
|
||||||
|
case EncodingMsgpack:
|
||||||
|
return msgpackClientHandle
|
||||||
|
case EncodingJson:
|
||||||
|
return jsonClientHandle
|
||||||
|
default:
|
||||||
|
return jsonClientHandle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHandlerForContentType(contentType string) *clientHandle {
|
||||||
|
switch contentType {
|
||||||
|
case msgpackClientHandle.contentType:
|
||||||
|
return msgpackClientHandle
|
||||||
|
case jsonClientHandle.contentType:
|
||||||
|
return jsonClientHandle
|
||||||
|
default:
|
||||||
|
return jsonClientHandle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
jsonContentType = "application/json; charset=utf-8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type responseWriterWithLength struct {
|
type responseWriterWithLength struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user