mirror of
https://github.com/foomo/gotsrpc.git
synced 2025-10-16 12:35:35 +00:00
merged arg casting
This commit is contained in:
commit
6da67fa249
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
.*
|
||||
!.git*
|
||||
|
||||
/vendor/
|
||||
|
||||
5
Makefile
5
Makefile
@ -1,3 +1,8 @@
|
||||
|
||||
.PHONY: demo
|
||||
demo:
|
||||
cd demo && gotsrpc -skipgotsrpc config.yml
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
GOBIN=/usr/local/bin go install cmd/gotsrpc/gotsrpc.go
|
||||
95
build.go
95
build.go
@ -7,11 +7,11 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"path/filepath"
|
||||
|
||||
"github.com/foomo/gotsrpc/config"
|
||||
)
|
||||
|
||||
@ -55,26 +55,36 @@ func Build(conf *config.Config, goPath string) {
|
||||
mappedTypeScript := map[string]map[string]*code{}
|
||||
for name, target := range conf.Targets {
|
||||
fmt.Fprintln(os.Stderr, "building target", name)
|
||||
|
||||
longPackageName := target.Package
|
||||
longPackageNameParts := strings.Split(longPackageName, "/")
|
||||
goFilename := path.Join(goPath, "src", longPackageName, "gotsrpc.go")
|
||||
goRPCProxiesFilename := path.Join(goPath, "src", longPackageName, "gorpc.go")
|
||||
goRPCClientsFilename := path.Join(goPath, "src", longPackageName, "gorpcclient.go")
|
||||
goTSRPCProxiesFilename := path.Join(goPath, "src", longPackageName, "gotsrpc.go")
|
||||
goTSRPCClientsFilename := path.Join(goPath, "src", longPackageName, "gotsrpcclient.go")
|
||||
|
||||
_, err := os.Stat(goFilename)
|
||||
if err == nil {
|
||||
fmt.Fprintln(os.Stderr, " removing existing", goFilename)
|
||||
os.Remove(goFilename)
|
||||
remove := func(filename string) {
|
||||
_, err := os.Stat(filename)
|
||||
if err == nil {
|
||||
fmt.Fprintln(os.Stderr, " removing existing", filename)
|
||||
os.Remove(filename)
|
||||
}
|
||||
}
|
||||
remove(goRPCProxiesFilename)
|
||||
remove(goRPCClientsFilename)
|
||||
remove(goTSRPCProxiesFilename)
|
||||
remove(goTSRPCClientsFilename)
|
||||
|
||||
packageName := longPackageNameParts[len(longPackageNameParts)-1]
|
||||
|
||||
services, structs, scalarTypes, constants, err := Read(goPath, longPackageName, target.Services)
|
||||
goPaths := []string{goPath, runtime.GOROOT()}
|
||||
services, structs, scalarTypes, constants, err := Read(goPaths, longPackageName, target.Services)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, " an error occured while trying to understand your code", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
ts, err := RenderTypeScriptServices(conf.ModuleKind, services, conf.Mappings, scalarTypes, target.TypeScriptModule)
|
||||
ts, err := RenderTypeScriptServices(conf.ModuleKind, services, conf.Mappings, scalarTypes, target)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate ts code", err)
|
||||
os.Exit(3)
|
||||
@ -98,25 +108,64 @@ func Build(conf *config.Config, goPath string) {
|
||||
os.Exit(4)
|
||||
}
|
||||
|
||||
gocode, goerr := RenderGo(services, longPackageName, packageName)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate go code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
formatAndWrite := func(code string, filename string) {
|
||||
formattedGoBytes, formattingError := format.Source([]byte(code))
|
||||
if formattingError == nil {
|
||||
code = string(formattedGoBytes)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, " could not format go ts rpc proxies code", formattingError)
|
||||
}
|
||||
|
||||
writeErr := ioutil.WriteFile(filename, []byte(code), 0644)
|
||||
if writeErr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not write go source to file", writeErr)
|
||||
os.Exit(5)
|
||||
}
|
||||
}
|
||||
if len(target.TSRPC) > 0 {
|
||||
goTSRPCProxiesCode, goerr := RenderGoTSRPCProxies(services, longPackageName, packageName, target)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate go ts rpc proxies code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
}
|
||||
formatAndWrite(goTSRPCProxiesCode, goTSRPCProxiesFilename)
|
||||
|
||||
goTSRPCClientsCode, goerr := RenderGoTSRPCClients(services, longPackageName, packageName, target)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate go ts rpc clients code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
}
|
||||
formatAndWrite(goTSRPCClientsCode, goTSRPCClientsFilename)
|
||||
}
|
||||
|
||||
formattedGoBytes, formattingError := format.Source([]byte(gocode))
|
||||
if formattingError == nil {
|
||||
gocode = string(formattedGoBytes)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, " could not format go code", formattingError)
|
||||
if len(target.GoRPC) > 0 {
|
||||
goRPCProxiesCode, goerr := RenderGoRPCProxies(services, longPackageName, packageName, target)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate go rpc proxies code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
}
|
||||
formatAndWrite(goRPCProxiesCode, goRPCProxiesFilename)
|
||||
|
||||
goRPCClientsCode, goerr := RenderGoRPCClients(services, longPackageName, packageName, target)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate go rpc clients code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
}
|
||||
formatAndWrite(goRPCClientsCode, goRPCClientsFilename)
|
||||
}
|
||||
|
||||
writeErr := ioutil.WriteFile(goFilename, []byte(gocode), 0644)
|
||||
if writeErr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not write go source to file", writeErr)
|
||||
os.Exit(5)
|
||||
if len(target.PHPRPC) > 0 {
|
||||
phpRPCClientsCode, goerr := RenderPHPRPCClients(services, target)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, " could not generate php rpc clients code in target", name, goerr)
|
||||
os.Exit(4)
|
||||
}
|
||||
for filename, code := range phpRPCClientsCode {
|
||||
updateCode(filename, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// spew.Dump(mappedTypeScript)
|
||||
for goPackage, mappedStructsMap := range mappedTypeScript {
|
||||
mapping, ok := conf.Mappings[goPackage]
|
||||
|
||||
50
client.go
Normal file
50
client.go
Normal file
@ -0,0 +1,50 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ClientTransport to use for calls
|
||||
var ClientTransport = &http.Transport{}
|
||||
|
||||
// CallClient calls a method on the remove service
|
||||
func CallClient(url string, endpoint string, method string, args []interface{}, reply []interface{}) error {
|
||||
// Marshall args
|
||||
jsonArgs := []string{}
|
||||
for _, value := range args {
|
||||
jsonArg, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jsonArgs = append(jsonArgs, string(jsonArg))
|
||||
}
|
||||
// Create request
|
||||
request := "[" + strings.Join(jsonArgs, ",") + "]"
|
||||
// Create post url
|
||||
postURL := fmt.Sprintf("%s%s/%s", url, endpoint, method)
|
||||
// Post
|
||||
client := &http.Client{Transport: ClientTransport}
|
||||
resp, err := client.Post(postURL, "application/json", strings.NewReader(request))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// Read in body
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check status
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("%s: %s", resp.Status, string(body))
|
||||
}
|
||||
// Unmarshal reply
|
||||
if err := json.Unmarshal(body, &reply); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -39,7 +39,7 @@ func serveFile(name string, w http.ResponseWriter) {
|
||||
|
||||
func main() {
|
||||
d := &Demo{
|
||||
proxy: demo.NewServiceGoTSRPCProxy(&demo.Service{}, "/service"),
|
||||
proxy: demo.NewServiceGoTSRPCProxy(&demo.Demo{}, "/service"),
|
||||
}
|
||||
fmt.Println(http.ListenAndServe(":8080", d))
|
||||
}
|
||||
|
||||
@ -8,11 +8,52 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type PHPTarget struct {
|
||||
Out string `yaml:"out"`
|
||||
Namespace string `yaml:"namespace"`
|
||||
}
|
||||
|
||||
type Target struct {
|
||||
Package string
|
||||
Services map[string]string
|
||||
TypeScriptModule string `yaml:"module"`
|
||||
Out string
|
||||
Package string `yaml:"package"`
|
||||
Services map[string]string `yaml:"services"`
|
||||
TypeScriptModule string `yaml:"module"`
|
||||
Out string `yaml:"out"`
|
||||
GoRPC []string `yaml:"gorpc"`
|
||||
TSRPC []string `yaml:"tsrpc"`
|
||||
PHPRPC map[string]*PHPTarget `yaml:"phprpc"`
|
||||
}
|
||||
|
||||
func (t *Target) IsGoRPC(service string) bool {
|
||||
for _, value := range t.GoRPC {
|
||||
if value == service {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Target) IsTSRPC(service string) bool {
|
||||
if len(t.TSRPC) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, value := range t.TSRPC {
|
||||
if value == service {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Target) IsPHPRPC(service string) bool {
|
||||
if len(t.PHPRPC) == 0 {
|
||||
return false
|
||||
}
|
||||
_, ok := t.PHPRPC[service]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (t *Target) GetPHPTarget(service string) *PHPTarget {
|
||||
return t.PHPRPC[service]
|
||||
}
|
||||
|
||||
type Mapping struct {
|
||||
|
||||
@ -3,9 +3,14 @@ targets:
|
||||
demo:
|
||||
module: GoTSRPC.Demo
|
||||
services:
|
||||
- Service
|
||||
/service/foo: Foo
|
||||
/service/demo: Demo
|
||||
package: github.com/foomo/gotsrpc/demo
|
||||
out: /tmp/test.ts
|
||||
out: /tmp/test.ts
|
||||
gorpc:
|
||||
- Foo
|
||||
- Demo
|
||||
|
||||
mappings:
|
||||
github.com/foomo/gotsrpc/demo:
|
||||
module: GoTSRPC.Demo
|
||||
|
||||
10
demo/demo.go
10
demo/demo.go
@ -6,21 +6,17 @@ type Err struct {
|
||||
|
||||
type ScalarInPlace string
|
||||
|
||||
type Service struct {
|
||||
type Demo struct {
|
||||
Bla bool
|
||||
}
|
||||
|
||||
func (s *Service) Hello(name string) (reply string, err *Err) {
|
||||
func (d *Demo) Hello(name string) (reply string, err *Err) {
|
||||
if name == "Peter" {
|
||||
return "", &Err{"fuck you Peter I do not like you"}
|
||||
}
|
||||
return "Hello from the server: " + name, nil
|
||||
}
|
||||
|
||||
func sepp(bar bool) string {
|
||||
return "ich bin der sepp"
|
||||
}
|
||||
|
||||
func (s *Service) nothingInNothinOut() {
|
||||
func (d *Demo) nothingInNothinOut() {
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package demo
|
||||
|
||||
import "github.com/foomo/gotsrpc/demo/nested"
|
||||
|
||||
//import nstd "github.com/foomo/gotsrpc/demo/nested"
|
||||
import nstd "github.com/foomo/gotsrpc/demo/nested"
|
||||
|
||||
type Address struct {
|
||||
City string `json:"city,omitempty"`
|
||||
@ -13,8 +11,8 @@ type Address struct {
|
||||
ArrayArrayAddress [][]*Address
|
||||
People []Person
|
||||
MapCrap map[string]map[int]bool
|
||||
NestedPtr *nested.Nested
|
||||
NestedStruct nested.Nested
|
||||
NestedPtr *nstd.Nested
|
||||
NestedStruct nstd.Nested
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
@ -32,22 +30,26 @@ type Person struct {
|
||||
iAmPrivate string
|
||||
}
|
||||
|
||||
func (s *Service) ExtractAddress(person *Person) (addr *Address, e *Err) {
|
||||
func (d *Demo) ExtractAddress(person *Person) (addr *Address, e *Err) {
|
||||
if person.AddressPtr != nil {
|
||||
return person.AddressPtr, nil
|
||||
}
|
||||
return nil, &Err{"there is no address on that person"}
|
||||
}
|
||||
|
||||
func (s *Service) TestScalarInPlace() ScalarInPlace {
|
||||
func (d *Demo) TestScalarInPlace() ScalarInPlace {
|
||||
return ScalarInPlace("hier")
|
||||
}
|
||||
|
||||
func (s *Service) Nest() *nested.Nested {
|
||||
func (d *Demo) MapCrap() (crap map[string][]int) {
|
||||
return map[string][]int{}
|
||||
}
|
||||
|
||||
func (d *Demo) Nest() *nstd.Nested {
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (s *Service) GiveMeAScalar() (amount nstd.Amount, wahr nstd.True, hier ScalarInPlace) {
|
||||
func (s *Service) giveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace) {
|
||||
return nested.Amount(10), nested.ItIsTrue, ScalarInPlace("hier")
|
||||
func (d *Demo) GiveMeAScalar() (amount nstd.Amount, wahr nstd.True, hier ScalarInPlace) {
|
||||
//func (s *Service) giveMeAScalar() (amount nstd.Amount, wahr nstd.True, hier ScalarInPlace) {
|
||||
return nstd.Amount(10), nstd.ItIsTrue, ScalarInPlace("hier")
|
||||
}
|
||||
223
demo/gorpc.go
Normal file
223
demo/gorpc.go
Normal file
@ -0,0 +1,223 @@
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package demo
|
||||
|
||||
import (
|
||||
tls "crypto/tls"
|
||||
gob "encoding/gob"
|
||||
fmt "fmt"
|
||||
gotsrpc "github.com/foomo/gotsrpc"
|
||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
||||
gorpc "github.com/valyala/gorpc"
|
||||
reflect "reflect"
|
||||
strings "strings"
|
||||
time "time"
|
||||
)
|
||||
|
||||
type (
|
||||
FooGoRPCProxy struct {
|
||||
server *gorpc.Server
|
||||
service *Foo
|
||||
callStatsHandler gotsrpc.GoRPCCallStatsHandlerFun
|
||||
}
|
||||
|
||||
HelloRequest struct {
|
||||
Number int64
|
||||
}
|
||||
HelloResponse struct {
|
||||
RetHello_0 int
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(HelloRequest{})
|
||||
gob.Register(HelloResponse{})
|
||||
}
|
||||
|
||||
func NewFooGoRPCProxy(addr string, service *Foo, tlsConfig *tls.Config) *FooGoRPCProxy {
|
||||
proxy := &FooGoRPCProxy{
|
||||
service: service,
|
||||
}
|
||||
|
||||
if tlsConfig != nil {
|
||||
proxy.server = gorpc.NewTLSServer(addr, proxy.handler, tlsConfig)
|
||||
} else {
|
||||
proxy.server = gorpc.NewTCPServer(addr, proxy.handler)
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (p *FooGoRPCProxy) Start() error {
|
||||
return p.server.Start()
|
||||
}
|
||||
|
||||
func (p *FooGoRPCProxy) Stop() {
|
||||
p.server.Stop()
|
||||
}
|
||||
|
||||
func (p *FooGoRPCProxy) SetCallStatsHandler(handler gotsrpc.GoRPCCallStatsHandlerFun) {
|
||||
p.callStatsHandler = handler
|
||||
}
|
||||
|
||||
func (p *FooGoRPCProxy) handler(clientAddr string, request interface{}) (response interface{}) {
|
||||
start := time.Now()
|
||||
|
||||
reqType := reflect.TypeOf(request).String()
|
||||
funcNameParts := strings.Split(reqType, ".")
|
||||
funcName := funcNameParts[len(funcNameParts)-1]
|
||||
|
||||
switch funcName {
|
||||
case "HelloRequest":
|
||||
req := request.(HelloRequest)
|
||||
retHello_0 := p.service.Hello(req.Number)
|
||||
response = HelloResponse{RetHello_0: retHello_0}
|
||||
default:
|
||||
fmt.Println("Unkown request type", reflect.TypeOf(request).String())
|
||||
}
|
||||
|
||||
if p.callStatsHandler != nil {
|
||||
p.callStatsHandler(&gotsrpc.CallStats{
|
||||
Func: funcName,
|
||||
Package: "github.com/foomo/gotsrpc/demo",
|
||||
Service: "Foo",
|
||||
Execution: time.Since(start),
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
DemoGoRPCProxy struct {
|
||||
server *gorpc.Server
|
||||
service *Demo
|
||||
callStatsHandler gotsrpc.GoRPCCallStatsHandlerFun
|
||||
}
|
||||
|
||||
ExtractAddressRequest struct {
|
||||
Person *Person
|
||||
}
|
||||
ExtractAddressResponse struct {
|
||||
Addr *Address
|
||||
E *Err
|
||||
}
|
||||
|
||||
GiveMeAScalarRequest struct {
|
||||
}
|
||||
GiveMeAScalarResponse struct {
|
||||
Amount nested.Amount
|
||||
Wahr nested.True
|
||||
Hier ScalarInPlace
|
||||
}
|
||||
|
||||
HelloRequest struct {
|
||||
Name string
|
||||
}
|
||||
HelloResponse struct {
|
||||
Reply string
|
||||
Err *Err
|
||||
}
|
||||
|
||||
MapCrapRequest struct {
|
||||
}
|
||||
MapCrapResponse struct {
|
||||
Crap map[string][]int
|
||||
}
|
||||
|
||||
NestRequest struct {
|
||||
}
|
||||
NestResponse struct {
|
||||
RetNest_0 *nested.Nested
|
||||
}
|
||||
|
||||
TestScalarInPlaceRequest struct {
|
||||
}
|
||||
TestScalarInPlaceResponse struct {
|
||||
RetTestScalarInPlace_0 ScalarInPlace
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(ExtractAddressRequest{})
|
||||
gob.Register(ExtractAddressResponse{})
|
||||
gob.Register(GiveMeAScalarRequest{})
|
||||
gob.Register(GiveMeAScalarResponse{})
|
||||
gob.Register(HelloRequest{})
|
||||
gob.Register(HelloResponse{})
|
||||
gob.Register(MapCrapRequest{})
|
||||
gob.Register(MapCrapResponse{})
|
||||
gob.Register(NestRequest{})
|
||||
gob.Register(NestResponse{})
|
||||
gob.Register(TestScalarInPlaceRequest{})
|
||||
gob.Register(TestScalarInPlaceResponse{})
|
||||
}
|
||||
|
||||
func NewDemoGoRPCProxy(addr string, service *Demo, tlsConfig *tls.Config) *DemoGoRPCProxy {
|
||||
proxy := &DemoGoRPCProxy{
|
||||
service: service,
|
||||
}
|
||||
|
||||
if tlsConfig != nil {
|
||||
proxy.server = gorpc.NewTLSServer(addr, proxy.handler, tlsConfig)
|
||||
} else {
|
||||
proxy.server = gorpc.NewTCPServer(addr, proxy.handler)
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (p *DemoGoRPCProxy) Start() error {
|
||||
return p.server.Start()
|
||||
}
|
||||
|
||||
func (p *DemoGoRPCProxy) Stop() {
|
||||
p.server.Stop()
|
||||
}
|
||||
|
||||
func (p *DemoGoRPCProxy) SetCallStatsHandler(handler gotsrpc.GoRPCCallStatsHandlerFun) {
|
||||
p.callStatsHandler = handler
|
||||
}
|
||||
|
||||
func (p *DemoGoRPCProxy) handler(clientAddr string, request interface{}) (response interface{}) {
|
||||
start := time.Now()
|
||||
|
||||
reqType := reflect.TypeOf(request).String()
|
||||
funcNameParts := strings.Split(reqType, ".")
|
||||
funcName := funcNameParts[len(funcNameParts)-1]
|
||||
|
||||
switch funcName {
|
||||
case "ExtractAddressRequest":
|
||||
req := request.(ExtractAddressRequest)
|
||||
addr, e := p.service.ExtractAddress(req.Person)
|
||||
response = ExtractAddressResponse{Addr: addr, E: e}
|
||||
case "GiveMeAScalarRequest":
|
||||
amount, wahr, hier := p.service.GiveMeAScalar()
|
||||
response = GiveMeAScalarResponse{Amount: amount, Wahr: wahr, Hier: hier}
|
||||
case "HelloRequest":
|
||||
req := request.(HelloRequest)
|
||||
reply, err := p.service.Hello(req.Name)
|
||||
response = HelloResponse{Reply: reply, Err: err}
|
||||
case "MapCrapRequest":
|
||||
crap := p.service.MapCrap()
|
||||
response = MapCrapResponse{Crap: crap}
|
||||
case "NestRequest":
|
||||
retNest_0 := p.service.Nest()
|
||||
response = NestResponse{RetNest_0: retNest_0}
|
||||
case "TestScalarInPlaceRequest":
|
||||
retTestScalarInPlace_0 := p.service.TestScalarInPlace()
|
||||
response = TestScalarInPlaceResponse{RetTestScalarInPlace_0: retTestScalarInPlace_0}
|
||||
default:
|
||||
fmt.Println("Unkown request type", reflect.TypeOf(request).String())
|
||||
}
|
||||
|
||||
if p.callStatsHandler != nil {
|
||||
p.callStatsHandler(&gotsrpc.CallStats{
|
||||
Func: funcName,
|
||||
Package: "github.com/foomo/gotsrpc/demo",
|
||||
Service: "Demo",
|
||||
Execution: time.Since(start),
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
131
demo/gorpcclient.go
Normal file
131
demo/gorpcclient.go
Normal file
@ -0,0 +1,131 @@
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package demo
|
||||
|
||||
import (
|
||||
tls "crypto/tls"
|
||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
||||
gorpc "github.com/valyala/gorpc"
|
||||
)
|
||||
|
||||
type FooGoRPCClient struct {
|
||||
client *gorpc.Client
|
||||
}
|
||||
|
||||
func NewFooGoRPCClient(addr string, tlsConfig *tls.Config) *FooGoRPCClient {
|
||||
client := &FooGoRPCClient{}
|
||||
if tlsConfig == nil {
|
||||
client.client = gorpc.NewTCPClient(addr)
|
||||
} else {
|
||||
client.client = gorpc.NewTLSClient(addr, tlsConfig)
|
||||
}
|
||||
client.Start()
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *FooGoRPCClient) Start() {
|
||||
c.client.Start()
|
||||
}
|
||||
|
||||
func (c *FooGoRPCClient) Stop() {
|
||||
c.client.Stop()
|
||||
}
|
||||
|
||||
func (c *FooGoRPCClient) Hello(number int64) (retHello_0 int, clientErr error) {
|
||||
req := HelloRequest{Number: number}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(HelloResponse)
|
||||
return response.RetHello_0, nil
|
||||
}
|
||||
|
||||
type DemoGoRPCClient struct {
|
||||
client *gorpc.Client
|
||||
}
|
||||
|
||||
func NewDemoGoRPCClient(addr string, tlsConfig *tls.Config) *DemoGoRPCClient {
|
||||
client := &DemoGoRPCClient{}
|
||||
if tlsConfig == nil {
|
||||
client.client = gorpc.NewTCPClient(addr)
|
||||
} else {
|
||||
client.client = gorpc.NewTLSClient(addr, tlsConfig)
|
||||
}
|
||||
client.Start()
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) Start() {
|
||||
c.client.Start()
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) Stop() {
|
||||
c.client.Stop()
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) ExtractAddress(person *Person) (addr *Address, e *Err, clientErr error) {
|
||||
req := ExtractAddressRequest{Person: person}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(ExtractAddressResponse)
|
||||
return response.Addr, response.E, nil
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) GiveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace, clientErr error) {
|
||||
req := GiveMeAScalarRequest{}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(GiveMeAScalarResponse)
|
||||
return response.Amount, response.Wahr, response.Hier, nil
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) Hello(name string) (reply string, err *Err, clientErr error) {
|
||||
req := HelloRequest{Name: name}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(HelloResponse)
|
||||
return response.Reply, response.Err, nil
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) MapCrap() (crap map[string][]int, clientErr error) {
|
||||
req := MapCrapRequest{}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(MapCrapResponse)
|
||||
return response.Crap, nil
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) Nest() (retNest_0 *nested.Nested, clientErr error) {
|
||||
req := NestRequest{}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(NestResponse)
|
||||
return response.RetNest_0, nil
|
||||
}
|
||||
|
||||
func (c *DemoGoRPCClient) TestScalarInPlace() (retTestScalarInPlace_0 ScalarInPlace, clientErr error) {
|
||||
req := TestScalarInPlaceRequest{}
|
||||
res, err := c.client.Call(req)
|
||||
if err != nil {
|
||||
clientErr = err
|
||||
return
|
||||
}
|
||||
response := res.(TestScalarInPlaceResponse)
|
||||
return response.RetTestScalarInPlace_0, nil
|
||||
}
|
||||
174
demo/gotsrpc.go
174
demo/gotsrpc.go
@ -4,16 +4,25 @@ package demo
|
||||
import (
|
||||
gotsrpc "github.com/foomo/gotsrpc"
|
||||
http "net/http"
|
||||
time "time"
|
||||
)
|
||||
|
||||
type ServiceGoTSRPCProxy struct {
|
||||
type FooGoTSRPCProxy struct {
|
||||
EndPoint string
|
||||
allowOrigin []string
|
||||
service *Service
|
||||
service *Foo
|
||||
}
|
||||
|
||||
func NewServiceGoTSRPCProxy(service *Service, endpoint string, allowOrigin []string) *ServiceGoTSRPCProxy {
|
||||
return &ServiceGoTSRPCProxy{
|
||||
func NewDefaultFooGoTSRPCProxy(service *Foo, allowOrigin []string) *FooGoTSRPCProxy {
|
||||
return &FooGoTSRPCProxy{
|
||||
EndPoint: "/service/foo",
|
||||
allowOrigin: allowOrigin,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFooGoTSRPCProxy(service *Foo, endpoint string, allowOrigin []string) *FooGoTSRPCProxy {
|
||||
return &FooGoTSRPCProxy{
|
||||
EndPoint: endpoint,
|
||||
allowOrigin: allowOrigin,
|
||||
service: service,
|
||||
@ -21,46 +30,155 @@ func NewServiceGoTSRPCProxy(service *Service, endpoint string, allowOrigin []str
|
||||
}
|
||||
|
||||
// ServeHTTP exposes your service
|
||||
func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
func (p *FooGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
for _, origin := range p.allowOrigin {
|
||||
// todo we have to compare this with the referer ... and only send one
|
||||
w.Header().Add("Access-Control-Allow-Origin", origin)
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
if r.Method != "POST" {
|
||||
if r.Method != http.MethodPost {
|
||||
if r.Method == http.MethodOptions {
|
||||
return
|
||||
}
|
||||
gotsrpc.ErrorMethodNotAllowed(w)
|
||||
return
|
||||
}
|
||||
|
||||
var args []interface{}
|
||||
switch gotsrpc.GetCalledFunc(r, p.EndPoint) {
|
||||
funcName := gotsrpc.GetCalledFunc(r, p.EndPoint)
|
||||
callStats := gotsrpc.GetStatsForRequest(r)
|
||||
if callStats != nil {
|
||||
callStats.Func = funcName
|
||||
callStats.Package = "github.com/foomo/gotsrpc/demo"
|
||||
callStats.Service = "Foo"
|
||||
}
|
||||
switch funcName {
|
||||
case "Hello":
|
||||
args = []interface{}{""}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
args = []interface{}{int64(0)}
|
||||
err := gotsrpc.LoadArgs(args, callStats, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
helloReply, helloErr := p.service.Hello(args[0].(string))
|
||||
gotsrpc.Reply([]interface{}{helloReply, helloErr}, w)
|
||||
return
|
||||
case "ExtractAddress":
|
||||
args = []interface{}{&Person{}}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
executionStart := time.Now()
|
||||
helloRet := p.service.Hello(int64(args[0].(float64)))
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
extractAddressAddr, extractAddressE := p.service.ExtractAddress(args[0].(*Person))
|
||||
gotsrpc.Reply([]interface{}{extractAddressAddr, extractAddressE}, w)
|
||||
return
|
||||
case "TestScalarInPlace":
|
||||
testScalarInPlaceRet := p.service.TestScalarInPlace()
|
||||
gotsrpc.Reply([]interface{}{testScalarInPlaceRet}, w)
|
||||
return
|
||||
case "Nest":
|
||||
nestRet := p.service.Nest()
|
||||
gotsrpc.Reply([]interface{}{nestRet}, w)
|
||||
gotsrpc.Reply([]interface{}{helloRet}, callStats, r, w)
|
||||
return
|
||||
default:
|
||||
http.Error(w, "404 - not found "+r.URL.Path, http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
type DemoGoTSRPCProxy struct {
|
||||
EndPoint string
|
||||
allowOrigin []string
|
||||
service *Demo
|
||||
}
|
||||
|
||||
func NewDefaultDemoGoTSRPCProxy(service *Demo, allowOrigin []string) *DemoGoTSRPCProxy {
|
||||
return &DemoGoTSRPCProxy{
|
||||
EndPoint: "/service/demo",
|
||||
allowOrigin: allowOrigin,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDemoGoTSRPCProxy(service *Demo, endpoint string, allowOrigin []string) *DemoGoTSRPCProxy {
|
||||
return &DemoGoTSRPCProxy{
|
||||
EndPoint: endpoint,
|
||||
allowOrigin: allowOrigin,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP exposes your service
|
||||
func (p *DemoGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
for _, origin := range p.allowOrigin {
|
||||
// todo we have to compare this with the referer ... and only send one
|
||||
w.Header().Add("Access-Control-Allow-Origin", origin)
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
if r.Method != http.MethodPost {
|
||||
if r.Method == http.MethodOptions {
|
||||
return
|
||||
}
|
||||
gotsrpc.ErrorMethodNotAllowed(w)
|
||||
return
|
||||
}
|
||||
|
||||
var args []interface{}
|
||||
funcName := gotsrpc.GetCalledFunc(r, p.EndPoint)
|
||||
callStats := gotsrpc.GetStatsForRequest(r)
|
||||
if callStats != nil {
|
||||
callStats.Func = funcName
|
||||
callStats.Package = "github.com/foomo/gotsrpc/demo"
|
||||
callStats.Service = "Demo"
|
||||
}
|
||||
switch funcName {
|
||||
case "ExtractAddress":
|
||||
args = []interface{}{&Person{}}
|
||||
err := gotsrpc.LoadArgs(args, callStats, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
executionStart := time.Now()
|
||||
extractAddressAddr, extractAddressE := p.service.ExtractAddress(args[0].(*Person))
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{extractAddressAddr, extractAddressE}, callStats, r, w)
|
||||
return
|
||||
case "GiveMeAScalar":
|
||||
executionStart := time.Now()
|
||||
giveMeAScalarAmount, giveMeAScalarWahr, giveMeAScalarHier := p.service.GiveMeAScalar()
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{giveMeAScalarAmount, giveMeAScalarWahr, giveMeAScalarHier}, callStats, r, w)
|
||||
return
|
||||
case "Hello":
|
||||
args = []interface{}{""}
|
||||
err := gotsrpc.LoadArgs(args, callStats, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
executionStart := time.Now()
|
||||
helloReply, helloErr := p.service.Hello(args[0].(string))
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{helloReply, helloErr}, callStats, r, w)
|
||||
return
|
||||
case "MapCrap":
|
||||
executionStart := time.Now()
|
||||
mapCrapCrap := p.service.MapCrap()
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{mapCrapCrap}, callStats, r, w)
|
||||
return
|
||||
case "Nest":
|
||||
executionStart := time.Now()
|
||||
nestRet := p.service.Nest()
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{nestRet}, callStats, r, w)
|
||||
return
|
||||
case "TestScalarInPlace":
|
||||
executionStart := time.Now()
|
||||
testScalarInPlaceRet := p.service.TestScalarInPlace()
|
||||
if callStats != nil {
|
||||
callStats.Execution = time.Now().Sub(executionStart)
|
||||
}
|
||||
gotsrpc.Reply([]interface{}{testScalarInPlaceRet}, callStats, r, w)
|
||||
return
|
||||
default:
|
||||
http.Error(w, "404 - not found "+r.URL.Path, http.StatusNotFound)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
package demo_test
|
||||
88
demo/gotsrpcclient.go
Normal file
88
demo/gotsrpcclient.go
Normal file
@ -0,0 +1,88 @@
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package demo
|
||||
|
||||
import (
|
||||
gotsrpc "github.com/foomo/gotsrpc"
|
||||
nested "github.com/foomo/gotsrpc/demo/nested"
|
||||
)
|
||||
|
||||
type FooGoTSRPCClient struct {
|
||||
URL string
|
||||
EndPoint string
|
||||
}
|
||||
|
||||
func NewDefaultFooGoTSRPCClient(url string) *FooGoTSRPCClient {
|
||||
return NewFooGoTSRPCClient(url, "/service/foo")
|
||||
}
|
||||
|
||||
func NewFooGoTSRPCClient(url string, endpoint string) *FooGoTSRPCClient {
|
||||
return &FooGoTSRPCClient{
|
||||
URL: url,
|
||||
EndPoint: endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *FooGoTSRPCClient) Hello(number int64) (retHello_0 int, clientErr error) {
|
||||
args := []interface{}{number}
|
||||
reply := []interface{}{&retHello_0}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "Hello", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
type DemoGoTSRPCClient struct {
|
||||
URL string
|
||||
EndPoint string
|
||||
}
|
||||
|
||||
func NewDefaultDemoGoTSRPCClient(url string) *DemoGoTSRPCClient {
|
||||
return NewDemoGoTSRPCClient(url, "/service/demo")
|
||||
}
|
||||
|
||||
func NewDemoGoTSRPCClient(url string, endpoint string) *DemoGoTSRPCClient {
|
||||
return &DemoGoTSRPCClient{
|
||||
URL: url,
|
||||
EndPoint: endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) ExtractAddress(person *Person) (addr *Address, e *Err, clientErr error) {
|
||||
args := []interface{}{person}
|
||||
reply := []interface{}{&addr, &e}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "ExtractAddress", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) GiveMeAScalar() (amount nested.Amount, wahr nested.True, hier ScalarInPlace, clientErr error) {
|
||||
args := []interface{}{}
|
||||
reply := []interface{}{&amount, &wahr, &hier}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "GiveMeAScalar", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) Hello(name string) (reply string, err *Err, clientErr error) {
|
||||
args := []interface{}{name}
|
||||
reply := []interface{}{&reply, &err}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "Hello", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) MapCrap() (crap map[string][]int, clientErr error) {
|
||||
args := []interface{}{}
|
||||
reply := []interface{}{&crap}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "MapCrap", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) Nest() (retNest_0 *nested.Nested, clientErr error) {
|
||||
args := []interface{}{}
|
||||
reply := []interface{}{&retNest_0}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "Nest", args, reply)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *DemoGoTSRPCClient) TestScalarInPlace() (retTestScalarInPlace_0 ScalarInPlace, clientErr error) {
|
||||
args := []interface{}{}
|
||||
reply := []interface{}{&retTestScalarInPlace_0}
|
||||
clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "TestScalarInPlace", args, reply)
|
||||
return
|
||||
}
|
||||
36
glide.lock
generated
Normal file
36
glide.lock
generated
Normal file
@ -0,0 +1,36 @@
|
||||
hash: ceb81b420e31dbc1d0fac128b688dfb563ab5fc6e0220d995dc20830e7a127c8
|
||||
updated: 2016-12-17T07:08:03.465146982+01:00
|
||||
imports:
|
||||
- name: github.com/beorn7/perks
|
||||
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||
subpackages:
|
||||
- quantile
|
||||
- name: github.com/golang/protobuf
|
||||
version: da116c3771bf4a398a43f44e069195ef1c9688ef
|
||||
subpackages:
|
||||
- proto
|
||||
- name: github.com/matttproud/golang_protobuf_extensions
|
||||
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
|
||||
subpackages:
|
||||
- pbutil
|
||||
- name: github.com/prometheus/client_golang
|
||||
version: c5b7fccd204277076155f10851dad72b76a49317
|
||||
subpackages:
|
||||
- prometheus
|
||||
- name: github.com/prometheus/client_model
|
||||
version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
|
||||
subpackages:
|
||||
- go
|
||||
- name: github.com/prometheus/common
|
||||
version: 0d5de9d6d8629cb8bee6d4674da4127cd8b615a3
|
||||
subpackages:
|
||||
- expfmt
|
||||
- internal/bitbucket.org/ww/goautoneg
|
||||
- model
|
||||
- name: github.com/prometheus/procfs
|
||||
version: abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
|
||||
- name: github.com/valyala/gorpc
|
||||
version: 908281bef77441f2d0ec1792189b4032a1dace0c
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: a5b47d31c556af34a302ce5d659e6fea44d90de0
|
||||
testImports: []
|
||||
8
glide.yaml
Normal file
8
glide.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
package: github.com/foomo/gotsrpc
|
||||
import:
|
||||
- package: github.com/prometheus/client_golang
|
||||
version: ~0.8.0
|
||||
subpackages:
|
||||
- prometheus
|
||||
- package: github.com/valyala/gorpc
|
||||
- package: gopkg.in/yaml.v2
|
||||
504
go.go
504
go.go
@ -3,11 +3,14 @@ package gotsrpc
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/gotsrpc/config"
|
||||
)
|
||||
|
||||
func (v *Value) isHTTPResponseWriter() bool {
|
||||
return v.StructType != nil && v.StructType.Name == "ResponseWriter" && v.StructType.Package == "net/http"
|
||||
}
|
||||
|
||||
func (v *Value) isHTTPRequest() bool {
|
||||
return v.IsPtr && v.StructType != nil && v.StructType.Name == "Request" && v.StructType.Package == "net/http"
|
||||
}
|
||||
@ -26,10 +29,20 @@ func (v *Value) goType(aliases map[string]string, packageName string) (t string)
|
||||
t += aliases[v.StructType.Package] + "."
|
||||
}
|
||||
t += v.StructType.Name
|
||||
|
||||
case v.Map != nil:
|
||||
t += `map[` + v.Map.KeyType + `]` + v.Map.Value.goType(aliases, packageName)
|
||||
case v.Scalar != nil:
|
||||
// TODO this is a hack to retrieve string types
|
||||
if packageName != v.Scalar.Package {
|
||||
t += aliases[v.Scalar.Package] + "."
|
||||
}
|
||||
t += v.Scalar.Name[len(v.Scalar.Package)+1:]
|
||||
default:
|
||||
// TODO
|
||||
fmt.Println("WARN: can't resolve goType")
|
||||
}
|
||||
return
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Value) emptyLiteral(aliases map[string]string) (e string) {
|
||||
@ -50,10 +63,24 @@ func (v *Value) emptyLiteral(aliases map[string]string) (e string) {
|
||||
return "float64(0.0)"
|
||||
case "int":
|
||||
return "int(0)"
|
||||
case "int8":
|
||||
return "int8(0)"
|
||||
case "int16":
|
||||
return "int16(0)"
|
||||
case "int32":
|
||||
return "int32(0)"
|
||||
case "int64":
|
||||
return "int64(0)"
|
||||
case "uint":
|
||||
return "uint(0)"
|
||||
case "uint8":
|
||||
return "uint8(0)"
|
||||
case "uint16":
|
||||
return "uint16(0)"
|
||||
case "uint32":
|
||||
return "uint32(0)"
|
||||
case "uint64":
|
||||
return "uint64(0)"
|
||||
case "bool":
|
||||
return "false"
|
||||
}
|
||||
@ -102,43 +129,55 @@ func strfirst(str string, strfunc func(string) string) string {
|
||||
|
||||
}
|
||||
return res
|
||||
|
||||
}
|
||||
|
||||
func renderServiceProxies(services map[string]*Service, fullPackageName string, packageName string, g *code) error {
|
||||
aliases := map[string]string{
|
||||
"net/http": "http",
|
||||
"time": "time",
|
||||
"github.com/foomo/gotsrpc": "gotsrpc",
|
||||
}
|
||||
r := strings.NewReplacer(".", "_", "/", "_", "-", "_")
|
||||
extractImports := func(fields []*Field) {
|
||||
for _, f := range fields {
|
||||
if f.Value.StructType != nil {
|
||||
st := f.Value.StructType
|
||||
if st.Package != fullPackageName {
|
||||
alias, ok := aliases[st.Package]
|
||||
if !ok {
|
||||
packageParts := strings.Split(st.Package, "/")
|
||||
beautifulAlias := packageParts[len(packageParts)-1]
|
||||
uglyAlias := r.Replace(st.Package)
|
||||
alias = beautifulAlias
|
||||
for _, otherAlias := range aliases {
|
||||
if otherAlias == beautifulAlias {
|
||||
alias = uglyAlias
|
||||
break
|
||||
}
|
||||
}
|
||||
aliases[st.Package] = alias
|
||||
}
|
||||
func extractImports(fields []*Field, fullPackageName string, aliases map[string]string) {
|
||||
|
||||
r := strings.NewReplacer(".", "_", "/", "_", "-", "_")
|
||||
|
||||
extractImport := func(st *StructType) {
|
||||
if st.Package != fullPackageName {
|
||||
alias, ok := aliases[st.Package]
|
||||
if !ok {
|
||||
packageParts := strings.Split(st.Package, "/")
|
||||
beautifulAlias := packageParts[len(packageParts)-1]
|
||||
uglyAlias := r.Replace(st.Package)
|
||||
alias = beautifulAlias
|
||||
for _, otherAlias := range aliases {
|
||||
if otherAlias == beautifulAlias {
|
||||
alias = uglyAlias
|
||||
break
|
||||
}
|
||||
}
|
||||
aliases[st.Package] = alias
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, s := range services {
|
||||
for _, m := range s.Methods {
|
||||
extractImports(m.Args)
|
||||
|
||||
for _, f := range fields {
|
||||
if f.Value.StructType != nil {
|
||||
extractImport(f.Value.StructType)
|
||||
} else if f.Value.Array != nil && f.Value.Array.Value.StructType != nil {
|
||||
extractImport(f.Value.Array.Value.StructType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func renderTSRPCServiceProxies(services map[string]*Service, fullPackageName string, packageName string, config *config.Target, g *code) error {
|
||||
aliases := map[string]string{
|
||||
"time": "time",
|
||||
"net/http": "http",
|
||||
"github.com/foomo/gotsrpc": "gotsrpc",
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !config.IsTSRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
for _, m := range service.Methods {
|
||||
extractImports(m.Args, fullPackageName, aliases)
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,6 +194,12 @@ func renderServiceProxies(services map[string]*Service, fullPackageName string,
|
||||
)
|
||||
`)
|
||||
for endpoint, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !config.IsTSRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
proxyName := service.Name + "GoTSRPCProxy"
|
||||
g.l(`
|
||||
type ` + proxyName + ` struct {
|
||||
@ -179,7 +224,7 @@ func renderServiceProxies(services map[string]*Service, fullPackageName string,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ServeHTTP exposes your service
|
||||
func (p *` + proxyName + `) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@ -244,6 +289,9 @@ func renderServiceProxies(services map[string]*Service, fullPackageName string,
|
||||
|
||||
args = append(args, arg.Value.emptyLiteral(aliases))
|
||||
switch arg.Value.GoScalarType {
|
||||
// case "int", "int8", "int16", "int32", "int64",
|
||||
// "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
// callArgs = append(callArgs, fmt.Sprint(arg.Value.GoScalarType+"(args[", skipArgI, "].(float64))"))
|
||||
default:
|
||||
// assert
|
||||
callArgs = append(callArgs, fmt.Sprint("args[", skipArgI, "].("+arg.Value.goType(aliases, fullPackageName)+")"))
|
||||
@ -292,14 +340,398 @@ func renderServiceProxies(services map[string]*Service, fullPackageName string,
|
||||
g.ind(1).l("http.Error(w, \"404 - not found \" + r.URL.Path, http.StatusNotFound)")
|
||||
g.ind(-2).l("}") // close switch
|
||||
g.ind(-1).l("}") // close ServeHttp
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RenderGo(services map[string]*Service, longPackageName, packageName string) (gocode string, err error) {
|
||||
func renderTSRPCServiceClients(services map[string]*Service, fullPackageName string, packageName string, config *config.Target, g *code) error {
|
||||
aliases := map[string]string{
|
||||
"github.com/foomo/gotsrpc": "gotsrpc",
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !config.IsTSRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
for _, m := range service.Methods {
|
||||
extractImports(m.Args, fullPackageName, aliases)
|
||||
extractImports(m.Return, fullPackageName, aliases)
|
||||
}
|
||||
}
|
||||
|
||||
imports := ""
|
||||
for packageName, alias := range aliases {
|
||||
imports += alias + " \"" + packageName + "\"\n"
|
||||
}
|
||||
|
||||
g.l(`
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package ` + packageName + `
|
||||
import (
|
||||
` + imports + `
|
||||
)
|
||||
`)
|
||||
for endpoint, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !config.IsTSRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
clientName := service.Name + "GoTSRPCClient"
|
||||
g.l(`
|
||||
type ` + clientName + ` struct {
|
||||
URL string
|
||||
EndPoint string
|
||||
}
|
||||
|
||||
func NewDefault` + clientName + `(url string) *` + clientName + ` {
|
||||
return New` + clientName + `(url, "` + endpoint + `")
|
||||
}
|
||||
|
||||
func New` + clientName + `(url string, endpoint string) *` + clientName + ` {
|
||||
return &` + clientName + `{
|
||||
URL: url,
|
||||
EndPoint: endpoint,
|
||||
}
|
||||
}
|
||||
`)
|
||||
for _, method := range service.Methods {
|
||||
args := []string{}
|
||||
params := []string{}
|
||||
for _, a := range method.Args {
|
||||
args = append(args, a.Name)
|
||||
params = append(params, a.Name+" "+a.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
rets := []string{}
|
||||
returns := []string{}
|
||||
for i, r := range method.Return {
|
||||
name := r.Name
|
||||
if len(name) == 0 {
|
||||
name = fmt.Sprintf("ret%s_%d", method.Name, i)
|
||||
}
|
||||
rets = append(rets, "&"+name)
|
||||
returns = append(returns, name+" "+r.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
returns = append(returns, "clientErr error")
|
||||
g.l(`func (c *` + clientName + `) ` + method.Name + `(` + strings.Join(params, ", ") + `) (` + strings.Join(returns, ", ") + `) {`)
|
||||
g.l(`args := []interface{}{` + strings.Join(args, ", ") + `}`)
|
||||
g.l(`reply := []interface{}{` + strings.Join(rets, ", ") + `}`)
|
||||
g.l(`clientErr = gotsrpc.CallClient(c.URL, c.EndPoint, "` + method.Name + `", args, reply)`)
|
||||
g.l(`return`)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func renderGoRPCServiceProxies(services map[string]*Service, fullPackageName string, packageName string, config *config.Target, g *code) error {
|
||||
aliases := map[string]string{
|
||||
"fmt": "fmt",
|
||||
"time": "time",
|
||||
"strings": "strings",
|
||||
"reflect": "reflect",
|
||||
"crypto/tls": "tls",
|
||||
"encoding/gob": "gob",
|
||||
"github.com/valyala/gorpc": "gorpc",
|
||||
"github.com/foomo/gotsrpc": "gotsrpc",
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
if !config.IsGoRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, m := range service.Methods {
|
||||
extractImports(m.Args, fullPackageName, aliases)
|
||||
extractImports(m.Return, fullPackageName, aliases)
|
||||
}
|
||||
}
|
||||
|
||||
imports := ""
|
||||
for packageName, alias := range aliases {
|
||||
imports += alias + " \"" + packageName + "\"\n"
|
||||
}
|
||||
|
||||
g.l(`
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package ` + packageName + `
|
||||
import (
|
||||
` + imports + `
|
||||
)
|
||||
`)
|
||||
|
||||
for _, service := range services {
|
||||
if !config.IsGoRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
proxyName := service.Name + "GoRPCProxy"
|
||||
// Types
|
||||
g.l(`type (`)
|
||||
// Proxy type
|
||||
g.l(`
|
||||
` + proxyName + ` struct {
|
||||
server *gorpc.Server
|
||||
service *` + service.Name + `
|
||||
callStatsHandler gotsrpc.GoRPCCallStatsHandlerFun
|
||||
}
|
||||
`)
|
||||
// Request & Response types
|
||||
for _, method := range service.Methods {
|
||||
// Request type
|
||||
g.l(ucfirst(service.Name+method.Name) + `Request struct {`)
|
||||
for _, a := range method.Args {
|
||||
g.l(ucfirst(a.Name) + ` ` + a.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
g.l(`}`)
|
||||
// Response type
|
||||
g.l(ucfirst(service.Name+method.Name) + `Response struct {`)
|
||||
for i, r := range method.Return {
|
||||
name := r.Name
|
||||
if len(name) == 0 {
|
||||
name = fmt.Sprintf("ret%s_%d", method.Name, i)
|
||||
}
|
||||
g.l(ucfirst(name) + ` ` + r.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
}
|
||||
g.l(`)`)
|
||||
g.nl()
|
||||
// Init
|
||||
g.l(`func init() {`)
|
||||
for _, method := range service.Methods {
|
||||
g.l(`gob.Register(` + ucfirst(service.Name+method.Name) + `Request{})`)
|
||||
g.l(`gob.Register(` + ucfirst(service.Name+method.Name) + `Response{})`)
|
||||
}
|
||||
g.l(`}`)
|
||||
// Constructor
|
||||
g.l(`
|
||||
func New` + proxyName + `(addr string, service *` + service.Name + `, tlsConfig *tls.Config) *` + proxyName + ` {
|
||||
proxy := &` + proxyName + `{
|
||||
service: service,
|
||||
}
|
||||
|
||||
if tlsConfig != nil {
|
||||
proxy.server = gorpc.NewTLSServer(addr, proxy.handler, tlsConfig)
|
||||
} else {
|
||||
proxy.server = gorpc.NewTCPServer(addr, proxy.handler)
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (p *` + proxyName + `) Start() error {
|
||||
return p.server.Start()
|
||||
}
|
||||
|
||||
func (p *` + proxyName + `) Serve() error {
|
||||
return p.server.Serve()
|
||||
}
|
||||
|
||||
func (p *` + proxyName + `) Stop() {
|
||||
p.server.Stop()
|
||||
}
|
||||
|
||||
func (p *` + proxyName + `) SetCallStatsHandler(handler gotsrpc.GoRPCCallStatsHandlerFun) {
|
||||
p.callStatsHandler = handler
|
||||
}
|
||||
`)
|
||||
g.nl()
|
||||
// Handler
|
||||
g.l(`func (p *` + proxyName + `) handler(clientAddr string, request interface{}) (response interface{}) {`)
|
||||
g.l(`start := time.Now()`)
|
||||
g.nl()
|
||||
g.l(`reqType := reflect.TypeOf(request).String()`)
|
||||
g.l(`funcNameParts := strings.Split(reqType, ".")`)
|
||||
g.l(`funcName := funcNameParts[len(funcNameParts)-1]`)
|
||||
g.nl()
|
||||
g.l(`switch funcName {`)
|
||||
for _, method := range service.Methods {
|
||||
argParams := []string{}
|
||||
for _, a := range method.Args {
|
||||
argParams = append(argParams, "req."+ucfirst(a.Name))
|
||||
}
|
||||
rets := []string{}
|
||||
retParams := []string{}
|
||||
for i, r := range method.Return {
|
||||
name := r.Name
|
||||
if len(name) == 0 {
|
||||
name = fmt.Sprintf("ret%s_%d", method.Name, i)
|
||||
}
|
||||
rets = append(rets, name)
|
||||
retParams = append(retParams, ucfirst(name)+`: `+name)
|
||||
}
|
||||
g.l(`case "` + service.Name + method.Name + `Request":`)
|
||||
if len(argParams) > 0 {
|
||||
g.l(`req := request.(` + service.Name + method.Name + `Request)`)
|
||||
}
|
||||
if len(rets) > 0 {
|
||||
g.l(strings.Join(rets, ", ") + ` := p.service.` + method.Name + `(` + strings.Join(argParams, ", ") + `)`)
|
||||
} else {
|
||||
g.l(`p.service.` + method.Name + `(` + strings.Join(argParams, ", ") + `)`)
|
||||
}
|
||||
g.l(`response = ` + service.Name + method.Name + `Response{` + strings.Join(retParams, ", ") + `}`)
|
||||
}
|
||||
g.l(`default:`)
|
||||
g.l(`fmt.Println("Unkown request type", reflect.TypeOf(request).String())`)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
g.l(`if p.callStatsHandler != nil {`)
|
||||
g.l(`p.callStatsHandler(&gotsrpc.CallStats{`)
|
||||
g.l(`Func: funcName,`)
|
||||
g.l(`Package: "` + fullPackageName + `",`)
|
||||
g.l(`Service: "` + service.Name + `",`)
|
||||
g.l(`Execution: time.Since(start),`)
|
||||
g.l(`})`)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
g.l(`return`)
|
||||
g.l(`}`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func renderGoRPCServiceClients(services map[string]*Service, fullPackageName string, packageName string, config *config.Target, g *code) error {
|
||||
aliases := map[string]string{
|
||||
"crypto/tls": "tls",
|
||||
"github.com/valyala/gorpc": "gorpc",
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
if !config.IsGoRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
for _, m := range service.Methods {
|
||||
extractImports(m.Args, fullPackageName, aliases)
|
||||
extractImports(m.Return, fullPackageName, aliases)
|
||||
}
|
||||
}
|
||||
|
||||
imports := ""
|
||||
for packageName, alias := range aliases {
|
||||
imports += alias + " \"" + packageName + "\"\n"
|
||||
}
|
||||
|
||||
g.l(`
|
||||
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
|
||||
package ` + packageName + `
|
||||
import (
|
||||
` + imports + `
|
||||
)
|
||||
`)
|
||||
for _, service := range services {
|
||||
if !config.IsGoRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
clientName := service.Name + "GoRPCClient"
|
||||
// Client type
|
||||
g.l(`
|
||||
type ` + clientName + ` struct {
|
||||
Client *gorpc.Client
|
||||
}
|
||||
`)
|
||||
// Constructor
|
||||
g.l(`
|
||||
func New` + clientName + `(addr string, tlsConfig *tls.Config) *` + clientName + ` {
|
||||
client := &` + clientName + `{}
|
||||
if tlsConfig == nil {
|
||||
client.Client = gorpc.NewTCPClient(addr)
|
||||
} else {
|
||||
client.Client = gorpc.NewTLSClient(addr, tlsConfig)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *` + clientName + `) Start() {
|
||||
c.Client.Start()
|
||||
}
|
||||
|
||||
func (c *` + clientName + `) Stop() {
|
||||
c.Client.Stop()
|
||||
}
|
||||
`)
|
||||
g.nl()
|
||||
// Methods
|
||||
for _, method := range service.Methods {
|
||||
args := []string{}
|
||||
params := []string{}
|
||||
for _, a := range method.Args {
|
||||
args = append(args, ucfirst(a.Name)+`: `+a.Name)
|
||||
params = append(params, a.Name+" "+a.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
rets := []string{}
|
||||
returns := []string{}
|
||||
for i, r := range method.Return {
|
||||
name := r.Name
|
||||
if len(name) == 0 {
|
||||
name = fmt.Sprintf("ret%s_%d", method.Name, i)
|
||||
}
|
||||
rets = append(rets, "response."+ucfirst(name))
|
||||
returns = append(returns, name+" "+r.Value.goType(aliases, fullPackageName))
|
||||
}
|
||||
returns = append(returns, "clientErr error")
|
||||
g.l(`func (c *` + clientName + `) ` + method.Name + `(` + strings.Join(params, ", ") + `) (` + strings.Join(returns, ", ") + `) {`)
|
||||
g.l(`req := ` + service.Name + method.Name + `Request{` + strings.Join(args, ", ") + `}`)
|
||||
if len(rets) > 0 {
|
||||
g.l(`rpcCallRes, rpcCallErr := c.Client.Call(req)`)
|
||||
} else {
|
||||
g.l(`_, rpcCallErr := c.Client.Call(req)`)
|
||||
}
|
||||
g.l(`if rpcCallErr != nil {`)
|
||||
g.l(`clientErr = rpcCallErr`)
|
||||
g.l(`return`)
|
||||
g.l(`}`)
|
||||
if len(rets) > 0 {
|
||||
g.l(`response := rpcCallRes.(` + service.Name + method.Name + `Response)`)
|
||||
g.l(`return ` + strings.Join(rets, ", ") + `, nil`)
|
||||
} else {
|
||||
g.l(`return nil`)
|
||||
}
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RenderGoTSRPCProxies(services map[string]*Service, longPackageName, packageName string, config *config.Target) (gocode string, err error) {
|
||||
g := newCode(" ")
|
||||
err = renderServiceProxies(services, longPackageName, packageName, g)
|
||||
err = renderTSRPCServiceProxies(services, longPackageName, packageName, config, g)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gocode = g.string()
|
||||
return
|
||||
}
|
||||
|
||||
func RenderGoTSRPCClients(services map[string]*Service, longPackageName, packageName string, config *config.Target) (gocode string, err error) {
|
||||
g := newCode(" ")
|
||||
err = renderTSRPCServiceClients(services, longPackageName, packageName, config, g)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gocode = g.string()
|
||||
return
|
||||
}
|
||||
|
||||
func RenderGoRPCProxies(services map[string]*Service, longPackageName, packageName string, config *config.Target) (gocode string, err error) {
|
||||
g := newCode(" ")
|
||||
err = renderGoRPCServiceProxies(services, longPackageName, packageName, config, g)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gocode = g.string()
|
||||
return
|
||||
}
|
||||
|
||||
func RenderGoRPCClients(services map[string]*Service, longPackageName, packageName string, config *config.Target) (gocode string, err error) {
|
||||
g := newCode(" ")
|
||||
err = renderGoRPCServiceClients(services, longPackageName, packageName, config, g)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
4
gorpc.go
Normal file
4
gorpc.go
Normal file
@ -0,0 +1,4 @@
|
||||
package gotsrpc
|
||||
|
||||
|
||||
type GoRPCCallStatsHandlerFun func(stats *CallStats)
|
||||
32
gotsrpc.go
32
gotsrpc.go
@ -8,6 +8,7 @@ import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
@ -37,13 +38,17 @@ func ErrorMethodNotAllowed(w http.ResponseWriter) {
|
||||
|
||||
func LoadArgs(args interface{}, callStats *CallStats, r *http.Request) error {
|
||||
start := time.Now()
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&args)
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(body, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
if callStats != nil {
|
||||
callStats.Unmarshalling = time.Now().Sub(start)
|
||||
callStats.RequestSize = len(body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -71,6 +76,7 @@ func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.Res
|
||||
return
|
||||
}
|
||||
if stats != nil {
|
||||
stats.ResponseSize = len(jsonBytes)
|
||||
stats.Marshalling = time.Now().Sub(serializationStart)
|
||||
}
|
||||
//r = r.WithContext(ctx)
|
||||
@ -88,12 +94,24 @@ func jsonDump(v interface{}) {
|
||||
fmt.Println(string(jsonBytes))
|
||||
}
|
||||
|
||||
func parsePackage(goPath string, packageName string) (pkg *ast.Package, err error) {
|
||||
fset := token.NewFileSet()
|
||||
dir := path.Join(goPath, "src", packageName)
|
||||
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
|
||||
func parseDir(goPaths []string, packageName string) (map[string]*ast.Package, error) {
|
||||
errorStrings := map[string]string{}
|
||||
for _, goPath := range goPaths {
|
||||
fset := token.NewFileSet()
|
||||
dir := path.Join(goPath, "src", packageName)
|
||||
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
|
||||
if err == nil {
|
||||
return pkgs, nil
|
||||
}
|
||||
errorStrings[dir] = err.Error()
|
||||
}
|
||||
return nil, errors.New("could not parse dir for package name: " + packageName + " in goPaths " + strings.Join(goPaths, ", ") + " : " + fmt.Sprint(errorStrings))
|
||||
}
|
||||
|
||||
func parsePackage(goPaths []string, packageName string) (pkg *ast.Package, err error) {
|
||||
pkgs, err := parseDir(goPaths, packageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.New("could not parse package " + packageName + ": " + err.Error())
|
||||
}
|
||||
packageNameParts := strings.Split(packageName, "/")
|
||||
if len(packageNameParts) == 0 {
|
||||
|
||||
107
php.go
Normal file
107
php.go
Normal file
@ -0,0 +1,107 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"github.com/foomo/gotsrpc/config"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func renderPHPRPCServiceClients(service *Service, namespce string, g *code) error {
|
||||
g.l(`<?php`)
|
||||
g.l(`// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc`)
|
||||
g.nl()
|
||||
g.l(`namespace ` + namespce + `;`)
|
||||
g.nl()
|
||||
|
||||
g.l(`class ` + service.Name + `Client`)
|
||||
g.l(`{`)
|
||||
g.ind(1)
|
||||
|
||||
// Variables
|
||||
g.l(`public static $defaultOptions = ['http' => ['method' => 'POST', 'timeout' => 5, 'header' => 'Content-type: application/json']];`)
|
||||
g.nl()
|
||||
g.l(`private $options;`)
|
||||
g.l(`private $endpoint;`)
|
||||
g.nl()
|
||||
|
||||
// Constructor
|
||||
g.l(`/**`)
|
||||
g.l(` * @param string $endpoint`)
|
||||
g.l(` * @param array $options`)
|
||||
g.l(` */`)
|
||||
g.l(`public function __construct($endpoint, array $options=null)`)
|
||||
g.l(`{`)
|
||||
g.ind(1)
|
||||
g.l(`$this->endpoint = $endpoint;`)
|
||||
g.l(`$this->options = (is_null($options)) ? self::$defaultOptions : $options;`)
|
||||
g.ind(-1)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
|
||||
// Service methods
|
||||
for _, method := range service.Methods {
|
||||
args := []string{}
|
||||
params := []string{}
|
||||
|
||||
g.l(`/**`)
|
||||
for _, a := range method.Args {
|
||||
args = append(args, "$"+a.Name)
|
||||
params = append(params, "$"+a.Name)
|
||||
g.l(` * @param $` + a.Name)
|
||||
}
|
||||
g.l(` * @return array`)
|
||||
g.l(` */`)
|
||||
g.l(`public function ` + lcfirst(method.Name) + `(` + strings.Join(params, ", ") + `)`)
|
||||
g.l(`{`)
|
||||
g.ind(1)
|
||||
g.l(`return $this->call('` + method.Name + `', [` + strings.Join(params, ", ") + `]);`)
|
||||
g.ind(-1)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
}
|
||||
|
||||
// Protected methods
|
||||
g.l(`/**`)
|
||||
g.l(` * @param string $method`)
|
||||
g.l(` * @param array $request`)
|
||||
g.l(` * @return array`)
|
||||
g.l(` * @throws \Exception`)
|
||||
g.l(` */`)
|
||||
g.l(`protected function call($method, array $request)`)
|
||||
g.l(`{`)
|
||||
g.ind(1)
|
||||
g.l(`$options = $this->options;`)
|
||||
g.l(`$options['http']['content'] = json_encode($request);`)
|
||||
g.l(`if (false === $content = @file_get_contents($this->endpoint . '/' . $method, false, stream_context_create($options))) {`)
|
||||
g.ind(1)
|
||||
g.l(`$err = error_get_last();`)
|
||||
g.l(`throw new \Exception($err['message'], $err['type']);`)
|
||||
g.ind(-1)
|
||||
g.l(`}`)
|
||||
g.l(`return json_decode($content);`)
|
||||
g.ind(-1)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
|
||||
g.ind(-1)
|
||||
g.l(`}`)
|
||||
g.nl()
|
||||
return nil
|
||||
}
|
||||
|
||||
func RenderPHPRPCClients(services map[string]*Service, config *config.Target) (code map[string]string, err error) {
|
||||
code = map[string]string{}
|
||||
for _, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !config.IsPHPRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
target := config.GetPHPTarget(service.Name)
|
||||
g := newCode(" ")
|
||||
if err = renderPHPRPCServiceClients(service, target.Namespace, g); err != nil {
|
||||
return
|
||||
}
|
||||
code[target.Out+"/"+service.Name+"Client.php"] = g.string()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -8,22 +8,46 @@ import (
|
||||
)
|
||||
|
||||
func InstrumentService(s http.HandlerFunc) (handler http.HandlerFunc) {
|
||||
counterVec := p.NewSummaryVec(p.SummaryOpts{
|
||||
requestDuration := p.NewSummaryVec(p.SummaryOpts{
|
||||
Namespace: "gotsrpc",
|
||||
Subsystem: "service",
|
||||
Name: "time_nanoseconds",
|
||||
Help: "nanoseconds to unmarshal requests, execute a service function and marshal its reponses",
|
||||
}, []string{"package", "service", "func", "type"})
|
||||
p.MustRegister(counterVec)
|
||||
requestSize := p.NewSummaryVec(p.SummaryOpts{
|
||||
Namespace: "gotsrpc",
|
||||
Subsystem: "service",
|
||||
Name: "size_bytes",
|
||||
Help: "request and response sizes in bytes",
|
||||
}, []string{"package", "service", "func", "type"})
|
||||
|
||||
p.MustRegister(requestSize)
|
||||
p.MustRegister(requestDuration)
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
*r = *gotsrpc.RequestWithStatsContext(r)
|
||||
s.ServeHTTP(w, r)
|
||||
stats := gotsrpc.GetStatsForRequest(r)
|
||||
if stats != nil {
|
||||
counterVec.WithLabelValues(stats.Package, stats.Service, stats.Func, "unmarshalling").Observe(float64(stats.Unmarshalling))
|
||||
counterVec.WithLabelValues(stats.Package, stats.Service, stats.Func, "execution").Observe(float64(stats.Execution))
|
||||
counterVec.WithLabelValues(stats.Package, stats.Service, stats.Func, "marshalling").Observe(float64(stats.Marshalling))
|
||||
requestSize.WithLabelValues(stats.Package, stats.Service, stats.Func, "request").Observe(float64(stats.RequestSize))
|
||||
requestSize.WithLabelValues(stats.Package, stats.Service, stats.Func, "response").Observe(float64(stats.ResponseSize))
|
||||
requestDuration.WithLabelValues(stats.Package, stats.Service, stats.Func, "unmarshalling").Observe(float64(stats.Unmarshalling))
|
||||
requestDuration.WithLabelValues(stats.Package, stats.Service, stats.Func, "execution").Observe(float64(stats.Execution))
|
||||
requestDuration.WithLabelValues(stats.Package, stats.Service, stats.Func, "marshalling").Observe(float64(stats.Marshalling))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func InstrumentGoRPCService() gotsrpc.GoRPCCallStatsHandlerFun {
|
||||
callsCounter := p.NewSummaryVec(p.SummaryOpts{
|
||||
Namespace: "gorpc",
|
||||
Subsystem: "service",
|
||||
Name: "time_seconds",
|
||||
Help: "seconds to execute a service method",
|
||||
}, []string{"package", "service", "func", "type"})
|
||||
p.MustRegister(callsCounter)
|
||||
|
||||
return func(stats *gotsrpc.CallStats) {
|
||||
callsCounter.WithLabelValues(stats.Package, stats.Service, stats.Func, "execution").Observe(float64(stats.Execution))
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@ -182,13 +181,14 @@ func loadConstants(pkg *ast.Package) map[string]*ast.BasicLit {
|
||||
|
||||
}
|
||||
|
||||
func Read(goPath string, packageName string, serviceMap map[string]string) (services map[string]*Service, structs map[string]*Struct, scalars map[string]*Scalar, constants map[string]map[string]*ast.BasicLit, err error) {
|
||||
func Read(goPaths []string, packageName string, serviceMap map[string]string) (services map[string]*Service, structs map[string]*Struct, scalars map[string]*Scalar, constants map[string]map[string]*ast.BasicLit, err error) {
|
||||
if len(serviceMap) == 0 {
|
||||
err = errors.New("nothing to do service names are empty")
|
||||
return
|
||||
}
|
||||
pkg, err := parsePackage(goPath, packageName)
|
||||
if err != nil {
|
||||
pkg, parseErr := parsePackage(goPaths, packageName)
|
||||
if parseErr != nil {
|
||||
err = parseErr
|
||||
return
|
||||
}
|
||||
services, err = readServicesInPackage(pkg, packageName, serviceMap)
|
||||
@ -211,7 +211,7 @@ func Read(goPath string, packageName string, serviceMap map[string]string) (serv
|
||||
structs = map[string]*Struct{}
|
||||
scalars = map[string]*Scalar{}
|
||||
|
||||
collectErr := collectTypes(goPath, missingTypes, structs, scalars)
|
||||
collectErr := collectTypes(goPaths, missingTypes, structs, scalars)
|
||||
if collectErr != nil {
|
||||
err = errors.New("error while collecting structs: " + collectErr.Error())
|
||||
}
|
||||
@ -225,7 +225,7 @@ func Read(goPath string, packageName string, serviceMap map[string]string) (serv
|
||||
structPackage := structDef.Package
|
||||
_, ok := constants[structPackage]
|
||||
if !ok {
|
||||
pkg, constPkgErr := parsePackage(goPath, structPackage)
|
||||
pkg, constPkgErr := parsePackage(goPaths, structPackage)
|
||||
if constPkgErr != nil {
|
||||
err = constPkgErr
|
||||
return
|
||||
@ -265,7 +265,7 @@ func fixFieldStructs(fields []*Field, structs map[string]*Struct, scalars map[st
|
||||
}
|
||||
}
|
||||
|
||||
func collectTypes(goPath string, missingTypes map[string]bool, structs map[string]*Struct, scalars map[string]*Scalar) error {
|
||||
func collectTypes(goPaths []string, missingTypes map[string]bool, structs map[string]*Struct, scalars map[string]*Scalar) error {
|
||||
scannedPackageStructs := map[string]map[string]*Struct{}
|
||||
scannedPackageScalars := map[string]map[string]*Scalar{}
|
||||
missingTypeNames := func() []string {
|
||||
@ -297,19 +297,19 @@ func collectTypes(goPath string, missingTypes map[string]bool, structs map[strin
|
||||
packageStructs, structOK := scannedPackageStructs[packageName]
|
||||
packageScalars, scalarOK := scannedPackageScalars[packageName]
|
||||
if !structOK || !scalarOK {
|
||||
parsedPackageStructs, parsedPackageScalars, err := getTypesInPackage(goPath, packageName)
|
||||
parsedPackageStructs, parsedPackageScalars, err := getTypesInPackage(goPaths, packageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trace("found structs in", goPath, packageName)
|
||||
trace("found structs in", goPaths, packageName)
|
||||
for structName, strct := range packageStructs {
|
||||
trace(" struct", structName, strct)
|
||||
if strct == nil {
|
||||
panic("how could that be")
|
||||
}
|
||||
}
|
||||
trace("found scalars in", goPath, packageName)
|
||||
trace("found scalars in", goPaths, packageName)
|
||||
for scalarName, scalar := range parsedPackageScalars {
|
||||
trace(" scalar", scalarName, scalar)
|
||||
}
|
||||
@ -417,13 +417,10 @@ func (st *StructType) FullName() string {
|
||||
return fullName
|
||||
}
|
||||
|
||||
func getTypesInPackage(goPath string, packageName string) (structs map[string]*Struct, scalars map[string]*Scalar, err error) {
|
||||
pkg, err := parsePackage(goPath, packageName)
|
||||
func getTypesInPackage(goPaths []string, packageName string) (structs map[string]*Struct, scalars map[string]*Scalar, err error) {
|
||||
pkg, err := parsePackage(goPaths, packageName)
|
||||
if err != nil {
|
||||
pkg, err = parsePackage(runtime.GOROOT(), packageName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
structs, scalars, err = readStructs(pkg, packageName)
|
||||
if err != nil {
|
||||
|
||||
2
stats.go
2
stats.go
@ -7,4 +7,6 @@ type CallStats struct {
|
||||
Execution time.Duration
|
||||
Marshalling time.Duration
|
||||
Unmarshalling time.Duration
|
||||
RequestSize int
|
||||
ResponseSize int
|
||||
}
|
||||
|
||||
@ -92,7 +92,9 @@ func getScalarFromAstIdent(ident *ast.Ident) ScalarType {
|
||||
return ScalarTypeString
|
||||
case "bool":
|
||||
return ScalarTypeBool
|
||||
case "int", "int32", "int64", "float", "float32", "float64":
|
||||
case "float", "float32", "float64",
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64":
|
||||
return ScalarTypeNumber
|
||||
default:
|
||||
if ident.Obj != nil && ident.Obj.Decl != nil && reflect.ValueOf(ident.Obj.Decl).Type().String() == "*ast.TypeSpec" {
|
||||
@ -202,25 +204,27 @@ func (v *Value) loadExpr(expr ast.Expr, fileImports fileImportSpecMap) {
|
||||
v.Array = &Array{Value: &Value{}}
|
||||
|
||||
switch reflect.ValueOf(fieldArray.Elt).Type().String() {
|
||||
case "*ast.ArrayType":
|
||||
//readAstArrayType(v.Array.Value, fieldArray.Elt.(*ast.ArrayType), fileImports)
|
||||
v.Array.Value.loadExpr(fieldArray.Elt.(*ast.ArrayType), fileImports)
|
||||
case "*ast.Ident":
|
||||
readAstType(v.Array.Value, fieldArray.Elt.(*ast.Ident), fileImports)
|
||||
case "*ast.StarExpr":
|
||||
readAstStarExpr(v.Array.Value, fieldArray.Elt.(*ast.StarExpr), fileImports)
|
||||
case "*ast.ArrayType":
|
||||
//readAstArrayType(v.Array.Value, fieldArray.Elt.(*ast.ArrayType), fileImports)
|
||||
v.Array.Value.loadExpr(fieldArray.Elt.(*ast.ArrayType), fileImports)
|
||||
case "*ast.MapType":
|
||||
v.Array.Value.Map = &Map{
|
||||
Value: &Value{},
|
||||
}
|
||||
readAstMapType(v.Array.Value.Map, fieldArray.Elt.(*ast.MapType), fileImports)
|
||||
case "*ast.SelectorExpr":
|
||||
readAstSelectorExpr(v.Array.Value, fieldArray.Elt.(*ast.SelectorExpr), fileImports)
|
||||
case "*ast.StructType":
|
||||
readAstStructType(v.Array.Value, fieldArray.Elt.(*ast.StructType), fileImports)
|
||||
default:
|
||||
trace("---------------------> array of", reflect.ValueOf(fieldArray.Elt).Type().String())
|
||||
}
|
||||
case "*ast.Ident":
|
||||
|
||||
fieldIdent := expr.(*ast.Ident)
|
||||
|
||||
readAstType(v, fieldIdent, fileImports)
|
||||
case "*ast.StarExpr":
|
||||
// a pointer on sth
|
||||
|
||||
@ -285,7 +285,7 @@ func ucFirst(str string) string {
|
||||
return constPrefix
|
||||
}
|
||||
|
||||
func RenderTypeScriptServices(moduleKind config.ModuleKind, services map[string]*Service, mappings config.TypeScriptMappings, scalarTypes map[string]*Scalar, tsModuleName string) (typeScript string, err error) {
|
||||
func RenderTypeScriptServices(moduleKind config.ModuleKind, services map[string]*Service, mappings config.TypeScriptMappings, scalarTypes map[string]*Scalar, target *config.Target) (typeScript string, err error) {
|
||||
ts := newCode(" ")
|
||||
if !SkipGoTSRPC {
|
||||
|
||||
@ -299,7 +299,7 @@ func RenderTypeScriptServices(moduleKind config.ModuleKind, services map[string]
|
||||
request.open('POST', endPoint + "/" + encodeURIComponent(method), true);
|
||||
// this causes problems, when the browser decides to do a cors OPTIONS request
|
||||
// request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
request.send(JSON.stringify(args));
|
||||
request.send(JSON.stringify(args));
|
||||
request.onload = function() {
|
||||
if (request.status == 200) {
|
||||
try {
|
||||
@ -311,7 +311,7 @@ func RenderTypeScriptServices(moduleKind config.ModuleKind, services map[string]
|
||||
} else {
|
||||
err(request);
|
||||
}
|
||||
};
|
||||
};
|
||||
request.onerror = function() {
|
||||
err(request);
|
||||
};
|
||||
@ -323,11 +323,16 @@ func RenderTypeScriptServices(moduleKind config.ModuleKind, services map[string]
|
||||
if !SkipGoTSRPC {
|
||||
ts.l("} // close")
|
||||
}
|
||||
ts.l("module " + tsModuleName + " {")
|
||||
ts.l("module " + target.TypeScriptModule + " {")
|
||||
ts.ind(1)
|
||||
}
|
||||
|
||||
for endPoint, service := range services {
|
||||
// Check if we should render this service as ts rcp
|
||||
// Note: remove once there's a separate gorcp generator
|
||||
if !target.IsTSRPC(service.Name) {
|
||||
continue
|
||||
}
|
||||
err = renderService(SkipGoTSRPC, moduleKind, service, endPoint, mappings, scalarTypes, ts)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
Loading…
Reference in New Issue
Block a user