Simplified
parent
5893ad898b
commit
984592b7fd
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module go.digitalcircle.com.br/tools/apigen
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/kong v0.2.15
|
github.com/alecthomas/kong v0.2.17
|
||||||
github.com/fatih/structtag v1.2.0
|
github.com/fatih/structtag v1.2.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -1,5 +1,7 @@
|
||||||
github.com/alecthomas/kong v0.2.15 h1:HP3K1XuFn0wGSWFGVW67V+65tXw/Ht8FDYiLNAuX2Ug=
|
github.com/alecthomas/kong v0.2.15 h1:HP3K1XuFn0wGSWFGVW67V+65tXw/Ht8FDYiLNAuX2Ug=
|
||||||
github.com/alecthomas/kong v0.2.15/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
github.com/alecthomas/kong v0.2.15/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||||
|
github.com/alecthomas/kong v0.2.17 h1:URDISCI96MIgcIlQyoCAlhOmrSw6pZScBNkctg8r0W0=
|
||||||
|
github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -40,6 +42,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
|
@ -54,3 +57,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fatih/structtag"
|
"github.com/fatih/structtag"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
@ -117,18 +118,33 @@ func addStruct(a *ast.GenDecl) {
|
||||||
api.Types[tp.Name] = &tp
|
api.Types[tp.Name] = &tp
|
||||||
}
|
}
|
||||||
|
|
||||||
func addFunction(a *ast.FuncDecl) {
|
func addFunction(a *ast.FuncDecl) error {
|
||||||
md := manageComments(a.Doc)
|
md := manageComments(a.Doc)
|
||||||
|
|
||||||
if md["API"] == "" {
|
if md["API"] == "" {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
llog("Adding Fuction: %s => %#v", a.Name, md)
|
llog("Adding Fuction: %s => %#v", a.Name, md)
|
||||||
reqType := &APIParamType{}
|
reqType := &APIParamType{}
|
||||||
resType := &APIParamType{}
|
resType := &APIParamType{}
|
||||||
|
|
||||||
if len(a.Type.Params.List) > 1 {
|
if len(a.Type.Params.List) != 2 {
|
||||||
|
return errors.New(fmt.Sprintf("Function %s does not have 2 IN parameters (context and pointer to req struct)", a.Name.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a.Type.Results.List) != 2 {
|
||||||
|
return errors.New(fmt.Sprintf("Function %s does not have 2 OUT parameters (pointer to res struct and err)", a.Name.Name))
|
||||||
|
}
|
||||||
|
if a.Type.Results.List[1].Type.(*ast.Ident).Name != "error" {
|
||||||
|
return errors.New(fmt.Sprintf("Function %s does not have error as 2nd OUT parameter", a.Name.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
p0tp := a.Type.Params.List[0].Type.(*ast.SelectorExpr)
|
||||||
|
if p0tp.X.(*ast.Ident).Name != "context" && p0tp.Sel.Name != "Context" {
|
||||||
|
return errors.New(fmt.Sprintf("Function %s, param 1 is not of type context.Context", a.Name))
|
||||||
|
}
|
||||||
|
|
||||||
switch x := a.Type.Params.List[1].Type.(type) {
|
switch x := a.Type.Params.List[1].Type.(type) {
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
reqType.Ispointer = true
|
reqType.Ispointer = true
|
||||||
|
@ -139,33 +155,10 @@ func addFunction(a *ast.FuncDecl) {
|
||||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||||
}
|
}
|
||||||
case *ast.ArrayType:
|
default:
|
||||||
reqType.IsArray = true
|
return errors.New(fmt.Sprintf("Function %s does not have 2 IN parameters (context and pointer to req struct)", a.Name.Name))
|
||||||
switch y := x.Elt.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
reqType.Typename = y.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
|
||||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
|
||||||
case *ast.StarExpr:
|
|
||||||
reqType.Ispointer = true
|
|
||||||
switch z := y.X.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
reqType.Typename = z.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[z.X.(*ast.Ident).Name] = api.Imports[z.X.(*ast.Ident).Name]
|
|
||||||
reqType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.Ident:
|
|
||||||
reqType.Typename = x.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[x.X.(*ast.Ident).Name] = api.Imports[x.X.(*ast.Ident).Name]
|
|
||||||
reqType.Typename = x.X.(*ast.Ident).Name + "." + x.Sel.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Type.Results != nil && len(a.Type.Results.List) > 0 {
|
}
|
||||||
|
|
||||||
switch x := a.Type.Results.List[0].Type.(type) {
|
switch x := a.Type.Results.List[0].Type.(type) {
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
|
@ -177,29 +170,8 @@ func addFunction(a *ast.FuncDecl) {
|
||||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||||
}
|
}
|
||||||
case *ast.ArrayType:
|
default:
|
||||||
resType.IsArray = true
|
return errors.New(fmt.Sprintf("Function %s does not have 2 OUT parameters (pointer to res struct and err)", a.Name.Name))
|
||||||
switch y := x.Elt.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
resType.Typename = y.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
|
||||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
|
||||||
case *ast.StarExpr:
|
|
||||||
resType.Ispointer = true
|
|
||||||
switch z := y.X.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
resType.Typename = z.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[z.X.(*ast.Ident).Name] = api.Imports[z.X.(*ast.Ident).Name]
|
|
||||||
resType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.Ident:
|
|
||||||
resType.Typename = x.Name
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
api.UsedImportsFunctions[x.X.(*ast.Ident).Name] = api.Imports[x.X.(*ast.Ident).Name]
|
|
||||||
resType.Typename = x.X.(*ast.Ident).Name + "." + x.Sel.Name
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,8 +199,8 @@ func addFunction(a *ast.FuncDecl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
api.Methods[a.Name.Name] = &fn
|
api.Methods[a.Name.Name] = &fn
|
||||||
}
|
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func load(src string) error {
|
func load(src string) error {
|
||||||
|
@ -255,6 +227,11 @@ func load(src string) error {
|
||||||
// Print the AST.
|
// Print the AST.
|
||||||
ast.Inspect(v, func(n ast.Node) bool {
|
ast.Inspect(v, func(n ast.Node) bool {
|
||||||
|
|
||||||
|
//tp := reflect.TypeOf(n)
|
||||||
|
//if tp != nil {
|
||||||
|
// log.Printf("Type: %#v", tp.String())
|
||||||
|
//}
|
||||||
|
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
|
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
|
@ -278,7 +255,10 @@ func load(src string) error {
|
||||||
case *ast.File:
|
case *ast.File:
|
||||||
manageCommentsGroups(x.Comments)
|
manageCommentsGroups(x.Comments)
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
addFunction(x)
|
err = addFunction(x)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
llog("Adding fn: %s", x.Name)
|
llog("Adding fn: %s", x.Name)
|
||||||
case *ast.ValueSpec:
|
case *ast.ValueSpec:
|
||||||
if x.Names[0].Name == "BASEPATH" {
|
if x.Names[0].Name == "BASEPATH" {
|
||||||
|
@ -341,5 +321,5 @@ func load(src string) error {
|
||||||
|
|
||||||
api.Namespace = packageName
|
api.Namespace = packageName
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,113 @@ func processGoServerOutput(f string) error {
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
"net/http"
|
"net/http"
|
||||||
)`)
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)`)
|
||||||
|
|
||||||
for k := range api.UsedImportsFunctions {
|
for k := range api.UsedImportsFunctions {
|
||||||
WNL(`import "%s"`, k)
|
WNL(`import "%s"`, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WNL(`func handleTag(s string, r *http.Request) string {
|
||||||
|
parts := strings.Split(s, ":")
|
||||||
|
where := "Q"
|
||||||
|
key := ""
|
||||||
|
if len(parts) == 1 {
|
||||||
|
key = parts[0]
|
||||||
|
} else {
|
||||||
|
where = parts[0]
|
||||||
|
key = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch where {
|
||||||
|
case "Q":
|
||||||
|
return r.URL.Query().Get(key)
|
||||||
|
case "H":
|
||||||
|
return r.Header.Get(key)
|
||||||
|
case "P":
|
||||||
|
switch key {
|
||||||
|
case "*":
|
||||||
|
return r.URL.Path
|
||||||
|
case "last":
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
return pps[len(pps)-1]
|
||||||
|
case "len":
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
return strconv.Itoa(len(pps))
|
||||||
|
default:
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
n, _ := strconv.Atoi(key)
|
||||||
|
if n < len(pps) {
|
||||||
|
return pps[n]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert(s string, tpname string) interface{} {
|
||||||
|
switch tpname {
|
||||||
|
case "string":
|
||||||
|
return s
|
||||||
|
|
||||||
|
case "int":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return v
|
||||||
|
case "int8":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int8(v)
|
||||||
|
case "int16":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int16(v)
|
||||||
|
case "int32":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int32(v)
|
||||||
|
case "int64":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int64(v)
|
||||||
|
case "uint":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return uint(v)
|
||||||
|
case "float32":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return float32(v)
|
||||||
|
case "float64":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return float64(v)
|
||||||
|
case "bool":
|
||||||
|
return s == "true" || s == "1" || s == "Y"
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map(r *http.Request, in interface{}) error {
|
||||||
|
|
||||||
|
tp := reflect.TypeOf(in)
|
||||||
|
vl := reflect.ValueOf(in)
|
||||||
|
if tp.Kind() == reflect.Ptr {
|
||||||
|
tp = tp.Elem()
|
||||||
|
vl = vl.Elem()
|
||||||
|
}
|
||||||
|
if tp.Kind() != reflect.Struct {
|
||||||
|
return errors.New("Type is not struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < tp.NumField(); i++ {
|
||||||
|
k, ok := tp.Field(i).Tag.Lookup("in")
|
||||||
|
if ok {
|
||||||
|
str := handleTag(k, r)
|
||||||
|
v := convert(str, tp.Field(i).Type.Name())
|
||||||
|
strv := reflect.ValueOf(v)
|
||||||
|
vl.Field(i).Set(strv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
WNL(`type API struct {
|
WNL(`type API struct {
|
||||||
Mux *http.ServeMux
|
Mux *http.ServeMux
|
||||||
Perms map[string]string
|
Perms map[string]string
|
||||||
|
@ -47,41 +148,6 @@ func (a *API) GetPerm(r *http.Request) string {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
WNL(`func Init() *API{
|
|
||||||
mux := &http.ServeMux{}
|
|
||||||
|
|
||||||
ret := &API{
|
|
||||||
Mux: mux,
|
|
||||||
Perms: make(map[string]string),
|
|
||||||
}`)
|
|
||||||
for _, v := range api.Methods {
|
|
||||||
if v.Perm != "" {
|
|
||||||
WNL(` ret.Perms["%s_%s"]="%s"`, v.Verb, v.Path, v.Perm)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for _, v := range api.SortedPaths {
|
|
||||||
WNL(` mux.HandleFunc("%s",func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
switch r.Method {`, v.Path)
|
|
||||||
for _, v1 := range v.SortedVerbs {
|
|
||||||
WNL(` case "%s":`, v1.Method.Verb)
|
|
||||||
if v1.Method.Raw {
|
|
||||||
WNL(` %s(w,r)`, v1.Method.Name)
|
|
||||||
} else {
|
|
||||||
WNL(` h_%s(w,r)`, v1.Method.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WNL(` default:
|
|
||||||
http.Error(w,"Method not allowed",500)
|
|
||||||
}`)
|
|
||||||
|
|
||||||
}
|
|
||||||
WNL(` })`)
|
|
||||||
|
|
||||||
WNL(` return ret
|
|
||||||
}`)
|
|
||||||
|
|
||||||
for _, v := range api.Methods {
|
for _, v := range api.Methods {
|
||||||
WNL(`func h_%s(w http.ResponseWriter, r *http.Request) {
|
WNL(`func h_%s(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
@ -90,6 +156,12 @@ func (a *API) GetPerm(r *http.Request) string {
|
||||||
|
|
||||||
WNL(" req := %s", ResImplType(v.ReqType))
|
WNL(" req := %s", ResImplType(v.ReqType))
|
||||||
|
|
||||||
|
WNL(` err:=Map(r,req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}`)
|
||||||
|
|
||||||
WNL(` if r.Method!=http.MethodGet && r.Method!=http.MethodHead {`)
|
WNL(` if r.Method!=http.MethodGet && r.Method!=http.MethodHead {`)
|
||||||
|
|
||||||
if v.ReqType.Ispointer || v.ReqType.IsArray {
|
if v.ReqType.Ispointer || v.ReqType.IsArray {
|
||||||
|
@ -119,5 +191,41 @@ func (a *API) GetPerm(r *http.Request) string {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WNL(`func Init() *API{
|
||||||
|
mux := &http.ServeMux{}
|
||||||
|
|
||||||
|
ret := &API{
|
||||||
|
Mux: mux,
|
||||||
|
Perms: make(map[string]string),
|
||||||
|
}`)
|
||||||
|
for _, v := range api.Methods {
|
||||||
|
if v.Perm != "" {
|
||||||
|
WNL(` ret.Perms["%s_%s"]="%s"`, v.Verb, v.Path, v.Perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
for _, v := range api.SortedPaths {
|
||||||
|
WNL(` mux.HandleFunc("%s",func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {`, v.Path)
|
||||||
|
for _, v1 := range v.SortedVerbs {
|
||||||
|
WNL(` case "%s":`, v1.Method.Verb)
|
||||||
|
if v1.Method.Raw {
|
||||||
|
WNL(` %s(w,r)`, v1.Method.Name)
|
||||||
|
} else {
|
||||||
|
WNL(` h_%s(w,r)`, v1.Method.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WNL(` default:
|
||||||
|
http.Error(w,"Method not allowed",500)
|
||||||
|
}`)
|
||||||
|
|
||||||
|
WNL(` })`)
|
||||||
|
}
|
||||||
|
|
||||||
|
WNL(` return ret
|
||||||
|
}`)
|
||||||
|
|
||||||
return os.WriteFile(f, buf.Bytes(), 0600)
|
return os.WriteFile(f, buf.Bytes(), 0600)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from typing import List
|
||||||
|
#region Base
|
||||||
|
|
||||||
|
|
||||||
|
__ctx = {"apibase":""}
|
||||||
|
|
||||||
|
|
||||||
|
def SetAPIBase(s: str):
|
||||||
|
__ctx["apibase"] = s
|
||||||
|
|
||||||
|
|
||||||
|
def GetAPIBase() -> str:
|
||||||
|
return __ctx["apibase"]
|
||||||
|
|
||||||
|
|
||||||
|
def SetCookie(s: str):
|
||||||
|
__ctx["cookie"] = s
|
||||||
|
|
||||||
|
|
||||||
|
def GetCookie() -> str:
|
||||||
|
return __ctx["cookie"]
|
||||||
|
|
||||||
|
|
||||||
|
def InvokeTxt(path: str, method: str, body) -> str:
|
||||||
|
headers = {"Content-type": "application/json", "Cookie": "dc="+GetCookie()}
|
||||||
|
fpath = GetAPIBase() + path
|
||||||
|
r = requests.request(method, fpath, json=body, headers=headers)
|
||||||
|
return r.text
|
||||||
|
|
||||||
|
|
||||||
|
def InvokeJSON(path: str, method: str, body) -> dict:
|
||||||
|
d = body.__dict__
|
||||||
|
return json.loads(InvokeTxt(path, method, d))
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Types
|
||||||
|
@ dataclass
|
||||||
|
class SomeReq :
|
||||||
|
fielda: str
|
||||||
|
|
||||||
|
|
||||||
|
@ dataclass
|
||||||
|
class SomeRes :
|
||||||
|
msg: str
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
def Dosome(req:SomeReq)-> SomeRes:
|
||||||
|
return InvokeJSON("/some","POST",req)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
|
@ -0,0 +1,101 @@
|
||||||
|
//#region Base
|
||||||
|
|
||||||
|
|
||||||
|
var apibase="";
|
||||||
|
|
||||||
|
export function SetAPIBase(s:string){
|
||||||
|
apibase=s;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetAPIBase(): string{
|
||||||
|
return apibase;
|
||||||
|
}
|
||||||
|
|
||||||
|
let REGEX_DATE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/
|
||||||
|
|
||||||
|
type HTMLMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "TRACE"
|
||||||
|
|
||||||
|
async function Invoke(path: string, method: HTMLMethod, body?: any): Promise<Response> {
|
||||||
|
let jbody = undefined
|
||||||
|
let init = {method: method, mode: "cors", credentials: "include", withCredentials: true}
|
||||||
|
if (!!body) {
|
||||||
|
let jbody = JSON.stringify(body)
|
||||||
|
//@ts-ignore
|
||||||
|
init.body = jbody
|
||||||
|
}
|
||||||
|
if (apibase.endsWith("/") && path.startsWith("/")) {
|
||||||
|
path = path.substr(1, path.length)
|
||||||
|
}
|
||||||
|
let fpath = (apibase + path)
|
||||||
|
//@ts-ignore
|
||||||
|
let res = await fetch(fpath, init)
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
async function InvokeJSON(path: string, method: HTMLMethod, body?: any): Promise<any> {
|
||||||
|
|
||||||
|
let txt = await InvokeTxt(path, method, body)
|
||||||
|
if (txt == "") {
|
||||||
|
txt = "{}"
|
||||||
|
}
|
||||||
|
let ret = JSON.parse(txt, (k: string, v: string) => {
|
||||||
|
if (REGEX_DATE.exec(v)) {
|
||||||
|
return new Date(v)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
async function InvokeTxt(path: string, method: HTMLMethod, body?: any): Promise<string> {
|
||||||
|
//@ts-ignore
|
||||||
|
let res = await Invoke(path, method, body)
|
||||||
|
|
||||||
|
let txt = await res.text()
|
||||||
|
|
||||||
|
if (res.status < 200 || res.status >= 400) {
|
||||||
|
// webix.alert("API Error:" + res.status + "\n" + txt)
|
||||||
|
console.error("API Error:" + res.status + "\n" + txt)
|
||||||
|
let e = new Error(txt)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
async function InvokeOk(path: string, method: HTMLMethod, body?: any): Promise<boolean> {
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
let res = await Invoke(path, method, body)
|
||||||
|
|
||||||
|
let txt = await res.text()
|
||||||
|
if (res.status >= 400) {
|
||||||
|
console.error("API Error:" + res.status + "\n" + txt)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Types
|
||||||
|
export interface SomeReq {
|
||||||
|
fielda ?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SomeRes {
|
||||||
|
msg ?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Methods
|
||||||
|
/**
|
||||||
|
Dosome*/
|
||||||
|
export async function Dosome(req:SomeReq):Promise<SomeRes>{
|
||||||
|
return InvokeJSON("/some","POST",req)
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
|
@ -0,0 +1,201 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleTag(s string, r *http.Request) string {
|
||||||
|
parts := strings.Split(s, ":")
|
||||||
|
where := "Q"
|
||||||
|
key := ""
|
||||||
|
if len(parts) == 1 {
|
||||||
|
key = parts[0]
|
||||||
|
} else {
|
||||||
|
where = parts[0]
|
||||||
|
key = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch where {
|
||||||
|
case "Q":
|
||||||
|
return r.URL.Query().Get(key)
|
||||||
|
case "H":
|
||||||
|
return r.Header.Get(key)
|
||||||
|
case "P":
|
||||||
|
switch key {
|
||||||
|
case "*":
|
||||||
|
return r.URL.Path
|
||||||
|
case "last":
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
return pps[len(pps)-1]
|
||||||
|
case "len":
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
return strconv.Itoa(len(pps))
|
||||||
|
default:
|
||||||
|
pps := strings.Split(r.URL.Path, "/")
|
||||||
|
n, _ := strconv.Atoi(key)
|
||||||
|
if n < len(pps) {
|
||||||
|
return pps[n]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert(s string, tpname string) interface{} {
|
||||||
|
switch tpname {
|
||||||
|
case "string":
|
||||||
|
return s
|
||||||
|
|
||||||
|
case "int":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return v
|
||||||
|
case "int8":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int8(v)
|
||||||
|
case "int16":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int16(v)
|
||||||
|
case "int32":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int32(v)
|
||||||
|
case "int64":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return int64(v)
|
||||||
|
case "uint":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return uint(v)
|
||||||
|
case "float32":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return float32(v)
|
||||||
|
case "float64":
|
||||||
|
v, _ := strconv.Atoi(s)
|
||||||
|
return float64(v)
|
||||||
|
case "bool":
|
||||||
|
return s == "true" || s == "1" || s == "Y"
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map(r *http.Request, in interface{}) error {
|
||||||
|
|
||||||
|
tp := reflect.TypeOf(in)
|
||||||
|
vl := reflect.ValueOf(in)
|
||||||
|
if tp.Kind() == reflect.Ptr {
|
||||||
|
tp = tp.Elem()
|
||||||
|
vl = vl.Elem()
|
||||||
|
}
|
||||||
|
if tp.Kind() != reflect.Struct {
|
||||||
|
return errors.New("Type is not struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < tp.NumField(); i++ {
|
||||||
|
k, ok := tp.Field(i).Tag.Lookup("in")
|
||||||
|
if ok {
|
||||||
|
str := handleTag(k, r)
|
||||||
|
v := convert(str, tp.Field(i).Type.Name())
|
||||||
|
strv := reflect.ValueOf(v)
|
||||||
|
vl.Field(i).Set(strv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type API struct {
|
||||||
|
Mux *http.ServeMux
|
||||||
|
Perms map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) GetPerm(r *http.Request) string {
|
||||||
|
return a.Perms[r.Method+"_"+strings.Split(r.RequestURI, "?")[0]]
|
||||||
|
}
|
||||||
|
|
||||||
|
func h_Dosome(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
ctx = context.WithValue(r.Context(), "REQ", r)
|
||||||
|
ctx = context.WithValue(ctx, "RES", w)
|
||||||
|
req := &SomeReq{}
|
||||||
|
err := Map(r, req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||||
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res, err := Dosome(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Add("Content-Type", "Application/json")
|
||||||
|
err = json.NewEncoder(w).Encode(res)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func h_Dosome2(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
ctx = context.WithValue(r.Context(), "REQ", r)
|
||||||
|
ctx = context.WithValue(ctx, "RES", w)
|
||||||
|
req := &SomeReq2{}
|
||||||
|
err := Map(r, req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||||
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res, err := Dosome2(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Add("Content-Type", "Application/json")
|
||||||
|
err = json.NewEncoder(w).Encode(res)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Init() *API {
|
||||||
|
mux := &http.ServeMux{}
|
||||||
|
|
||||||
|
ret := &API{
|
||||||
|
Mux: mux,
|
||||||
|
Perms: make(map[string]string),
|
||||||
|
}
|
||||||
|
mux.HandleFunc("/some", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
h_Dosome(w, r)
|
||||||
|
default:
|
||||||
|
http.Error(w, "Method not allowed", 500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/some2", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
h_Dosome2(w, r)
|
||||||
|
default:
|
||||||
|
http.Error(w, "Method not allowed", 500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//@API
|
||||||
|
type SomeReq struct {
|
||||||
|
Fielda string `json:"fielda"`
|
||||||
|
Fieldb time.Time `json:"fielda"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//@API
|
||||||
|
type SomeReq2 struct {
|
||||||
|
Fielda string `json:"fielda"`
|
||||||
|
Fieldb time.Time `json:"fielda"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//@API
|
||||||
|
type SomeRes struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//@API
|
||||||
|
//@PATH: /some
|
||||||
|
//@VERB: POST
|
||||||
|
func Dosome(ctx context.Context, req *SomeReq) (res *SomeRes, err error) {
|
||||||
|
res = &SomeRes{Msg: fmt.Sprintf("%s: %s", req.Fielda, req.Fieldb.String())}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//@API
|
||||||
|
//@PATH: /some2
|
||||||
|
//@VERB: POST
|
||||||
|
func Dosome2(ctx context.Context, req *SomeReq2) (res *SomeRes, err error) {
|
||||||
|
res = &SomeRes{Msg: fmt.Sprintf("%s: %s", req.Fielda, req.Fieldb.String())}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Basepath string = ""
|
||||||
|
var Host string = ""
|
||||||
|
var ExtraHeaders map[string]string = make(map[string]string)
|
||||||
|
|
||||||
|
var cli *http.Client
|
||||||
|
|
||||||
|
func SetCli(nc *http.Client) {
|
||||||
|
cli = nc
|
||||||
|
}
|
||||||
|
|
||||||
|
func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
err := json.NewEncoder(b).Encode(bodyo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body := bytes.NewReader(b.Bytes())
|
||||||
|
req, err := http.NewRequest(m, Host+Basepath+path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-type", "application/json")
|
||||||
|
|
||||||
|
for k, v := range ExtraHeaders {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := cli.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode >= 400 {
|
||||||
|
bs, err := ioutil.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, errors.New(string(bs))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := json.NewDecoder(res.Body)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type SomeReq struct {
|
||||||
|
Fielda string
|
||||||
|
Fieldb time.Time
|
||||||
|
}
|
||||||
|
type SomeReq2 struct {
|
||||||
|
Fielda string
|
||||||
|
Fieldb time.Time
|
||||||
|
}
|
||||||
|
type SomeRes struct {
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Dosome(req *SomeReq) (res *SomeRes, err error) {
|
||||||
|
var dec *json.Decoder
|
||||||
|
dec, err = invoke("POST", "/some", req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ret *SomeRes = &SomeRes{}
|
||||||
|
err = dec.Decode(ret)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
func Dosome2(req *SomeReq2) (res *SomeRes, err error) {
|
||||||
|
var dec *json.Decoder
|
||||||
|
dec, err = invoke("POST", "/some2", req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ret *SomeRes = &SomeRes{}
|
||||||
|
err = dec.Decode(ret)
|
||||||
|
return ret, err
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
api "go.digitalcircle.com.br/tools/apigen/test/demo/cli"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
api.Host = "http://localhost:8080"
|
||||||
|
api.SetCli(&http.Client{})
|
||||||
|
res, err := api.Dosome(&api.SomeReq{
|
||||||
|
Fielda: "ASD123",
|
||||||
|
Fieldb: time.Unix(0, 0),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
log.Printf("%#v", res)
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.digitalcircle.com.br/tools/apigen/test/demo/api"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
aapi := api.Init()
|
||||||
|
http.ListenAndServe(":8080", aapi.Mux)
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
POST http://localhost:8080/some
|
||||||
|
|
||||||
|
{"fielda":"Hello World","fieldb":""}
|
|
@ -25,7 +25,7 @@ type AStr struct {
|
||||||
@PERM: ASD
|
@PERM: ASD
|
||||||
@VERB: POST
|
@VERB: POST
|
||||||
*/
|
*/
|
||||||
func SomeAPI(ctx context.Context, s *AStr) (out *AStr, err error) {
|
func SomeAPI(ctx context.Context, s *AStr, c int) (out *AStr, err error) {
|
||||||
//print("Got:" + s)
|
//print("Got:" + s)
|
||||||
//out = time.Now().String() + " - Hey Ya!"
|
//out = time.Now().String() + " - Hey Ya!"
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
package goapi
|
package goapi
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
import "crypto"
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var Basepath string = ""
|
var Basepath string = ""
|
||||||
var Host string = ""
|
var Host string = ""
|
||||||
var ExtraHeaders map[string]string = make(map[string]string)
|
var ExtraHeaders map[string]string = make(map[string]string)
|
||||||
|
|
||||||
|
var Ver string = ""
|
||||||
|
var cli http.Client
|
||||||
|
|
||||||
|
func SetCli(nc http.Client) {
|
||||||
|
cli = nc
|
||||||
|
}
|
||||||
|
|
||||||
func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
err := json.NewEncoder(b).Encode(bodyo)
|
err := json.NewEncoder(b).Encode(bodyo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
body := bytes.NewReader(b.Bytes())
|
body := bytes.NewReader(b.Bytes())
|
||||||
req, err := http.NewRequest(m, Host+Basepath+path, body)
|
req, err := http.NewRequest(m, Host+Basepath+path, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,19 +40,19 @@ func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
cli := http.Client{}
|
|
||||||
res, err := cli.Do(req)
|
res, err := cli.Do(req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
if res.StatusCode >= 400 {
|
if res.StatusCode >= 400 {
|
||||||
bs, err := ioutil.ReadAll(res.Body)
|
bs, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New(string(bs))
|
return nil, errors.New(string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,65 +61,24 @@ func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type AStr struct {
|
type AStr struct {
|
||||||
Arrofpstr []string
|
|
||||||
|
|
||||||
City string
|
|
||||||
|
|
||||||
Country string
|
|
||||||
|
|
||||||
HouseNumber int64
|
HouseNumber int64
|
||||||
|
|
||||||
IsCondo bool
|
|
||||||
|
|
||||||
Recursive map[string]AStr
|
|
||||||
|
|
||||||
Some crypto.Decrypter
|
|
||||||
|
|
||||||
SomeWeirdTest string
|
SomeWeirdTest string
|
||||||
|
Recursive map[string]AStr
|
||||||
When time.Time
|
When time.Time
|
||||||
|
Some crypto.Decrypter
|
||||||
|
Country string
|
||||||
|
City string
|
||||||
|
IsCondo bool
|
||||||
|
Arrofpstr []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SomeAPI(req string) (res string, err error) {
|
func SomeAPI(req *AStr) (res *AStr, err error) {
|
||||||
var dec *json.Decoder
|
var dec *json.Decoder
|
||||||
dec, err = invoke("POST", "/someapi", req)
|
dec, err = invoke("POST", "/someapi", req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var ret string
|
var ret *AStr = &AStr{}
|
||||||
err = dec.Decode(ret)
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SomeAPI2(req crypto.Hash) (res []string, err error) {
|
|
||||||
var dec *json.Decoder
|
|
||||||
dec, err = invoke("DELETE", "/someapi", req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var ret []string
|
|
||||||
err = dec.Decode(ret)
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SomeGET(req string) (res string, err error) {
|
|
||||||
var dec *json.Decoder
|
|
||||||
dec, err = invoke("GET", "/someapi", req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var ret string
|
|
||||||
err = dec.Decode(ret)
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SomePUT(req string) (res string, err error) {
|
|
||||||
var dec *json.Decoder
|
|
||||||
dec, err = invoke("PUT", "/someapi", req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var ret string
|
|
||||||
err = dec.Decode(ret)
|
err = dec.Decode(ret)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue