Simplified
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user