gotsrpc/go.go

200 lines
4.7 KiB
Go

package gotsrpc
import (
"fmt"
"strings"
)
func (v *Value) isHTTPResponseWriter() bool {
return v.StructType != nil && v.StructType.Name == "ResponseWriter" && v.StructType.Package == "http"
}
func (v *Value) isHTTPRequest() bool {
return v.IsPtr && v.StructType != nil && v.StructType.Name == "Request" && v.StructType.Package == "http"
}
func (v *Value) goType() (t string) {
if v.IsPtr {
t = "*"
}
switch true {
case v.Array != nil:
t += "[]" + v.Array.Value.goType()
case len(v.GoScalarType) > 0:
t += v.GoScalarType
case v.StructType != nil:
t += v.StructType.Name
}
return
}
func (v *Value) emptyLiteral() (e string) {
e = ""
if v.IsPtr {
e += "&"
}
switch true {
case len(v.GoScalarType) > 0:
switch v.GoScalarType {
case "string":
e += "\"\""
case "float":
return "float(0.0)"
case "float32":
return "float32(0.0)"
case "float64":
return "float64(0.0)"
case "int":
return "int(0)"
case "int32":
return "int32(0)"
case "int64":
return "int64(0)"
case "bool":
return "false"
}
case v.Array != nil:
e += "[]" + v.Array.Value.emptyLiteral() + "{}"
case v.StructType != nil:
e += v.StructType.Name + "{}"
}
return
}
func lcfirst(str string) string {
return strfirst(str, strings.ToLower)
}
func ucfirst(str string) string {
return strfirst(str, strings.ToUpper)
}
func strfirst(str string, strfunc func(string) string) string {
if len(str) == 0 {
return ""
} else if len(str) == 1 {
return strfunc(str)
}
return strfunc(str[0:1]) + str[1:]
}
func renderServiceProxies(services []*Service, packageName string, g *code) error {
g.l(`
// this file was auto generated by gotsrpc https://github.com/foomo/gotsrpc
package ` + packageName + `
import (
"net/http"
"github.com/foomo/gotsrpc"
)
`)
for _, service := range services {
proxyName := service.Name + "GoTSRPCProxy"
g.l(`
type ` + proxyName + ` struct {
EndPoint string
allowOrigin []string
service *` + service.Name + `
}
func New` + proxyName + `(service *` + service.Name + `, endpoint string, allowOrigin []string) *` + proxyName + ` {
return &` + proxyName + `{
EndPoint: endpoint,
allowOrigin : allowOrigin,
service: service,
}
}
// ServeHTTP exposes your service
func (p *` + proxyName + `) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, origin := range p.allowOrigin {
w.Header().Add("Access-Control-Allow-Origin", origin)
}
if r.Method != "POST" {
gotsrpc.ErrorMethodNotAllowed(w)
return
}
var args []interface{}
switch gotsrpc.GetCalledFunc(r, p.EndPoint) {`)
// indenting into switch cases
g.ind(4)
for _, method := range service.Methods {
// a case for each method
g.l("case \"" + method.Name + "\":")
g.ind(1)
callArgs := []string{}
isSessionRequest := false
if len(method.Args) > 0 {
args := []string{}
for argI, arg := range method.Args {
if argI == 0 && arg.Value.isHTTPResponseWriter() {
trace("skipping first arg is a http.ResponseWriter")
continue
}
if argI == 1 && arg.Value.isHTTPRequest() {
trace("skipping second arg is a *http.Request")
isSessionRequest = true
continue
}
args = append(args, arg.Value.emptyLiteral())
callArgs = append(callArgs, fmt.Sprint("args[", argI, "].("+arg.Value.goType()+")"))
}
g.l("args = []interface{}{" + strings.Join(args, ", ") + "}")
g.l("err := gotsrpc.LoadArgs(args, r)")
g.l("if err != nil {")
g.ind(1)
g.l("gotsrpc.ErrorCouldNotLoadArgs(w)")
g.l("return")
g.ind(-1)
g.l("}")
}
returnValueNames := []string{}
for retI, retField := range method.Return {
retArgName := retField.Name
if len(retArgName) == 0 {
retArgName = "ret"
if retI > 0 {
retArgName += "_" + fmt.Sprint(retI)
}
}
returnValueNames = append(returnValueNames, lcfirst(method.Name)+ucfirst(retArgName))
}
if len(returnValueNames) > 0 {
g.app(strings.Join(returnValueNames, ", ") + " := ")
}
if isSessionRequest {
callArgs = append([]string{"w", "r"}, callArgs...)
}
g.app("p.service." + method.Name + "(" + strings.Join(callArgs, ", ") + ")")
g.nl()
g.l("gotsrpc.Reply([]interface{}{" + strings.Join(returnValueNames, ", ") + "}, w)")
g.l("return")
g.ind(-1)
}
g.ind(-1).l("}") // close switch
g.ind(-1).l("}") // close ServeHttp
}
return nil
}
func RenderGo(services []*Service, packageName string) (gocode string, err error) {
g := newCode()
err = renderServiceProxies(services, packageName, g)
if err != nil {
return
}
gocode = g.string()
return
}