package request import ( "context" "io" "lone-services/pkg/utils" "net/http" "net/url" "strconv" "strings" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) type ctxKey string const ( CtxUserId ctxKey = "X-User-Id" CtxUserName ctxKey = "X-User-Name" CtxRefresh ctxKey = "X-Refresh" CtxClientIP ctxKey = "X-Client-Ip" CtxUserAgent ctxKey = "X-User-Agent" CtxClientCode ctxKey = "X-Client-Code" CtxSaleId ctxKey = "X-Sale-Id" CtxSaleName ctxKey = "X-Sale-Name" CtxSaleMobile ctxKey = "X-Sale-Mobile" CtxSaleProvince ctxKey = "X-Sale-Province" CtxStoreId ctxKey = "X-Store-Id" CtxStoreName ctxKey = "X-Store-Name" CtxGroupId ctxKey = "X-Group-Id" CtxGroupName ctxKey = "X-Group-Name" CtxUserType ctxKey = "X-User-Type" CtxRawBody ctxKey = "X-Raw-Body" ) var callbackPrefixes = []string{ "/api/v3/express/", "/api/v3/other1/", "/api/v3/other2/", } type UserInfo struct { ID int64 Name string RawUID string Refresh string ClientIP string UserAgent string Type string ClientCode string SaleId string SaleName string SaleMobile string SaleProvince string StoreId string StoreName string GroupId string GroupName string RawBody string Valid bool } func GetUserInfo(ctx context.Context) UserInfo { rawUID, _ := ctx.Value(CtxUserId).(string) name, _ := ctx.Value(CtxUserName).(string) refresh, _ := ctx.Value(CtxRefresh).(string) clientIP, _ := ctx.Value(CtxClientIP).(string) userAgent, _ := ctx.Value(CtxUserAgent).(string) userType, _ := ctx.Value(CtxUserType).(string) clientCode, _ := ctx.Value(CtxClientCode).(string) saleId, _ := ctx.Value(CtxSaleId).(string) saleName, _ := ctx.Value(CtxSaleName).(string) saleMobile, _ := ctx.Value(CtxSaleMobile).(string) saleProvince, _ := ctx.Value(CtxSaleProvince).(string) storeId, _ := ctx.Value(CtxStoreId).(string) storeName, _ := ctx.Value(CtxStoreName).(string) groupId, _ := ctx.Value(CtxGroupId).(string) groupName, _ := ctx.Value(CtxGroupName).(string) rawBody, _ := ctx.Value(CtxRawBody).(string) info := UserInfo{ RawUID: rawUID, Name: name, Refresh: refresh, ClientIP: clientIP, UserAgent: userAgent, Type: userType, ClientCode: clientCode, SaleId: saleId, SaleName: saleName, SaleMobile: saleMobile, SaleProvince: saleProvince, StoreId: storeId, StoreName: storeName, GroupId: groupId, GroupName: groupName, RawBody: rawBody, } if rawUID == "" { return info } uid, err := strconv.ParseInt(rawUID, 10, 64) if err != nil { info.Valid = false return info } info.ID = uid info.Valid = true return info } func getRealClientIP(r *http.Request) string { xff := r.Header.Get("X-Forwarded-For") if xff != "" { return xff } xri := r.Header.Get("X-Real-Ip") if xri != "" { return xri } return r.RemoteAddr } // UserReadMiddleware /** 增加透传的方法 * 1、这里加上代码 * 2、UserClientInterceptor这个方法里也要写相应的代码对可以 */ func UserReadMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { newCtx := r.Context() body, _ := io.ReadAll(r.Body) newCtx = context.WithValue(newCtx, CtxRawBody, string(body)) newCtx = context.WithValue(newCtx, CtxUserId, r.Header.Get("X-User-Id")) newCtx = context.WithValue(newCtx, CtxUserName, r.Header.Get("X-User-Name")) newCtx = context.WithValue(newCtx, CtxRefresh, r.Header.Get("X-Refresh")) newCtx = context.WithValue(newCtx, CtxClientIP, getRealClientIP(r)) newCtx = context.WithValue(newCtx, CtxUserAgent, r.UserAgent()) newCtx = context.WithValue(newCtx, CtxUserType, r.Header.Get("X-User-Type")) newCtx = context.WithValue(newCtx, CtxClientCode, r.Header.Get("X-Client-Code")) newCtx = context.WithValue(newCtx, CtxSaleId, r.Header.Get("X-Sale-Id")) newCtx = context.WithValue(newCtx, CtxSaleName, r.Header.Get("X-Sale-Name")) newCtx = context.WithValue(newCtx, CtxSaleMobile, r.Header.Get("X-Sale-Mobile")) newCtx = context.WithValue(newCtx, CtxSaleProvince, r.Header.Get("X-Sale-Province")) newCtx = context.WithValue(newCtx, CtxStoreId, r.Header.Get("X-Store-Id")) newCtx = context.WithValue(newCtx, CtxStoreName, r.Header.Get("X-Store-Name")) newCtx = context.WithValue(newCtx, CtxGroupId, r.Header.Get("X-Group-Id")) newCtx = context.WithValue(newCtx, CtxGroupName, r.Header.Get("X-Group-Name")) next(w, r.WithContext(newCtx)) } } func isCallbackPath(path string) bool { for _, prefix := range callbackPrefixes { if strings.HasPrefix(path, prefix) { return true } } return false } func setMDIfNotEmpty(md metadata.MD, key, value string) { if value != utils.StringEmpty { md.Set(key, value) } } func UserClientInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { user := GetUserInfo(ctx) md := metadata.New(map[string]string{}) if user.Valid { md.Set("x-user-id", user.RawUID) md.Set("x-user-name", url.QueryEscape(user.Name)) } setMDIfNotEmpty(md, "x-raw-body", user.RawBody) setMDIfNotEmpty(md, "x-refresh", user.Refresh) setMDIfNotEmpty(md, "x-client-ip", user.ClientIP) if user.UserAgent != utils.StringEmpty { md.Set("x-user-agent", url.QueryEscape(user.UserAgent)) } setMDIfNotEmpty(md, "x-user-type", user.Type) setMDIfNotEmpty(md, "x-client-code", user.ClientCode) setMDIfNotEmpty(md, "x-sale-id", user.SaleId) if user.SaleName != utils.StringEmpty { md.Set("x-sale-name", url.QueryEscape(user.SaleName)) } setMDIfNotEmpty(md, "x-sale-mobile", user.SaleMobile) setMDIfNotEmpty(md, "x-sale-province", user.SaleProvince) setMDIfNotEmpty(md, "x-store-id", user.StoreId) if user.StoreName != utils.StringEmpty { md.Set("x-store-name", url.QueryEscape(user.StoreName)) } setMDIfNotEmpty(md, "x-group-id", user.GroupId) if user.GroupName != utils.StringEmpty { md.Set("x-group-name", url.QueryEscape(user.GroupName)) } ctx = metadata.NewOutgoingContext(ctx, md) return invoker(ctx, method, req, reply, cc, opts...) }