From ddc366e958a04f92c20c1ad1473bbe709b970a45 Mon Sep 17 00:00:00 2001 From: hzy Date: Fri, 30 Jun 2023 16:49:01 +0800 Subject: [PATCH] =?UTF-8?q?http=E5=8A=A0=E5=AF=86=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- transport/v1/http/request.go | 53 +++++++++++++++++++++++++++++++++ transport/v1/http/response.go | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/transport/v1/http/request.go b/transport/v1/http/request.go index 7138840..be7334f 100644 --- a/transport/v1/http/request.go +++ b/transport/v1/http/request.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "gitea.drugeyes.vip/pharnexbase/tools/request" + "gitea.drugeyes.vip/pharnexbase/utils/enum" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/transport/http" "github.com/go-kratos/kratos/v2/transport/http/binding" @@ -87,3 +88,55 @@ func (t *Transport) RequestDecoder() http.DecodeRequestFunc { return nil } } + +func (t *Transport) RequestDecoderWithSignFilter(noEncrypt map[string]bool) http.DecodeRequestFunc { + return func(r *http.Request, v interface{}) error { + // 从Request Header的Content-Type中提取出对应的解码器 + codec, ok := http.CodecForRequest(r, "Content-Type") + // 如果找不到对应的解码器此时会报错 + if !ok { + return errors.BadRequest("CODEC", r.Header.Get("Content-Type")) + } + data, err := io.ReadAll(r.Body) + if err != nil { + return errors.BadRequest("CODEC", err.Error()) + } + + // 将post和query参数合并 + params := make(map[string]string) + gjson.ParseBytes(data).ForEach(func(key, value gjson.Result) bool { + switch value.Type { + case gjson.JSON: + var buf bytes.Buffer + json.Compact(&buf, []byte(value.String())) + params[key.String()] = buf.String() + default: + params[key.String()] = value.String() + } + + return true + }) + for _, val := range strings.Split(r.URL.RawQuery, "&") { + vals := strings.Split(val, "=") + if len(vals) < 2 { + continue + } + params[vals[0]], _ = url.PathUnescape(vals[1]) + } + + // 正式服验签 + if t.env == enum.Env_Production && noEncrypt[r.URL.Path] { + signature := request.NewSignature(t.apiKey, request.NewSHA1HashAlg()) + signStr := signature.GenSignature(params) + if signStr != r.Header.Get("sm5") { + return SignErr + } + } + + if err = codec.Unmarshal(data, v); err != nil { + return errors.BadRequest("CODEC", err.Error()) + } + + return nil + } +} diff --git a/transport/v1/http/response.go b/transport/v1/http/response.go index 45520bd..942c116 100644 --- a/transport/v1/http/response.go +++ b/transport/v1/http/response.go @@ -125,6 +125,61 @@ func (t *Transport) ResponseEncoderWithEncrypt() http.EncodeResponseFunc { } } +func (t *Transport) ResponseEncoderWithEncryptFilter(noEncrypt map[string]bool) http.EncodeResponseFunc { + return func(w stdhttp.ResponseWriter, r *stdhttp.Request, v interface{}) error { + if v == nil { + return nil + } + + // 重定向 + if rd, ok := v.(http.Redirector); ok { + url, code := rd.Redirect() + stdhttp.Redirect(w, r, url, code) + return nil + } + + // 文件下载 + if data, ok := v.(*transPbV1.FileResponse); ok { + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", data.Filename)) + if data.Filetype != "" { + w.Header().Set("Content-Type", data.Filetype) + } + w.Header().Set("Access-Control-Expose-Headers", "*") + w.WriteHeader(stdhttp.StatusOK) + w.Write(data.Data) + + return nil + } + + codec, _ := http.CodecForRequest(r, "Accept") + data, err := codec.Marshal(v) + if err != nil { + return err + } + + dataRes := string(data) + // 正式服加密 + if t.env == enum.Env_Production && noEncrypt[r.URL.Path] { + ecbMsg, err := sm4.Sm4Ecb([]byte(t.sm4Key), data, true) + if err == nil { + dataRes = fmt.Sprintf("\"%s\"", hex.EncodeToString(ecbMsg)) + w.Header().Set("en", "4") + } + } + + w.Header().Set("Content-Type", ContentType(codec.Name())) + w.Header().Set("Access-Control-Expose-Headers", "Traceid, En ,Content-Disposition, Authorization") + + d := fmt.Sprintf(`{"code": 200,"data": %s,"reason": "","message": ""}`, dataRes) + + _, err = w.Write([]byte(d)) + if err != nil { + return err + } + return nil + } +} + func (t *Transport) ErrorEncoder() http.EncodeErrorFunc { return func(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) { se := errors.FromError(err)