2021-10-03 14:39:42 +00:00
|
|
|
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 {
|
2021-11-28 22:08:32 +00:00
|
|
|
|
2021-10-03 14:39:42 +00:00
|
|
|
case "POST":
|
|
|
|
h_Dosome2(w, r)
|
|
|
|
default:
|
|
|
|
http.Error(w, "Method not allowed", 500)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
}
|