package server import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "io/ioutil" "log" "net/http" "net/url" "os" "reflect" "strconv" "strings" httptransport "github.com/go-kit/kit/transport/http" ) func (err Response) Error() string { b, _ := json.Marshal(err) return string(b) } func validateAPIToken(r *http.Request, clientid string) (interface{}, error) { //验证token是否有效 headerAuth := r.Header.Get("Authorization") authArr := strings.Split(headerAuth, " ") if len(authArr) != 2 { return nil, Response{ Errno: 1003, Errmsg: "auth failed", } } if authArr[0] != "Bearer" { return nil, Response{ Errno: 1004, Errmsg: "wrong auth method", } } if err := ValidateToken(authArr[1], clientid); err != nil { return nil, Response{ Errno: 1005, Errmsg: err.Error(), } } return nil, nil } func touchSessionToken(r *http.Request) { sessionId := r.Header.Get("SESSIONID") if sessionId != "" { go func() { _, err := TouchSessionToken(sessionId) if err != nil { log.Println(err) } }() } } // DecodeRequest decodes the request from the provided HTTP request, simply // by JSON decoding from the request body. It's designed to be used in // transport/http.Server. func DecodeRequest(r *http.Request, ptype reflect.Type, shouldLogin ...bool) (interface{}, error) { var pl interface{} if ptype == nil { pl = make(map[string]interface{}) } else { pl = reflect.New(ptype).Interface() } var reqItem = Request{ Payload: pl, } //TODO 优化reader sync.Pool buf, _ := ioutil.ReadAll(r.Body) log.Println(r.RequestURI, string(buf)) err := json.NewDecoder(bytes.NewReader(buf)).Decode(&reqItem) if err != nil { return nil, Response{ Errno: 101, Errmsg: err.Error(), //"wrong json fromat", } } //attach defualt wx_type if reqItem.Extra == nil { reqItem.Extra = map[string]interface{}{} } if _, ok := reqItem.Extra["wx_type"]; !ok { reqItem.Extra["wx_type"] = "" } if reqItem.ClientId == "" { return nil, Response{ Errno: 100, Errmsg: "param clientid required", } } //验证token是否有效 _, err = validateAPIToken(r, reqItem.ClientId) if err != nil { return nil, err } /*headerAuth := r.Header.Get("Authorization") authArr := strings.Split(headerAuth, " ") if len(authArr) != 2 { return nil, Response{ Errno: 1003, Errmsg: "auth failed", } } if authArr[0] != "Bearer" { return nil, Response{ Errno: 1004, Errmsg: "wrong auth method", } } if err := ValidateToken(authArr[1]); err != nil { return nil, Response{ Errno: 1005, Errmsg: err.Error(), } }*/ //根据sessionid 判断若用户已经登录,则刷新登录token //touchSessionToken(r) //判断是否需要登录 if len(shouldLogin) > 0 && shouldLogin[0] { //验证是否已经登录 sessionId := r.Header.Get("SESSIONID") if sessionId == "" { return nil, Response{ Errno: 1006, Errmsg: "miss session param", } } stoken, err := GetLoginSession(sessionId) if err != nil { return nil, Response{ Errno: 1007, Errmsg: "user should login", } } udata := stoken.Data.(string) udatas := strings.Split(udata, "-") if len(udatas) >= 2 { uid, _ := strconv.ParseInt(udatas[0], 10, 0) reqItem.UserId = int(uid) fmt.Println(udata, reqItem.UserId) reqItem.Mobile = udatas[1] } } return reqItem, err } // EncodeResponse encodes the response to the provided HTTP response // writer, simply by JSON encoding to the writer. It's designed to be used in // transport/http.Server. func EncodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") wr := io.MultiWriter(w, os.Stdout) jencoder := json.NewEncoder(wr) jencoder.SetEscapeHTML(false) return jencoder.Encode(response) } // 20220719 不打印日志,部分信息并没有太大意义。免得日志文件增长过快 func EncodeResponseNoLog(ctx context.Context, w http.ResponseWriter, response interface{}) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") //wr := io.MultiWriter(w, os.Stdout) jencoder := json.NewEncoder(w) jencoder.SetEscapeHTML(false) return jencoder.Encode(response) } func MakeDecodeRequest(ptype reflect.Type, shouldLogin ...bool) httptransport.DecodeRequestFunc { return func(ctx context.Context, r *http.Request) (interface{}, error) { return DecodeRequest(r, ptype, shouldLogin...) } } // EncodeRequest encodes the request to the provided HTTP request, simply // by JSON encoding to the request body. It's designed to be used in // transport/http.Client. func EncodeRequest(r *http.Request, request interface{}) error { var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(request); err != nil { return err } r.Body = ioutil.NopCloser(&buf) return nil } // DecodeResponse decodes the response from the provided HTTP response, // simply by JSON decoding from the response body. It's designed to be used in // transport/http.Client. func DecodeResponse(resp *http.Response, payload interface{}) (interface{}, error) { return nil, nil } func DecodeAuthRequest(ctx context.Context, req *http.Request) (interface{}, error) { rbytes, err := ioutil.ReadAll(req.Body) if err != nil { return nil, err } strReqData := string(rbytes) kv, err := url.ParseQuery(strReqData) if err != nil { return nil, err } tokenStr := kv.Get("assertion") if tokenStr == "" { return nil, errors.New("request auth data not found") } return tokenStr, nil } func DecodeFileRequest(ctx context.Context, req *http.Request) (interface{}, error) { touchSessionToken(req) clientId := req.Header.Get("clientid") if clientId == "" { return nil, Response{ Errno: 100, Errmsg: "param clientid required", } } _, err := validateAPIToken(req, clientId) if err != nil { return nil, err } req.ParseForm() file, _, _ := req.FormFile("file") return file, nil }